Änderungen von Dokument Prepare

Zuletzt geändert von Veronika Kocher am Freitag, 18 Sep. 2026 16:47

Von Version 1.11
bearbeitet von Veronika Kocher
am Freitag, 04 Sep. 2026 14:23
Änderungskommentar: Es gibt keinen Kommentar für diese Version
Auf Version 1.8
bearbeitet von Veronika Kocher
am Donnerstag, 03 Sep. 2026 10:09
Änderungskommentar: Es gibt keinen Kommentar für diese Version

Zusammenfassung

Details

Seiteneigenschaften
Inhalt
... ... @@ -462,11 +462,7 @@
462 462   <a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/Work%20%26%20Manage/" class="btn btn-default" style="background:#fff7f1;border-color:#e4cabc;color:#493a34;">Weiter zu Arbeiten &amp; Verwalten</a>
463 463   </section>
464 464  
465 -<!-- ARSN_TRAINING_WORKSHOPS_INCLUDE_V1_START -->
466 -{{include reference="Service Navigator.Art & Research Services Navigator.Code.TrainingWorkshopsBlock" author="target" /}}
467 -<!-- ARSN_TRAINING_WORKSHOPS_INCLUDE_V1_END -->
468 -
469 -<div style="margin:0 0 13px 0;">
465 + <div style="margin:0 0 13px 0;">
470 470   <div class="arsn-eyebrow" style="color:#8a4d36;margin-bottom:4px;">NÜTZLICHE MATERIALIEN</div>
471 471   <h3 style="font-size:22px;margin:0 0 4px 0;color:#35312d;">Praktische Ressourcen</h3>
472 472   </div>
... ... @@ -487,13 +487,12 @@
487 487  </div>
488 488  {{/html}}
489 489  
490 -{{html clean="false"}}
491 -<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_START -->
486 +\n\n
487 +\n\n{{html clean="false"}}
488 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_START -->
492 492  
493 -<style data-sn-service-navigator-master="1">
494 -/* =========================================================
495 - MASTER TYPOGRAPHY
496 - ========================================================= */
490 +<style data-sn-horizontal-box-harmonizer="7">
491 +/* ---------- Typography: never justify headings ---------- */
497 497  #xwikicontent h1,
498 498  #xwikicontent h2,
499 499  #xwikicontent h3,
... ... @@ -515,105 +515,88 @@
515 515   word-spacing:normal!important;
516 516  }
517 517  
518 -/* =========================================================
519 - COMING SOON / IN VORBEREITUNG
520 - ========================================================= */
521 -.sn-coming-soon-badge{
522 - display:inline-block;
523 - vertical-align:middle;
524 - margin-left:10px;
525 - padding:4px 8px;
526 - border-radius:14px;
527 - border:1px solid #efd9cc;
528 - background:#fff4ee;
529 - color:#8a4d36;
530 - font-size:11px;
531 - font-weight:700;
532 - letter-spacing:.055em;
533 - line-height:1.2;
534 - white-space:nowrap;
535 -}
536 -
537 -/* =========================================================
538 - NATIVE / DETAIL CALLOUT GEOMETRY
539 - Preserve existing backgrounds.
540 - ========================================================= */
541 -#xwikicontent .arsn-info,
542 -#xwikicontent .dmp-info,
543 -#xwikicontent .ido-info,
544 -#xwikicontent .pp-info,
545 -#xwikicontent .infomessage{
513 +/* ---------- Native XWiki semantic callouts ---------- */
514 +#xwikicontent .box.infomessage,
515 +#xwikicontent .infomessage,
516 +#xwikicontent .box.warningmessage,
517 +#xwikicontent .warningmessage,
518 +#xwikicontent .box.successmessage,
519 +#xwikicontent .successmessage,
520 +#xwikicontent .box.errormessage,
521 +#xwikicontent .errormessage,
522 +#xwikicontent [data-sn-callout-harmonized="1"]{
546 546   box-sizing:border-box!important;
547 - border-left:4px solid #21b6d7!important;
548 - border-radius:8px;
524 + border-radius:8px!important;
525 + border-top:1px solid rgba(0,0,0,.08)!important;
526 + border-right:1px solid rgba(0,0,0,.08)!important;
527 + border-bottom:1px solid rgba(0,0,0,.08)!important;
528 + border-left:4px solid var(--sn-callout-accent,#21b6d7)!important;
529 + padding:14px 16px!important;
549 549   text-align:left!important;
531 + text-justify:auto!important;
550 550   word-spacing:normal!important;
533 + box-shadow:none!important;
551 551  }
552 552  
553 -#xwikicontent .arsn-warn,
554 -#xwikicontent .dmp-warn,
555 -#xwikicontent .ido-warn,
556 -#xwikicontent .pp-warn,
557 -#xwikicontent .warn,
558 -#xwikicontent .warning,
559 -#xwikicontent .warningmessage,
536 +#xwikicontent .box.infomessage,
537 +#xwikicontent .infomessage{
538 + --sn-callout-accent:#21b6d7;
539 + background:#eaf7fb!important;
540 +}
541 +
542 +#xwikicontent .box.warningmessage,
543 +#xwikicontent .warningmessage{
544 + --sn-callout-accent:#f0aa00;
545 + background:#fff8e7!important;
546 +}
547 +
548 +#xwikicontent .box.successmessage,
549 +#xwikicontent .successmessage{
550 + --sn-callout-accent:#38b76a;
551 + background:#edf9f1!important;
552 +}
553 +
554 +#xwikicontent .box.errormessage,
560 560  #xwikicontent .errormessage{
561 - box-sizing:border-box!important;
562 - border-left:4px solid #e94b13!important;
563 - border-radius:8px;
564 - text-align:left!important;
565 - word-spacing:normal!important;
556 + --sn-callout-accent:#e94b13;
557 + background:#fff1ec!important;
566 566  }
567 567  
568 -[data-sn-master-equal-height],
569 -[data-sn-master-first-row]{
570 - box-sizing:border-box;
560 +#xwikicontent [data-sn-callout-harmonized="1"] > :first-child,
561 +#xwikicontent .infomessage > :first-child,
562 +#xwikicontent .warningmessage > :first-child,
563 +#xwikicontent .successmessage > :first-child,
564 +#xwikicontent .errormessage > :first-child{
565 + margin-top:0!important;
571 571  }
572 572  
573 -/* =========================================================
574 - FULL-WIDTH THREE-LINE NUMBER / TITLE / SUBTITLE BLOCKS
575 - ========================================================= */
576 -#xwikicontent .arsn-area-label[data-sn-three-line="1"]{
577 - display:grid!important;
578 - grid-template-columns:minmax(0,1fr)!important;
579 - grid-auto-rows:auto!important;
580 - width:100%!important;
581 - max-width:none!important;
582 - box-sizing:border-box!important;
583 - justify-items:start!important;
584 - align-items:start!important;
585 - gap:2px!important;
586 - text-align:left!important;
587 - text-align-last:left!important;
588 - text-justify:auto!important;
589 - word-spacing:normal!important;
590 - white-space:normal!important;
568 +#xwikicontent [data-sn-callout-harmonized="1"] > :last-child,
569 +#xwikicontent .infomessage > :last-child,
570 +#xwikicontent .warningmessage > :last-child,
571 +#xwikicontent .successmessage > :last-child,
572 +#xwikicontent .errormessage > :last-child{
573 + margin-bottom:0!important;
591 591  }
592 -#xwikicontent .arsn-area-label[data-sn-three-line="1"] > .arsn-area-number,
593 -#xwikicontent .arsn-area-label[data-sn-three-line="1"] > .sn-area-label-title,
594 -#xwikicontent .arsn-area-label[data-sn-three-line="1"] > .arsn-area-action{
595 - display:block!important;
596 - width:100%!important;
597 - margin:0!important;
598 - text-align:left!important;
599 - text-align-last:left!important;
600 - text-justify:auto!important;
601 - word-spacing:normal!important;
602 - white-space:normal!important;
575 +
576 +#xwikicontent [data-sn-equal-height-managed],
577 +#xwikicontent [data-sn-first-section-aligned],
578 +#xwikicontent [data-sn-first-content-aligned]{
579 + box-sizing:border-box;
603 603  }
604 604  </style>
605 605  
606 -<script data-sn-service-navigator-master="1">
583 +<script data-sn-horizontal-box-harmonizer="7">
607 607  (function(){
608 608   "use strict";
609 609  
610 - var PAGE_KIND="overview";
611 - var PLACEHOLDER=false;
612 - var PLACEHOLDER_LABEL="IN VORBEREITUNG";
613 -
614 614   var MOBILE_MAX=767;
615 615   var ROW_TOLERANCE=6;
589 + var MIN_W=150;
590 + var MIN_H=36;
591 + var MAX_PARENT_CHILDREN=18;
592 + var SEARCH_DEPTH=5;
616 616   var RESIZE_DEBOUNCE=220;
594 + var MIN_WIDTH_CHANGE=2;
617 617  
618 618   var root=
619 619   document.getElementById("xwikicontent")||
... ... @@ -623,114 +623,142 @@
623 623  
624 624   if(!root)return;
625 625  
626 - var managedHeight=new Set();
627 - var managedMargin=new Set();
628 - var originalHeight=new WeakMap();
629 - var originalMargin=new WeakMap();
604 + var heightManaged=new Set();
605 + var sectionManaged=new Set();
606 + var contentManaged=new Set();
630 630  
608 + var originalMinHeight=new WeakMap();
609 + var originalMarginTop=new WeakMap();
610 +
631 631   var resizeTimer=0;
632 - var running=false;
612 + var lastWidth=-1;
613 + var hasApplied=false;
614 + var applying=false;
633 633  
634 - var THEMES=[
635 - {
636 - name:"BLUE",
637 - accent:"#21b6d7",
638 - bg:"#eaf7fb",
639 - text:"#315d68",
640 - labels:[
641 - "HIER STARTEN",
642 - "ENTSCHEIDEN",
643 - "ÜBERPRÜFEN & ANPASSEN",
644 - "START HERE",
645 - "DECIDE",
646 - "REVIEW & ADAPT"
647 - ]
648 - },
649 - {
650 - name:"RED",
651 - accent:"#e94b13",
652 - bg:"#fff1ec",
653 - text:"#8a4d36",
654 - labels:[
655 - "PLANEN & ORGANISIEREN",
656 - "ORGANISIEREN & DOKUMENTIEREN",
657 - "PUBLIZIEREN & PRÄSENTIEREN",
658 - "PLAN & ORGANISE",
659 - "PLAN & ORGANIZE",
660 - "ORGANISE & DOCUMENT",
661 - "ORGANIZE & DOCUMENT",
662 - "PUBLISH & PRESENT"
663 - ]
664 - },
665 - {
666 - name:"YELLOW",
667 - accent:"#f0aa00",
668 - bg:"#fff8e7",
669 - text:"#785b17",
670 - labels:[
671 - "SCHÜTZEN & KLÄREN",
672 - "STANDARDISIEREN & IDENTIFIZIEREN",
673 - "ÖFFNEN, NACHNUTZEN & AUFFINDBAR MACHEN",
674 - "PROTECT & CLARIFY",
675 - "STANDARDISE & IDENTIFY",
676 - "STANDARDIZE & IDENTIFY",
677 - "OPEN, REUSE & MAKE FINDABLE"
678 - ]
679 - },
680 - {
681 - name:"GREEN",
682 - accent:"#38b76a",
683 - bg:"#edf9f1",
684 - text:"#3f7451",
685 - labels:[
686 - "INFRASTRUKTUR EINRICHTEN",
687 - "INFRASTRUKTUR & ZUSAMMENARBEIT EINRICHTEN",
688 - "SPEICHERN & ZUGRIFF STEUERN",
689 - "REPOSITORIUM, ERHALTEN & ÜBERGEBEN",
690 - "SET UP INFRASTRUCTURE",
691 - "SET UP INFRASTRUCTURE & COLLABORATION",
692 - "STORE & CONTROL ACCESS",
693 - "REPOSITORY, PRESERVE & HAND OVER"
694 - ]
616 + function num(v){
617 + var n=parseFloat(v);
618 + return Number.isFinite(n)?n:0;
619 + }
620 +
621 + function visible(el,minW,minH){
622 + if(!el||el.nodeType!==1)return false;
623 +
624 + var s=getComputedStyle(el);
625 +
626 + if(
627 + s.display==="none"||
628 + s.visibility==="hidden"||
629 + Number(s.opacity)===0
630 + ){
631 + return false;
695 695   }
696 - ];
697 697  
698 - function num(value){
699 - var n=parseFloat(value);
700 - return Number.isFinite(n)?n:0;
634 + var r=el.getBoundingClientRect();
635 +
636 + return (
637 + r.width>=(minW||1)&&
638 + r.height>=(minH||1)
639 + );
701 701   }
702 702  
703 - function norm(value){
704 - return String(value||"")
642 + function normalizeText(text){
643 + return String(text||"")
705 705   .replace(/\s+/g," ")
706 706   .trim()
707 707   .toUpperCase();
708 708   }
709 709  
710 - function visible(el){
711 - if(!el||el.nodeType!==1)return false;
649 + function excluded(el){
650 + return (
651 + !el.matches||
652 + el.matches(
653 + "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]"
654 + )
655 + );
656 + }
712 712  
713 - var style=getComputedStyle(el);
714 - var rect=el.getBoundingClientRect();
658 + /* ---------- Custom coloured callouts ---------- */
715 715  
660 + function nativeCallout(el){
661 + var c=
662 + typeof el.className==="string"
663 + ? el.className.toLowerCase()
664 + : "";
665 +
716 716   return (
717 - style.display!=="none"&&
718 - style.visibility!=="hidden"&&
719 - rect.width>20&&
720 - rect.height>4
667 + /(^|\s)(infomessage|warningmessage|successmessage|errormessage)(\s|$)/.test(c)
721 721   );
722 722   }
723 723  
724 - function saveStyle(el,map,property){
671 + function customCallout(el){
672 + if(!visible(el,220,42)||excluded(el))return false;
673 +
674 + var r=el.getBoundingClientRect();
675 +
676 + if(r.height>520)return false;
677 +
678 + var s=getComputedStyle(el);
679 +
680 + var bg=
681 + s.backgroundColor&&
682 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&&
683 + s.backgroundColor!=="transparent"&&
684 + s.backgroundColor!=="rgb(255, 255, 255)";
685 +
686 + var left=
687 + num(s.borderLeftWidth);
688 +
689 + return (
690 + bg&&
691 + left>=2
692 + );
693 + }
694 +
695 + function harmoniseCustomCallouts(){
696 + Array.from(
697 + root.querySelectorAll(
698 + "div,aside,section"
699 + )
700 + ).forEach(function(el){
701 + if(nativeCallout(el))return;
702 + if(!customCallout(el))return;
703 +
704 + var s=getComputedStyle(el);
705 +
706 + el.setAttribute(
707 + "data-sn-callout-harmonized",
708 + "1"
709 + );
710 +
711 + if(
712 + s.borderLeftColor
713 + ){
714 + el.style.setProperty(
715 + "--sn-callout-accent",
716 + s.borderLeftColor
717 + );
718 + }
719 + });
720 + }
721 +
722 + /* ---------- Restore only values V7 itself changed ---------- */
723 +
724 + function saveOriginal(el,map,property){
725 725   if(map.has(el))return;
726 726  
727 727   map.set(el,{
728 - value:el.style.getPropertyValue(property),
729 - priority:el.style.getPropertyPriority(property)
728 + value:
729 + el.style.getPropertyValue(
730 + property
731 + ),
732 + priority:
733 + el.style.getPropertyPriority(
734 + property
735 + )
730 730   });
731 731   }
732 732  
733 - function restoreStyle(el,map,property){
739 + function restoreOriginal(el,map,property){
734 734   var original=map.get(el);
735 735  
736 736   if(original&&original.value){
... ... @@ -740,1069 +740,770 @@
740 740   original.priority||""
741 741   );
742 742   }else{
743 - el.style.removeProperty(property);
749 + el.style.removeProperty(
750 + property
751 + );
744 744   }
745 745   }
746 746  
747 747   function resetRuntime(){
748 - managedHeight.forEach(function(el){
749 - restoreStyle(
756 + heightManaged.forEach(function(el){
757 + restoreOriginal(
750 750   el,
751 - originalHeight,
759 + originalMinHeight,
752 752   "min-height"
753 753   );
762 +
754 754   el.removeAttribute(
755 - "data-sn-master-equal-height"
764 + "data-sn-equal-height-managed"
756 756   );
757 757   });
758 758  
759 - managedMargin.forEach(function(el){
760 - restoreStyle(
768 + sectionManaged.forEach(function(el){
769 + restoreOriginal(
761 761   el,
762 - originalMargin,
771 + originalMarginTop,
763 763   "margin-top"
764 764   );
774 +
765 765   el.removeAttribute(
766 - "data-sn-master-first-row"
776 + "data-sn-first-section-aligned"
767 767   );
768 768   });
769 769  
770 - managedHeight.clear();
771 - managedMargin.clear();
772 - }
780 + contentManaged.forEach(function(el){
781 + restoreOriginal(
782 + el,
783 + originalMarginTop,
784 + "margin-top"
785 + );
773 773  
774 - function themeFor(text){
775 - var value=norm(text);
787 + el.removeAttribute(
788 + "data-sn-first-content-aligned"
789 + );
790 + });
776 776  
777 - for(var i=0;i<THEMES.length;i++){
778 - for(var j=0;j<THEMES[i].labels.length;j++){
779 - var label=THEMES[i].labels[j];
780 -
781 - if(
782 - value===label||
783 - value.indexOf(label+" ")===0||
784 - value.indexOf(label+" -")===0||
785 - value.indexOf(label+" ·")===0
786 - ){
787 - return THEMES[i];
788 - }
789 - }
790 - }
791 -
792 - return null;
792 + heightManaged.clear();
793 + sectionManaged.clear();
794 + contentManaged.clear();
793 793   }
794 794  
795 - /* =======================================================
796 - BORDERLESS FILLED RED/ORANGE CTA BUTTONS
797 - ======================================================= */
797 + /* ---------- Card detection ---------- */
798 798  
799 - function colourDistance(a,b){
800 - return Math.sqrt(
801 - Math.pow(a[0]-b[0],2)+
802 - Math.pow(a[1]-b[1],2)+
803 - Math.pow(a[2]-b[2],2)
804 - );
799 + function namedLikeBox(el){
800 + var c=
801 + typeof el.className==="string"
802 + ? el.className
803 + : "";
804 +
805 + return /(^|[\s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([\s_-]|$)/i.test(c);
805 805   }
806 806  
807 - function makeFilledRedOrangeCTAsBorderless(){
808 - var RED_ORANGE=[233,75,19];
808 + function boxLike(el){
809 + if(
810 + !visible(el,MIN_W,MIN_H)||
811 + excluded(el)
812 + ){
813 + return false;
814 + }
809 809  
810 - Array.from(
811 - root.querySelectorAll(
812 - 'a,button,[role="button"],input[type="submit"],input[type="button"]'
813 - )
814 - ).forEach(function(el){
815 - if(!visible(el))return;
816 + var s=getComputedStyle(el);
817 + var r=el.getBoundingClientRect();
816 816  
817 - var style=getComputedStyle(el);
818 - var rgb=parseRGB(style.backgroundColor);
819 + var border=
820 + num(s.borderTopWidth)+
821 + num(s.borderRightWidth)+
822 + num(s.borderBottomWidth)+
823 + num(s.borderLeftWidth);
819 819  
820 - if(!rgb)return;
825 + var radius=Math.max(
826 + num(s.borderTopLeftRadius),
827 + num(s.borderTopRightRadius),
828 + num(s.borderBottomLeftRadius),
829 + num(s.borderBottomRightRadius)
830 + );
821 821  
822 - if(
823 - colourDistance(
824 - rgb,
825 - RED_ORANGE
826 - )>55
827 - ){
828 - return;
829 - }
832 + var bg=
833 + s.backgroundColor&&
834 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&&
835 + s.backgroundColor!=="transparent";
830 830  
831 - var rect=el.getBoundingClientRect();
837 + var shadow=
838 + s.boxShadow&&
839 + s.boxShadow!=="none";
832 832  
833 - if(
834 - rect.width<80||
835 - rect.height<24
836 - ){
837 - return;
838 - }
841 + return (
842 + namedLikeBox(el)||
843 + border>=1||
844 + (bg&&radius>=3)||
845 + (shadow&&r.width>=180)
846 + );
847 + }
839 839  
840 - el.style.setProperty(
841 - "border",
842 - "none",
843 - "important"
844 - );
849 + function pickTarget(child){
850 + if(!visible(child,MIN_W,MIN_H))return null;
845 845  
846 - el.style.setProperty(
847 - "border-left",
848 - "none",
849 - "important"
850 - );
852 + if(boxLike(child))return child;
851 851  
852 - el.style.setProperty(
853 - "border-top",
854 - "none",
855 - "important"
856 - );
854 + var cr=child.getBoundingClientRect();
855 + var q=[];
857 857  
858 - el.style.setProperty(
859 - "border-right",
860 - "none",
861 - "important"
862 - );
863 -
864 - el.style.setProperty(
865 - "border-bottom",
866 - "none",
867 - "important"
868 - );
869 -
870 - el.style.setProperty(
871 - "box-shadow",
872 - "none",
873 - "important"
874 - );
857 + Array.from(child.children||[]).forEach(function(el){
858 + q.push({el:el,depth:1});
875 875   });
876 - }
877 877  
878 - /* =======================================================
879 - FULL-WIDTH THREE-LINE AREA LABELS
880 - ======================================================= */
861 + var best=null;
862 + var bestScore=-Infinity;
881 881  
882 - function compactText(value){
883 - return String(value||"")
884 - .replace(/\s+/g," ")
885 - .trim();
886 - }
864 + while(q.length){
865 + var item=q.shift();
866 + var el=item.el;
887 887  
888 - function makeThreeLineAreaLabels(){
889 - Array.from(
890 - root.querySelectorAll(
891 - ".arsn-area-label"
892 - )
893 - ).forEach(function(label){
894 - if(
895 - label.getAttribute(
896 - "data-sn-three-line"
897 - )==="1"
898 - ){
899 - return;
900 - }
868 + if(!visible(el,MIN_W,MIN_H))continue;
901 901  
902 - var number=
903 - label.querySelector(
904 - ":scope > .arsn-area-number"
905 - );
870 + var r=el.getBoundingClientRect();
906 906  
907 - var action=
908 - label.querySelector(
909 - ":scope > .arsn-area-action"
910 - );
911 -
912 912   if(
913 - !number||
914 - !action
873 + r.width>=cr.width*.68&&
874 + boxLike(el)
915 915   ){
916 - return;
917 - }
876 + var widthFit=
877 + 1-Math.min(
878 + 1,
879 + Math.abs(cr.width-r.width)/
880 + Math.max(1,cr.width)
881 + );
918 918  
919 - var clone=
920 - label.cloneNode(true);
883 + var topFit=
884 + 1-Math.min(
885 + 1,
886 + Math.abs(cr.top-r.top)/100
887 + );
921 921  
922 - var cloneNumber=
923 - clone.querySelector(
924 - ":scope > .arsn-area-number"
925 - );
889 + var score=
890 + widthFit*6+
891 + topFit*3+
892 + Math.min(r.height,900)/450+
893 + Math.min(r.width*r.height,900000)/900000;
926 926  
927 - var cloneAction=
928 - clone.querySelector(
929 - ":scope > .arsn-area-action"
930 - );
931 -
932 - if(cloneNumber){
933 - cloneNumber.remove();
895 + if(score>bestScore){
896 + best=el;
897 + bestScore=score;
898 + }
934 934   }
935 935  
936 - if(cloneAction){
937 - cloneAction.remove();
901 + if(item.depth<SEARCH_DEPTH){
902 + Array.from(el.children||[]).forEach(function(next){
903 + q.push({
904 + el:next,
905 + depth:item.depth+1
906 + });
907 + });
938 938   }
909 + }
939 939  
940 - var titleText=
941 - compactText(
942 - clone.textContent
943 - );
911 + return best;
912 + }
944 944  
945 - if(!titleText){
946 - return;
947 - }
914 + function groupRows(entries){
915 + var groups=[];
948 948  
949 - var numberNode=
950 - number.cloneNode(true);
951 -
952 - var actionNode=
953 - action.cloneNode(true);
954 -
955 - var titleNode=
956 - document.createElement(
957 - "span"
917 + entries
918 + .slice()
919 + .sort(function(a,b){
920 + return (
921 + a.rect.top-b.rect.top||
922 + a.rect.left-b.rect.left
958 958   );
924 + })
925 + .forEach(function(entry){
926 + var group=null;
959 959  
960 - titleNode.className=
961 - "sn-area-label-title";
928 + for(var i=0;i<groups.length;i++){
929 + if(
930 + Math.abs(
931 + groups[i].top-
932 + entry.rect.top
933 + )<=ROW_TOLERANCE
934 + ){
935 + group=groups[i];
936 + break;
937 + }
938 + }
962 962  
963 - titleNode.textContent=
964 - titleText;
940 + if(!group){
941 + group={
942 + top:entry.rect.top,
943 + entries:[]
944 + };
945 + groups.push(group);
946 + }
965 965  
966 - while(label.firstChild){
967 - label.removeChild(
968 - label.firstChild
969 - );
970 - }
948 + group.entries.push(entry);
949 + });
971 971  
972 - label.appendChild(
973 - numberNode
974 - );
975 -
976 - label.appendChild(
977 - titleNode
978 - );
979 -
980 - label.appendChild(
981 - actionNode
982 - );
983 -
984 - label.setAttribute(
985 - "data-sn-three-line",
986 - "1"
987 - );
988 -
989 - var head=
990 - label.closest(
991 - ".arsn-area-head"
992 - );
993 -
994 - if(head){
995 - head.style.setProperty(
996 - "width",
997 - "100%",
998 - "important"
999 - );
1000 -
1001 - head.style.setProperty(
1002 - "max-width",
1003 - "100%",
1004 - "important"
1005 - );
1006 -
1007 - head.style.setProperty(
1008 - "box-sizing",
1009 - "border-box",
1010 - "important"
1011 - );
1012 - }
1013 - });
951 + return groups;
1014 1014   }
1015 1015  
1016 - /* =======================================================
1017 - PLACEHOLDER BADGE
1018 - ======================================================= */
954 + function validRow(group){
955 + if(group.entries.length<2)return false;
1019 1019  
1020 - function applyPlaceholderBadge(){
1021 - if(!PLACEHOLDER)return;
957 + var lefts=
958 + group.entries
959 + .map(function(e){return e.rect.left;})
960 + .sort(function(a,b){return a-b;});
1022 1022  
1023 1023   if(
1024 - document.querySelector(
1025 - ".sn-coming-soon-badge"
1026 - )
963 + lefts[lefts.length-1]-
964 + lefts[0]<
965 + 80
1027 1027   ){
1028 - return;
967 + return false;
1029 1029   }
1030 1030  
1031 - var title=
1032 - document.querySelector(
1033 - "#document-title"
1034 - )||
1035 - document.querySelector(
1036 - "h1"
1037 - );
970 + var widths=
971 + group.entries
972 + .map(function(e){return e.rect.width;})
973 + .filter(function(w){return w>0;});
1038 1038  
1039 - if(!title)return;
975 + if(widths.length<2)return false;
1040 1040  
1041 - var badge=
1042 - document.createElement(
1043 - "span"
1044 - );
977 + var minW=
978 + Math.min.apply(Math,widths);
1045 1045  
1046 - badge.className=
1047 - "sn-coming-soon-badge";
980 + var maxW=
981 + Math.max.apply(Math,widths);
1048 1048  
1049 - badge.textContent=
1050 - PLACEHOLDER_LABEL;
1051 -
1052 - badge.setAttribute(
1053 - "aria-label",
1054 - PLACEHOLDER_LABEL
983 + return (
984 + maxW/
985 + Math.max(1,minW)<=
986 + 1.9
1055 1055   );
988 + }
1056 1056  
1057 - title.appendChild(
1058 - badge
990 + /* ---------- Known ARSN first section bars ---------- */
991 +
992 + function knownBar(el){
993 + var text=
994 + normalizeText(
995 + el.textContent
996 + );
997 +
998 + return (
999 + text==="HIER STARTEN"||
1000 + text==="ORGANISIEREN & DOKUMENTIEREN"||
1001 + text==="ENTSCHEIDEN"||
1002 + text==="START HERE"||
1003 + text==="GET STARTED"||
1004 + text==="ORGANISE & DOCUMENT"||
1005 + text==="ORGANIZE & DOCUMENT"||
1006 + text==="DECIDE"
1059 1059   );
1060 1060   }
1061 1061  
1062 - /* =======================================================
1063 - DETAIL PAGE OWN-ACCENT PROPAGATION
1064 - ======================================================= */
1010 + function findKnownBar(card){
1011 + var cardRect=
1012 + card.getBoundingClientRect();
1065 1065  
1066 - function parseRGB(value){
1067 - var match=String(value||"").match(
1068 - /rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i
1069 - );
1014 + var rows=
1015 + Array.from(
1016 + card.querySelectorAll(
1017 + "div,p,span,strong,h3,h4,h5,h6"
1018 + )
1019 + )
1020 + .filter(function(el){
1021 + if(!visible(el,20,6))return false;
1022 + if(!knownBar(el))return false;
1070 1070  
1071 - if(!match)return null;
1024 + var r=el.getBoundingClientRect();
1072 1072  
1073 - return [
1074 - Number(match[1]),
1075 - Number(match[2]),
1076 - Number(match[3])
1077 - ];
1078 - }
1026 + var rel=
1027 + r.top-
1028 + cardRect.top;
1079 1079  
1080 - function distance(a,b){
1081 - return Math.sqrt(
1082 - Math.pow(a[0]-b[0],2)+
1083 - Math.pow(a[1]-b[1],2)+
1084 - Math.pow(a[2]-b[2],2)
1085 - );
1030 + return (
1031 + rel>=35&&
1032 + rel<=
1033 + cardRect.height*.75
1034 + );
1035 + })
1036 + .sort(function(a,b){
1037 + return (
1038 + a.getBoundingClientRect().top-
1039 + b.getBoundingClientRect().top
1040 + );
1041 + });
1042 +
1043 + return rows[0]||null;
1086 1086   }
1087 1087  
1088 - function paletteMatch(cssColor){
1089 - var rgb=parseRGB(cssColor);
1046 + function alignKnownBars(cards){
1047 + var rows=
1048 + cards.map(function(card){
1049 + var bar=
1050 + findKnownBar(card);
1090 1090  
1091 - if(!rgb)return null;
1052 + if(!bar)return null;
1092 1092  
1093 - var palette=[
1094 - {hex:"#21b6d7",rgb:[33,182,215]},
1095 - {hex:"#e94b13",rgb:[233,75,19]},
1096 - {hex:"#f0aa00",rgb:[240,170,0]},
1097 - {hex:"#38b76a",rgb:[56,183,106]}
1098 - ];
1054 + var cr=
1055 + card.getBoundingClientRect();
1099 1099  
1100 - var best=null;
1101 - var bestDistance=Infinity;
1057 + var br=
1058 + bar.getBoundingClientRect();
1102 1102  
1103 - palette.forEach(function(item){
1104 - var d=distance(rgb,item.rgb);
1060 + return {
1061 + bar:bar,
1062 + relativeTop:
1063 + br.top-
1064 + cr.top
1065 + };
1066 + });
1105 1105  
1106 - if(d<bestDistance){
1107 - best=item;
1108 - bestDistance=d;
1109 - }
1110 - });
1068 + if(
1069 + rows.some(function(row){
1070 + return !row;
1071 + })
1072 + ){
1073 + return false;
1074 + }
1111 1111  
1112 - return bestDistance<=30
1113 - ?best
1114 - :null;
1115 - }
1076 + var target=
1077 + Math.max.apply(
1078 + Math,
1079 + rows.map(function(row){
1080 + return row.relativeTop;
1081 + })
1082 + );
1116 1116  
1117 - function propagateDetailAccents(){
1118 - if(PAGE_KIND!=="detail")return;
1084 + rows.forEach(function(row){
1085 + var delta=
1086 + target-
1087 + row.relativeTop;
1119 1119  
1120 - Array.from(
1121 - root.querySelectorAll(
1122 - ".arsn-call,.dmp-call,.ido-call,.pp-call,"+
1123 - ".arsn-source,.dmp-source,.ido-source,.pp-source"
1124 - )
1125 - ).forEach(function(el){
1126 - if(!visible(el))return;
1089 + if(delta<=1)return;
1127 1127  
1128 - var style=getComputedStyle(el);
1091 + saveOriginal(
1092 + row.bar,
1093 + originalMarginTop,
1094 + "margin-top"
1095 + );
1129 1129  
1130 - if(
1131 - num(style.borderTopWidth)>=2
1132 - ){
1133 - var match=
1134 - paletteMatch(
1135 - style.borderTopColor
1136 - );
1097 + var current=
1098 + num(
1099 + getComputedStyle(
1100 + row.bar
1101 + ).marginTop
1102 + );
1137 1137  
1138 - if(match){
1139 - el.style.setProperty(
1140 - "border-left",
1141 - "4px solid "+match.hex,
1142 - "important"
1143 - );
1144 - }
1145 - }
1146 - });
1104 + row.bar.style.setProperty(
1105 + "margin-top",
1106 + (
1107 + current+
1108 + delta
1109 + )+"px"
1110 + );
1147 1147  
1148 - // Warning families: explicit safety override.
1149 - Array.from(
1150 - root.querySelectorAll(
1151 - ".arsn-warn,.dmp-warn,.ido-warn,.pp-warn,"+
1152 - ".warn,.warning,.warningmessage,.errormessage"
1153 - )
1154 - ).forEach(function(el){
1155 - if(!visible(el))return;
1156 -
1157 - el.style.setProperty(
1158 - "border-left",
1159 - "4px solid #e94b13",
1160 - "important"
1112 + row.bar.setAttribute(
1113 + "data-sn-first-section-aligned",
1114 + "7"
1161 1161   );
1162 - });
1163 1163  
1164 - // Info families: explicit orientation override.
1165 - Array.from(
1166 - root.querySelectorAll(
1167 - ".arsn-info,.dmp-info,.ido-info,.pp-info,.infomessage"
1168 - )
1169 - ).forEach(function(el){
1170 - if(!visible(el))return;
1171 -
1172 - el.style.setProperty(
1173 - "border-left",
1174 - "4px solid #21b6d7",
1175 - "important"
1117 + sectionManaged.add(
1118 + row.bar
1176 1176   );
1177 1177   });
1121 +
1122 + return true;
1178 1178   }
1179 1179  
1180 - /* =======================================================
1181 - OVERVIEW SEMANTIC THEME PALETTE
1182 - ======================================================= */
1125 + /* ---------- Generic first content after heading ---------- */
1183 1183  
1184 - function smallestThemeHeaders(){
1185 - return Array.from(
1186 - root.querySelectorAll(
1187 - "div,span,p,strong,h3,h4,h5,h6"
1127 + function heading(card){
1128 + var cr=
1129 + card.getBoundingClientRect();
1130 +
1131 + var rows=
1132 + Array.from(
1133 + card.querySelectorAll(
1134 + "h1,h2,h3,h4,h5,h6,.box-title,[role=heading]"
1135 + )
1188 1188   )
1189 - ).filter(function(el){
1190 - if(!visible(el))return false;
1191 - if(!themeFor(el.textContent))return false;
1137 + .filter(function(el){
1138 + if(!visible(el,20,8))return false;
1192 1192  
1193 - return !Array.from(
1194 - el.children||[]
1195 - ).some(function(child){
1196 - return !!themeFor(
1197 - child.textContent
1140 + var r=el.getBoundingClientRect();
1141 +
1142 + var rel=
1143 + r.top-
1144 + cr.top;
1145 +
1146 + return (
1147 + rel>=0&&
1148 + rel<=
1149 + Math.min(
1150 + 160,
1151 + cr.height*.45
1152 + )
1198 1198   );
1154 + })
1155 + .sort(function(a,b){
1156 + return (
1157 + a.getBoundingClientRect().top-
1158 + b.getBoundingClientRect().top
1159 + );
1199 1199   });
1200 - });
1161 +
1162 + return rows[0]||null;
1201 1201   }
1202 1202  
1203 - function findOverviewCard(header){
1204 - var node=header.parentElement;
1205 - var candidates=[];
1165 + function firstContent(card,h){
1166 + if(!h)return null;
1206 1206  
1207 - while(node&&node!==root){
1208 - var rect=node.getBoundingClientRect();
1209 - var style=getComputedStyle(node);
1168 + var cr=
1169 + card.getBoundingClientRect();
1210 1210  
1211 - var border=
1212 - num(style.borderTopWidth)+
1213 - num(style.borderRightWidth)+
1214 - num(style.borderBottomWidth)+
1215 - num(style.borderLeftWidth);
1171 + var hr=
1172 + h.getBoundingClientRect();
1216 1216  
1217 - if(
1218 - rect.width>=220&&
1219 - rect.width<=800&&
1220 - rect.height>=120&&
1221 - border>=1
1222 - ){
1223 - candidates.push(node);
1224 - }
1174 + var rows=
1175 + Array.from(
1176 + card.querySelectorAll(
1177 + "p,div,ul,ol,dl,blockquote"
1178 + )
1179 + )
1180 + .filter(function(el){
1181 + if(
1182 + el===h||
1183 + h.contains(el)||
1184 + el.contains(h)
1185 + ){
1186 + return false;
1187 + }
1225 1225  
1226 - node=node.parentElement;
1227 - }
1189 + if(!visible(el,30,8))return false;
1228 1228  
1229 - if(!candidates.length)return null;
1191 + var text=
1192 + String(el.textContent||"")
1193 + .replace(/\s+/g," ")
1194 + .trim();
1230 1230  
1231 - candidates.sort(function(a,b){
1232 - return (
1233 - b.getBoundingClientRect().height-
1234 - a.getBoundingClientRect().height
1235 - );
1236 - });
1196 + if(text.length<3)return false;
1237 1237  
1238 - return candidates[0];
1239 - }
1198 + var r=el.getBoundingClientRect();
1240 1240  
1241 - function rowCandidates(link,card){
1242 - var result=[];
1243 - var cardRect=
1244 - card.getBoundingClientRect();
1200 + if(
1201 + r.top<
1202 + hr.bottom-1
1203 + ){
1204 + return false;
1205 + }
1245 1245  
1246 - var node=link;
1207 + if(
1208 + r.top-cr.top>
1209 + Math.min(
1210 + 280,
1211 + cr.height*.65
1212 + )
1213 + ){
1214 + return false;
1215 + }
1247 1247  
1248 - while(node&&node!==card){
1249 - if(visible(node)){
1250 - var rect=
1251 - node.getBoundingClientRect();
1252 -
1253 1253   if(
1254 - rect.height<=105&&
1255 - rect.width>=
1256 - cardRect.width*.50&&
1257 - rect.width<=
1258 - cardRect.width*1.03
1218 + r.height>
1219 + cr.height*.58
1259 1259   ){
1260 - result.push(node);
1221 + return false;
1261 1261   }
1262 - }
1263 1263  
1264 - node=node.parentElement;
1265 - }
1224 + return true;
1225 + })
1226 + .sort(function(a,b){
1227 + var ar=
1228 + a.getBoundingClientRect();
1266 1266  
1267 - return result;
1268 - }
1230 + var br=
1231 + b.getBoundingClientRect();
1269 1269  
1270 - function chooseOuterRow(
1271 - candidates,
1272 - link
1273 - ){
1274 - if(!candidates.length){
1275 - return link;
1276 - }
1277 -
1278 - var bordered=
1279 - candidates.filter(function(el){
1280 1280   return (
1281 - num(
1282 - getComputedStyle(el)
1283 - .borderLeftWidth
1284 - )>=1
1234 + ar.top-br.top||
1235 + ar.height-br.height
1285 1285   );
1286 1286   });
1287 1287  
1288 - var pool=
1289 - bordered.length
1290 - ?bordered
1291 - :candidates;
1239 + return rows[0]||null;
1240 + }
1292 1292  
1293 - pool.sort(function(a,b){
1294 - var ar=
1295 - a.getBoundingClientRect();
1242 + function alignGeneric(cards){
1243 + var rows=
1244 + cards.map(function(card){
1245 + var h=
1246 + heading(card);
1296 1296  
1297 - var br=
1298 - b.getBoundingClientRect();
1248 + var c=
1249 + firstContent(
1250 + card,
1251 + h
1252 + );
1299 1299  
1300 - return (
1301 - ar.left-br.left||
1302 - br.width-ar.width
1303 - );
1304 - });
1254 + if(!h||!c)return null;
1305 1305  
1306 - return pool[0]||link;
1307 - }
1256 + var cr=
1257 + card.getBoundingClientRect();
1308 1308  
1309 - function applyOverviewPalette(){
1310 - if(PAGE_KIND!=="overview"){
1311 - return [];
1259 + var rr=
1260 + c.getBoundingClientRect();
1261 +
1262 + return {
1263 + content:c,
1264 + relativeTop:
1265 + rr.top-cr.top
1266 + };
1267 + });
1268 +
1269 + if(
1270 + rows.some(function(row){
1271 + return !row;
1272 + })
1273 + ){
1274 + return false;
1312 1312   }
1313 1313  
1314 - var headers=
1315 - smallestThemeHeaders()
1316 - .map(function(el){
1317 - return {
1318 - el:el,
1319 - theme:
1320 - themeFor(
1321 - el.textContent
1322 - ),
1323 - card:
1324 - findOverviewCard(
1325 - el
1326 - )
1327 - };
1277 + var target=
1278 + Math.max.apply(
1279 + Math,
1280 + rows.map(function(row){
1281 + return row.relativeTop;
1328 1328   })
1329 - .filter(function(row){
1330 - return !!row.card;
1331 - });
1283 + );
1332 1332  
1333 - var unique=[];
1334 - var seenHeaders=new Set();
1285 + rows.forEach(function(row){
1286 + var delta=
1287 + target-
1288 + row.relativeTop;
1335 1335  
1336 - headers.forEach(function(row){
1337 - var key=
1338 - row.theme.name+
1339 - "|"+
1340 - Math.round(
1341 - row.card
1342 - .getBoundingClientRect()
1343 - .left
1344 - )+
1345 - "|"+
1346 - Math.round(
1347 - row.el
1348 - .getBoundingClientRect()
1349 - .top
1350 - );
1290 + if(delta<=1)return;
1351 1351  
1352 - if(!seenHeaders.has(key)){
1353 - seenHeaders.add(key);
1354 - unique.push(row);
1355 - }
1356 - });
1357 -
1358 - unique.forEach(function(row){
1359 - var headerRect=
1360 - row.el
1361 - .getBoundingClientRect();
1362 -
1363 - row.el.style.setProperty(
1364 - "background",
1365 - row.theme.bg,
1366 - "important"
1292 + saveOriginal(
1293 + row.content,
1294 + originalMarginTop,
1295 + "margin-top"
1367 1367   );
1368 1368  
1369 - row.el.style.setProperty(
1370 - "color",
1371 - row.theme.text,
1372 - "important"
1373 - );
1298 + var current=
1299 + num(
1300 + getComputedStyle(
1301 + row.content
1302 + ).marginTop
1303 + );
1374 1374  
1375 - row.el.style.setProperty(
1376 - "text-align",
1377 - "left",
1378 - "important"
1305 + row.content.style.setProperty(
1306 + "margin-top",
1307 + (
1308 + current+
1309 + delta
1310 + )+"px"
1379 1379   );
1380 1380  
1381 - row.el.style.setProperty(
1382 - "word-spacing",
1383 - "normal",
1384 - "important"
1313 + row.content.setAttribute(
1314 + "data-sn-first-content-aligned",
1315 + "7"
1385 1385   );
1386 1386  
1387 - var later=
1388 - unique
1389 - .filter(function(other){
1390 - return (
1391 - other.card===row.card&&
1392 - other.el
1393 - .getBoundingClientRect()
1394 - .top>
1395 - headerRect.top+2
1396 - );
1397 - })
1398 - .sort(function(a,b){
1399 - return (
1400 - a.el
1401 - .getBoundingClientRect()
1402 - .top-
1403 - b.el
1404 - .getBoundingClientRect()
1405 - .top
1406 - );
1407 - });
1408 -
1409 - var stopTop=
1410 - later.length
1411 - ?later[0].el
1412 - .getBoundingClientRect()
1413 - .top
1414 - :Infinity;
1415 -
1416 - Array.from(
1417 - row.card.querySelectorAll("a")
1418 - ).forEach(function(link){
1419 - if(!visible(link))return;
1420 -
1421 - var rect=
1422 - link.getBoundingClientRect();
1423 -
1424 - if(
1425 - rect.top<=
1426 - headerRect.bottom-2||
1427 - rect.top>=
1428 - stopTop-2
1429 - ){
1430 - return;
1431 - }
1432 -
1433 - var candidates=
1434 - rowCandidates(
1435 - link,
1436 - row.card
1437 - );
1438 -
1439 - var target=
1440 - chooseOuterRow(
1441 - candidates,
1442 - link
1443 - );
1444 -
1445 - candidates.forEach(function(el){
1446 - el.style.setProperty(
1447 - "border-left",
1448 - "0 solid transparent",
1449 - "important"
1450 - );
1451 - });
1452 -
1453 - target.style.setProperty(
1454 - "border-left",
1455 - "3px solid "+
1456 - row.theme.accent,
1457 - "important"
1458 - );
1459 -
1460 - target.style.setProperty(
1461 - "box-sizing",
1462 - "border-box",
1463 - "important"
1464 - );
1465 - });
1318 + contentManaged.add(
1319 + row.content
1320 + );
1466 1466   });
1467 1467  
1468 - return unique;
1323 + return true;
1469 1469   }
1470 1470  
1471 - /* =======================================================
1472 - OVERVIEW CARD HEIGHT + FIRST THEMATIC ROW
1473 - ======================================================= */
1326 + function applyRow(group){
1327 + if(!validRow(group))return false;
1474 1474  
1475 - function alignOverviewCards(headers){
1476 - if(
1477 - PAGE_KIND!=="overview"||
1478 - window.innerWidth<=MOBILE_MAX
1479 - ){
1480 - return;
1481 - }
1482 -
1483 1483   var cards=[];
1484 1484   var seen=new Set();
1485 1485  
1486 - headers.forEach(function(row){
1487 - if(!seen.has(row.card)){
1488 - seen.add(row.card);
1489 - cards.push(row.card);
1332 + group.entries.forEach(function(entry){
1333 + if(!seen.has(entry.target)){
1334 + seen.add(entry.target);
1335 + cards.push(entry.target);
1490 1490   }
1491 1491   });
1492 1492  
1493 - if(cards.length<2){
1494 - return;
1339 + if(cards.length<2)return false;
1340 +
1341 + if(
1342 + !alignKnownBars(cards)
1343 + ){
1344 + alignGeneric(cards);
1495 1495   }
1496 1496  
1497 - // Group cards by actual top position.
1498 - var groups=[];
1347 + var maxHeight=0;
1499 1499  
1500 1500   cards.forEach(function(card){
1501 - var top=
1502 - card.getBoundingClientRect().top;
1503 -
1504 - var group=null;
1505 -
1506 - for(var i=0;i<groups.length;i++){
1507 - if(
1508 - Math.abs(
1509 - groups[i].top-top
1510 - )<=ROW_TOLERANCE
1511 - ){
1512 - group=groups[i];
1513 - break;
1514 - }
1515 - }
1516 -
1517 - if(!group){
1518 - group={
1519 - top:top,
1520 - cards:[]
1521 - };
1522 - groups.push(group);
1523 - }
1524 -
1525 - group.cards.push(card);
1350 + maxHeight=
1351 + Math.max(
1352 + maxHeight,
1353 + card.getBoundingClientRect().height
1354 + );
1526 1526   });
1527 1527  
1528 - groups.forEach(function(group){
1529 - if(group.cards.length<2){
1530 - return;
1531 - }
1357 + maxHeight=
1358 + Math.ceil(
1359 + maxHeight
1360 + );
1532 1532  
1533 - var firstHeaders=
1534 - group.cards.map(function(card){
1535 - var candidates=
1536 - headers
1537 - .filter(function(row){
1538 - return row.card===card;
1539 - })
1540 - .sort(function(a,b){
1541 - return (
1542 - a.el
1543 - .getBoundingClientRect()
1544 - .top-
1545 - b.el
1546 - .getBoundingClientRect()
1547 - .top
1548 - );
1549 - });
1362 + if(maxHeight<MIN_H)return false;
1550 1550  
1551 - return candidates.length
1552 - ?candidates[0]
1553 - :null;
1554 - });
1364 + cards.forEach(function(card){
1365 + saveOriginal(
1366 + card,
1367 + originalMinHeight,
1368 + "min-height"
1369 + );
1555 1555  
1556 - if(
1557 - !firstHeaders.some(function(row){
1558 - return !row;
1559 - })
1560 - ){
1561 - var targetTop=
1562 - Math.max.apply(
1563 - Math,
1564 - firstHeaders.map(function(row){
1565 - return (
1566 - row.el
1567 - .getBoundingClientRect()
1568 - .top-
1569 - row.card
1570 - .getBoundingClientRect()
1571 - .top
1572 - );
1573 - })
1574 - );
1371 + card.style.setProperty(
1372 + "min-height",
1373 + maxHeight+"px"
1374 + );
1575 1575  
1576 - firstHeaders.forEach(function(row){
1577 - var relativeTop=
1578 - row.el
1579 - .getBoundingClientRect()
1580 - .top-
1581 - row.card
1582 - .getBoundingClientRect()
1583 - .top;
1376 + card.setAttribute(
1377 + "data-sn-equal-height-managed",
1378 + "7"
1379 + );
1584 1584  
1585 - var delta=
1586 - targetTop-relativeTop;
1381 + heightManaged.add(card);
1382 + });
1587 1587  
1588 - if(delta>1){
1589 - saveStyle(
1590 - row.el,
1591 - originalMargin,
1592 - "margin-top"
1593 - );
1384 + return true;
1385 + }
1594 1594  
1595 - var current=
1596 - num(
1597 - getComputedStyle(
1598 - row.el
1599 - ).marginTop
1600 - );
1387 + function calculate(force){
1388 + if(applying)return;
1601 1601  
1602 - row.el.style.setProperty(
1603 - "margin-top",
1604 - (
1605 - current+delta
1606 - )+"px"
1607 - );
1390 + var width=
1391 + Math.round(
1392 + window.innerWidth
1393 + );
1608 1608  
1609 - row.el.setAttribute(
1610 - "data-sn-master-first-row",
1611 - "1"
1612 - );
1395 + var meaningful=
1396 + lastWidth<0||
1397 + Math.abs(
1398 + width-
1399 + lastWidth
1400 + )>=
1401 + MIN_WIDTH_CHANGE;
1613 1613  
1614 - managedMargin.add(
1615 - row.el
1616 - );
1617 - }
1618 - });
1619 - }
1620 -
1621 - var maxHeight=0;
1622 -
1623 - group.cards.forEach(function(card){
1624 - maxHeight=
1625 - Math.max(
1626 - maxHeight,
1627 - card
1628 - .getBoundingClientRect()
1629 - .height
1630 - );
1631 - });
1632 -
1633 - maxHeight=
1634 - Math.ceil(maxHeight);
1635 -
1636 - group.cards.forEach(function(card){
1637 - saveStyle(
1638 - card,
1639 - originalHeight,
1640 - "min-height"
1641 - );
1642 -
1643 - card.style.setProperty(
1644 - "min-height",
1645 - maxHeight+"px"
1646 - );
1647 -
1648 - card.setAttribute(
1649 - "data-sn-master-equal-height",
1650 - "1"
1651 - );
1652 -
1653 - managedHeight.add(
1654 - card
1655 - );
1656 - });
1657 - });
1658 - }
1659 -
1660 - /* =======================================================
1661 - DETAIL GRID EQUAL HEIGHT, DESKTOP ONLY
1662 - ======================================================= */
1663 -
1664 - function equaliseDetailGrids(){
1665 1665   if(
1666 - PAGE_KIND!=="detail"||
1667 - window.innerWidth<=MOBILE_MAX
1404 + hasApplied&&
1405 + !force&&
1406 + !meaningful
1668 1668   ){
1669 1669   return;
1670 1670   }
1671 1671  
1672 - var selectors=[
1673 - ".arsn-grid",
1674 - ".arsn-grid-2",
1675 - ".arsn-grid-3",
1676 - ".dmp-grid",
1677 - ".ido-grid",
1678 - ".pp-grid"
1679 - ];
1411 + applying=true;
1680 1680  
1681 - selectors.forEach(function(selector){
1682 - Array.from(
1683 - root.querySelectorAll(selector)
1684 - ).forEach(function(grid){
1685 - var children=
1686 - Array.from(
1687 - grid.children||[]
1688 - ).filter(visible);
1413 + try{
1414 + harmoniseCustomCallouts();
1689 1689  
1690 - if(children.length<2){
1691 - return;
1416 + if(width<=MOBILE_MAX){
1417 + if(hasApplied){
1418 + resetRuntime();
1692 1692   }
1693 1693  
1694 - var groups=[];
1421 + hasApplied=false;
1422 + lastWidth=width;
1423 + return;
1424 + }
1695 1695  
1696 - children.forEach(function(child){
1697 - var top=
1698 - child
1699 - .getBoundingClientRect()
1700 - .top;
1426 + if(hasApplied){
1427 + resetRuntime();
1428 + }
1701 1701  
1702 - var group=null;
1430 + var parents=
1431 + Array.from(
1432 + root.querySelectorAll("*")
1433 + )
1434 + .filter(function(parent){
1435 + return (
1436 + visible(
1437 + parent,
1438 + MIN_W,
1439 + MIN_H
1440 + )&&
1441 + parent.children&&
1442 + parent.children.length>=2&&
1443 + parent.children.length<=
1444 + MAX_PARENT_CHILDREN
1445 + );
1446 + });
1703 1703  
1704 - for(var i=0;i<groups.length;i++){
1705 - if(
1706 - Math.abs(
1707 - groups[i].top-top
1708 - )<=ROW_TOLERANCE
1709 - ){
1710 - group=groups[i];
1711 - break;
1712 - }
1713 - }
1448 + var touched=
1449 + new Set();
1714 1714  
1715 - if(!group){
1716 - group={
1717 - top:top,
1718 - items:[]
1719 - };
1720 - groups.push(group);
1721 - }
1451 + parents.forEach(function(parent){
1452 + var entries=[];
1722 1722  
1723 - group.items.push(child);
1724 - });
1725 -
1726 - groups.forEach(function(group){
1727 - if(group.items.length<2){
1454 + Array.from(
1455 + parent.children
1456 + ).forEach(function(child){
1457 + if(
1458 + !visible(
1459 + child,
1460 + MIN_W,
1461 + MIN_H
1462 + )
1463 + ){
1728 1728   return;
1729 1729   }
1730 1730  
1731 - var maxHeight=0;
1467 + var target=
1468 + pickTarget(child);
1732 1732  
1733 - group.items.forEach(function(item){
1734 - maxHeight=
1735 - Math.max(
1736 - maxHeight,
1737 - item
1738 - .getBoundingClientRect()
1739 - .height
1740 - );
1470 + if(!target)return;
1471 +
1472 + entries.push({
1473 + target:target,
1474 + rect:
1475 + target.getBoundingClientRect()
1741 1741   });
1477 + });
1742 1742  
1743 - maxHeight=
1744 - Math.ceil(maxHeight);
1479 + groupRows(
1480 + entries
1481 + ).forEach(function(group){
1482 + if(!validRow(group))return;
1745 1745  
1746 - group.items.forEach(function(item){
1747 - saveStyle(
1748 - item,
1749 - originalHeight,
1750 - "min-height"
1751 - );
1484 + var targets=
1485 + group.entries.map(function(entry){
1486 + return entry.target;
1487 + });
1752 1752  
1753 - item.style.setProperty(
1754 - "min-height",
1755 - maxHeight+"px"
1756 - );
1489 + if(
1490 + !targets.some(function(el){
1491 + return !touched.has(el);
1492 + })
1493 + ){
1494 + return;
1495 + }
1757 1757  
1758 - item.setAttribute(
1759 - "data-sn-master-equal-height",
1760 - "1"
1761 - );
1762 -
1763 - managedHeight.add(item);
1764 - });
1497 + if(applyRow(group)){
1498 + targets.forEach(function(el){
1499 + touched.add(el);
1500 + });
1501 + }
1765 1765   });
1766 1766   });
1767 - });
1768 - }
1769 1769  
1770 - /* =======================================================
1771 - RUN / RESPONSIVE SCHEDULING
1772 - ======================================================= */
1773 -
1774 - function run(){
1775 - if(running)return;
1776 -
1777 - running=true;
1778 -
1779 - try{
1780 - resetRuntime();
1781 - applyPlaceholderBadge();
1782 - propagateDetailAccents();
1783 -
1784 - var headers=
1785 - applyOverviewPalette();
1786 -
1787 - makeThreeLineAreaLabels();
1788 - makeFilledRedOrangeCTAsBorderless();
1789 -
1790 - if(
1791 - window.innerWidth>
1792 - MOBILE_MAX
1793 - ){
1794 - alignOverviewCards(
1795 - headers
1796 - );
1797 -
1798 - equaliseDetailGrids();
1799 - }
1505 + lastWidth=width;
1506 + hasApplied=true;
1800 1800   }finally{
1801 - running=false;
1508 + applying=false;
1802 1802   }
1803 1803   }
1804 1804  
1805 - function onResize(){
1512 + function resize(){
1806 1806   if(resizeTimer){
1807 1807   clearTimeout(
1808 1808   resizeTimer
... ... @@ -1813,40 +1813,19 @@
1813 1813   setTimeout(
1814 1814   function(){
1815 1815   resizeTimer=0;
1816 - run();
1523 + calculate(false);
1817 1817   },
1818 1818   RESIZE_DEBOUNCE
1819 1819   );
1820 1820   }
1821 1821  
1822 - async function waitForReady(){
1823 - if(
1824 - document.readyState!=="complete"
1825 - ){
1826 - await new Promise(function(resolve){
1827 - window.addEventListener(
1828 - "load",
1829 - resolve,
1830 - {once:true}
1831 - );
1832 - });
1833 - }
1834 -
1835 - if(
1836 - document.fonts&&
1837 - document.fonts.ready
1838 - ){
1839 - try{
1840 - await document.fonts.ready;
1841 - }catch(error){}
1842 - }
1843 -
1529 + function waitImages(){
1844 1844   var images=
1845 1845   Array.from(
1846 1846   root.querySelectorAll("img")
1847 1847   );
1848 1848  
1849 - await Promise.all(
1535 + return Promise.all(
1850 1850   images.map(function(img){
1851 1851   if(img.complete){
1852 1852   return Promise.resolve();
... ... @@ -1871,20 +1871,46 @@
1871 1871   });
1872 1872   })
1873 1873   );
1560 + }
1874 1874  
1875 - run();
1562 + async function initial(){
1563 + if(
1564 + document.readyState!==
1565 + "complete"
1566 + ){
1567 + await new Promise(function(resolve){
1568 + addEventListener(
1569 + "load",
1570 + resolve,
1571 + {once:true}
1572 + );
1573 + });
1574 + }
1575 +
1576 + if(
1577 + document.fonts&&
1578 + document.fonts.ready
1579 + ){
1580 + try{
1581 + await document.fonts.ready;
1582 + }catch(error){}
1583 + }
1584 +
1585 + await waitImages();
1586 +
1587 + // Exactly one initial layout calculation.
1588 + calculate(true);
1876 1876   }
1877 1877  
1878 - window.addEventListener(
1591 + addEventListener(
1879 1879   "resize",
1880 - onResize,
1593 + resize,
1881 1881   {passive:true}
1882 1882   );
1883 1883  
1884 - waitForReady();
1597 + initial();
1885 1885  })();
1886 1886  </script>
1887 1887  
1888 -<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_END -->
1889 -{{/html}}
1890 -
1601 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_END -->
1602 +{{/html}}\n