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

From version 5.8
edited by Veronika Kocher
on Thursday, 03 Sep 2026 9:18
Change comment: There is no comment for this version
To version 5.11
edited by Veronika Kocher
on Thursday, 03 Sep 2026 13:04
Change comment: There is no comment for this version

Summary

Details

Page properties
Content
... ... @@ -262,21 +262,100 @@
262 262  {{/html}}
263 263  
264 264  {{html clean="false"}}
265 -<!-- SN_HORIZONTAL_BOX_HARMONIZER_START -->
266 -<style data-sn-horizontal-box-harmonizer="1">
267 -[data-sn-equal-height-managed="1"]{box-sizing:border-box}
268 -@media(max-width:767px){
269 - [data-sn-equal-height-managed="1"]{min-height:0!important}
265 +<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_START -->
266 +
267 +<style data-sn-service-navigator-master="1">
268 +/* =========================================================
269 + MASTER TYPOGRAPHY
270 + ========================================================= */
271 +#xwikicontent h1,
272 +#xwikicontent h2,
273 +#xwikicontent h3,
274 +#xwikicontent h4,
275 +#xwikicontent h5,
276 +#xwikicontent h6,
277 +#xwikicontent .box-title,
278 +#xwikicontent [role="heading"],
279 +#xwikicontent h1 a,
280 +#xwikicontent h2 a,
281 +#xwikicontent h3 a,
282 +#xwikicontent h4 a,
283 +#xwikicontent h5 a,
284 +#xwikicontent h6 a,
285 +#xwikicontent .box-title a,
286 +#xwikicontent [role="heading"] a{
287 + text-align:left!important;
288 + text-justify:auto!important;
289 + word-spacing:normal!important;
270 270  }
291 +
292 +/* =========================================================
293 + COMING SOON / IN VORBEREITUNG
294 + ========================================================= */
295 +.sn-coming-soon-badge{
296 + display:inline-block;
297 + vertical-align:middle;
298 + margin-left:10px;
299 + padding:4px 8px;
300 + border-radius:14px;
301 + border:1px solid #efd9cc;
302 + background:#fff4ee;
303 + color:#8a4d36;
304 + font-size:11px;
305 + font-weight:700;
306 + letter-spacing:.055em;
307 + line-height:1.2;
308 + white-space:nowrap;
309 +}
310 +
311 +/* =========================================================
312 + NATIVE / DETAIL CALLOUT GEOMETRY
313 + Preserve existing backgrounds.
314 + ========================================================= */
315 +#xwikicontent .arsn-info,
316 +#xwikicontent .dmp-info,
317 +#xwikicontent .ido-info,
318 +#xwikicontent .pp-info,
319 +#xwikicontent .infomessage{
320 + box-sizing:border-box!important;
321 + border-left:4px solid #21b6d7!important;
322 + border-radius:8px;
323 + text-align:left!important;
324 + word-spacing:normal!important;
325 +}
326 +
327 +#xwikicontent .arsn-warn,
328 +#xwikicontent .dmp-warn,
329 +#xwikicontent .ido-warn,
330 +#xwikicontent .pp-warn,
331 +#xwikicontent .warn,
332 +#xwikicontent .warning,
333 +#xwikicontent .warningmessage,
334 +#xwikicontent .errormessage{
335 + box-sizing:border-box!important;
336 + border-left:4px solid #e94b13!important;
337 + border-radius:8px;
338 + text-align:left!important;
339 + word-spacing:normal!important;
340 +}
341 +
342 +[data-sn-master-equal-height],
343 +[data-sn-master-first-row]{
344 + box-sizing:border-box;
345 +}
271 271  </style>
272 -<script data-sn-horizontal-box-harmonizer="1">
347 +
348 +<script data-sn-service-navigator-master="1">
273 273  (function(){
274 274   "use strict";
275 275  
352 + var PAGE_KIND="detail";
353 + var PLACEHOLDER=false;
354 + var PLACEHOLDER_LABEL="COMING SOON";
355 +
276 276   var MOBILE_MAX=767;
277 - var ROW_TOLERANCE=4;
278 - var MIN_W=150;
279 - var MIN_H=36;
357 + var ROW_TOLERANCE=6;
358 + var RESIZE_DEBOUNCE=220;
280 280  
281 281   var root=
282 282   document.getElementById("xwikicontent")||
... ... @@ -286,212 +286,1044 @@
286 286  
287 287   if(!root)return;
288 288  
289 - var managed=new Set();
290 - var raf=0;
368 + var managedHeight=new Set();
369 + var managedMargin=new Set();
370 + var originalHeight=new WeakMap();
371 + var originalMargin=new WeakMap();
291 291  
292 - function num(v){
293 - var n=parseFloat(v);
373 + var resizeTimer=0;
374 + var running=false;
375 +
376 + var THEMES=[
377 + {
378 + name:"BLUE",
379 + accent:"#21b6d7",
380 + bg:"#eaf7fb",
381 + text:"#315d68",
382 + labels:[
383 + "HIER STARTEN",
384 + "ENTSCHEIDEN",
385 + "ÜBERPRÜFEN & ANPASSEN",
386 + "START HERE",
387 + "DECIDE",
388 + "REVIEW & ADAPT"
389 + ]
390 + },
391 + {
392 + name:"RED",
393 + accent:"#e94b13",
394 + bg:"#fff1ec",
395 + text:"#8a4d36",
396 + labels:[
397 + "PLANEN & ORGANISIEREN",
398 + "ORGANISIEREN & DOKUMENTIEREN",
399 + "PUBLIZIEREN & PRÄSENTIEREN",
400 + "PLAN & ORGANISE",
401 + "PLAN & ORGANIZE",
402 + "ORGANISE & DOCUMENT",
403 + "ORGANIZE & DOCUMENT",
404 + "PUBLISH & PRESENT"
405 + ]
406 + },
407 + {
408 + name:"YELLOW",
409 + accent:"#f0aa00",
410 + bg:"#fff8e7",
411 + text:"#785b17",
412 + labels:[
413 + "SCHÜTZEN & KLÄREN",
414 + "STANDARDISIEREN & IDENTIFIZIEREN",
415 + "ÖFFNEN, NACHNUTZEN & AUFFINDBAR MACHEN",
416 + "PROTECT & CLARIFY",
417 + "STANDARDISE & IDENTIFY",
418 + "STANDARDIZE & IDENTIFY",
419 + "OPEN, REUSE & MAKE FINDABLE"
420 + ]
421 + },
422 + {
423 + name:"GREEN",
424 + accent:"#38b76a",
425 + bg:"#edf9f1",
426 + text:"#3f7451",
427 + labels:[
428 + "INFRASTRUKTUR EINRICHTEN",
429 + "INFRASTRUKTUR & ZUSAMMENARBEIT EINRICHTEN",
430 + "SPEICHERN & ZUGRIFF STEUERN",
431 + "REPOSITORIUM, ERHALTEN & ÜBERGEBEN",
432 + "SET UP INFRASTRUCTURE",
433 + "SET UP INFRASTRUCTURE & COLLABORATION",
434 + "STORE & CONTROL ACCESS",
435 + "REPOSITORY, PRESERVE & HAND OVER"
436 + ]
437 + }
438 + ];
439 +
440 + function num(value){
441 + var n=parseFloat(value);
294 294   return Number.isFinite(n)?n:0;
295 295   }
296 296  
445 + function norm(value){
446 + return String(value||"")
447 + .replace(/\s+/g," ")
448 + .trim()
449 + .toUpperCase();
450 + }
451 +
297 297   function visible(el){
298 298   if(!el||el.nodeType!==1)return false;
299 - var s=getComputedStyle(el);
300 - if(s.display==="none"||s.visibility==="hidden"||Number(s.opacity)===0)return false;
301 - var r=el.getBoundingClientRect();
302 - return r.width>=MIN_W&&r.height>=MIN_H;
454 +
455 + var style=getComputedStyle(el);
456 + var rect=el.getBoundingClientRect();
457 +
458 + return (
459 + style.display!=="none"&&
460 + style.visibility!=="hidden"&&
461 + rect.width>20&&
462 + rect.height>4
463 + );
303 303   }
304 304  
305 - function excluded(el){
306 - return !el.matches||el.matches(
307 - "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]"
466 + function saveStyle(el,map,property){
467 + if(map.has(el))return;
468 +
469 + map.set(el,{
470 + value:el.style.getPropertyValue(property),
471 + priority:el.style.getPropertyPriority(property)
472 + });
473 + }
474 +
475 + function restoreStyle(el,map,property){
476 + var original=map.get(el);
477 +
478 + if(original&&original.value){
479 + el.style.setProperty(
480 + property,
481 + original.value,
482 + original.priority||""
483 + );
484 + }else{
485 + el.style.removeProperty(property);
486 + }
487 + }
488 +
489 + function resetRuntime(){
490 + managedHeight.forEach(function(el){
491 + restoreStyle(
492 + el,
493 + originalHeight,
494 + "min-height"
495 + );
496 + el.removeAttribute(
497 + "data-sn-master-equal-height"
498 + );
499 + });
500 +
501 + managedMargin.forEach(function(el){
502 + restoreStyle(
503 + el,
504 + originalMargin,
505 + "margin-top"
506 + );
507 + el.removeAttribute(
508 + "data-sn-master-first-row"
509 + );
510 + });
511 +
512 + managedHeight.clear();
513 + managedMargin.clear();
514 + }
515 +
516 + function themeFor(text){
517 + var value=norm(text);
518 +
519 + for(var i=0;i<THEMES.length;i++){
520 + for(var j=0;j<THEMES[i].labels.length;j++){
521 + var label=THEMES[i].labels[j];
522 +
523 + if(
524 + value===label||
525 + value.indexOf(label+" ")===0||
526 + value.indexOf(label+" -")===0||
527 + value.indexOf(label+" ·")===0
528 + ){
529 + return THEMES[i];
530 + }
531 + }
532 + }
533 +
534 + return null;
535 + }
536 +
537 + /* =======================================================
538 + PLACEHOLDER BADGE
539 + ======================================================= */
540 +
541 + function applyPlaceholderBadge(){
542 + if(!PLACEHOLDER)return;
543 +
544 + if(
545 + document.querySelector(
546 + ".sn-coming-soon-badge"
547 + )
548 + ){
549 + return;
550 + }
551 +
552 + var title=
553 + document.querySelector(
554 + "#document-title"
555 + )||
556 + document.querySelector(
557 + "h1"
558 + );
559 +
560 + if(!title)return;
561 +
562 + var badge=
563 + document.createElement(
564 + "span"
565 + );
566 +
567 + badge.className=
568 + "sn-coming-soon-badge";
569 +
570 + badge.textContent=
571 + PLACEHOLDER_LABEL;
572 +
573 + badge.setAttribute(
574 + "aria-label",
575 + PLACEHOLDER_LABEL
308 308   );
577 +
578 + title.appendChild(
579 + badge
580 + );
309 309   }
310 310  
311 - function namedLikeBox(el){
312 - var c=typeof el.className==="string"?el.className:"";
313 - return /(^|[\s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([\s_-]|$)/i.test(c);
583 + /* =======================================================
584 + DETAIL PAGE OWN-ACCENT PROPAGATION
585 + ======================================================= */
586 +
587 + function parseRGB(value){
588 + var match=String(value||"").match(
589 + /rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i
590 + );
591 +
592 + if(!match)return null;
593 +
594 + return [
595 + Number(match[1]),
596 + Number(match[2]),
597 + Number(match[3])
598 + ];
314 314   }
315 315  
316 - function boxLike(el){
317 - if(!visible(el)||excluded(el))return false;
318 - var s=getComputedStyle(el);
319 - var r=el.getBoundingClientRect();
320 - var border=
321 - num(s.borderTopWidth)+num(s.borderRightWidth)+
322 - num(s.borderBottomWidth)+num(s.borderLeftWidth);
323 - var radius=Math.max(
324 - num(s.borderTopLeftRadius),num(s.borderTopRightRadius),
325 - num(s.borderBottomLeftRadius),num(s.borderBottomRightRadius)
601 + function distance(a,b){
602 + return Math.sqrt(
603 + Math.pow(a[0]-b[0],2)+
604 + Math.pow(a[1]-b[1],2)+
605 + Math.pow(a[2]-b[2],2)
326 326   );
327 - var bg=s.backgroundColor&&s.backgroundColor!=="rgba(0, 0, 0, 0)"&&s.backgroundColor!=="transparent";
328 - var shadow=s.boxShadow&&s.boxShadow!=="none";
329 - return namedLikeBox(el)||border>=1||(bg&&radius>=3)||(shadow&&r.width>=180);
330 330   }
331 331  
332 - function pickTarget(child){
333 - if(!visible(child))return null;
334 - if(boxLike(child))return child;
609 + function paletteMatch(cssColor){
610 + var rgb=parseRGB(cssColor);
335 335  
336 - var cr=child.getBoundingClientRect();
337 - var q=[];
338 - Array.from(child.children||[]).forEach(function(el){
339 - q.push({el:el,depth:1});
612 + if(!rgb)return null;
613 +
614 + var palette=[
615 + {hex:"#21b6d7",rgb:[33,182,215]},
616 + {hex:"#e94b13",rgb:[233,75,19]},
617 + {hex:"#f0aa00",rgb:[240,170,0]},
618 + {hex:"#38b76a",rgb:[56,183,106]}
619 + ];
620 +
621 + var best=null;
622 + var bestDistance=Infinity;
623 +
624 + palette.forEach(function(item){
625 + var d=distance(rgb,item.rgb);
626 +
627 + if(d<bestDistance){
628 + best=item;
629 + bestDistance=d;
630 + }
340 340   });
341 341  
342 - var best=null,bestScore=-1;
633 + return bestDistance<=30
634 + ?best
635 + :null;
636 + }
343 343  
344 - while(q.length){
345 - var item=q.shift();
346 - var el=item.el;
347 - if(!visible(el))continue;
638 + function propagateDetailAccents(){
639 + if(PAGE_KIND!=="detail")return;
348 348  
349 - var r=el.getBoundingClientRect();
641 + Array.from(
642 + root.querySelectorAll(
643 + ".arsn-call,.dmp-call,.ido-call,.pp-call,"+
644 + ".arsn-source,.dmp-source,.ido-source,.pp-source"
645 + )
646 + ).forEach(function(el){
647 + if(!visible(el))return;
350 350  
351 - if(r.width>=cr.width*.72&&boxLike(el)){
352 - var widthFit=1-Math.min(1,Math.abs(cr.width-r.width)/Math.max(1,cr.width));
353 - var topFit=1-Math.min(1,Math.abs(cr.top-r.top)/80);
354 - var score=widthFit*5+topFit*2+Math.min(r.height,600)/600;
355 - if(score>bestScore){
356 - best=el;
357 - bestScore=score;
649 + var style=getComputedStyle(el);
650 +
651 + if(
652 + num(style.borderTopWidth)>=2
653 + ){
654 + var match=
655 + paletteMatch(
656 + style.borderTopColor
657 + );
658 +
659 + if(match){
660 + el.style.setProperty(
661 + "border-left",
662 + "4px solid "+match.hex,
663 + "important"
664 + );
358 358   }
359 359   }
667 + });
360 360  
361 - if(item.depth<3){
362 - Array.from(el.children||[]).forEach(function(next){
363 - q.push({el:next,depth:item.depth+1});
364 - });
669 + // Warning families: explicit safety override.
670 + Array.from(
671 + root.querySelectorAll(
672 + ".arsn-warn,.dmp-warn,.ido-warn,.pp-warn,"+
673 + ".warn,.warning,.warningmessage,.errormessage"
674 + )
675 + ).forEach(function(el){
676 + if(!visible(el))return;
677 +
678 + el.style.setProperty(
679 + "border-left",
680 + "4px solid #e94b13",
681 + "important"
682 + );
683 + });
684 +
685 + // Info families: explicit orientation override.
686 + Array.from(
687 + root.querySelectorAll(
688 + ".arsn-info,.dmp-info,.ido-info,.pp-info,.infomessage"
689 + )
690 + ).forEach(function(el){
691 + if(!visible(el))return;
692 +
693 + el.style.setProperty(
694 + "border-left",
695 + "4px solid #21b6d7",
696 + "important"
697 + );
698 + });
699 + }
700 +
701 + /* =======================================================
702 + OVERVIEW SEMANTIC THEME PALETTE
703 + ======================================================= */
704 +
705 + function smallestThemeHeaders(){
706 + return Array.from(
707 + root.querySelectorAll(
708 + "div,span,p,strong,h3,h4,h5,h6"
709 + )
710 + ).filter(function(el){
711 + if(!visible(el))return false;
712 + if(!themeFor(el.textContent))return false;
713 +
714 + return !Array.from(
715 + el.children||[]
716 + ).some(function(child){
717 + return !!themeFor(
718 + child.textContent
719 + );
720 + });
721 + });
722 + }
723 +
724 + function findOverviewCard(header){
725 + var node=header.parentElement;
726 + var candidates=[];
727 +
728 + while(node&&node!==root){
729 + var rect=node.getBoundingClientRect();
730 + var style=getComputedStyle(node);
731 +
732 + var border=
733 + num(style.borderTopWidth)+
734 + num(style.borderRightWidth)+
735 + num(style.borderBottomWidth)+
736 + num(style.borderLeftWidth);
737 +
738 + if(
739 + rect.width>=220&&
740 + rect.width<=800&&
741 + rect.height>=120&&
742 + border>=1
743 + ){
744 + candidates.push(node);
365 365   }
746 +
747 + node=node.parentElement;
366 366   }
367 367  
368 - return best;
750 + if(!candidates.length)return null;
751 +
752 + candidates.sort(function(a,b){
753 + return (
754 + b.getBoundingClientRect().height-
755 + a.getBoundingClientRect().height
756 + );
757 + });
758 +
759 + return candidates[0];
369 369   }
370 370  
371 - function reset(){
372 - managed.forEach(function(el){
373 - el.style.removeProperty("min-height");
374 - el.removeAttribute("data-sn-equal-height-managed");
762 + function rowCandidates(link,card){
763 + var result=[];
764 + var cardRect=
765 + card.getBoundingClientRect();
766 +
767 + var node=link;
768 +
769 + while(node&&node!==card){
770 + if(visible(node)){
771 + var rect=
772 + node.getBoundingClientRect();
773 +
774 + if(
775 + rect.height<=105&&
776 + rect.width>=
777 + cardRect.width*.50&&
778 + rect.width<=
779 + cardRect.width*1.03
780 + ){
781 + result.push(node);
782 + }
783 + }
784 +
785 + node=node.parentElement;
786 + }
787 +
788 + return result;
789 + }
790 +
791 + function chooseOuterRow(
792 + candidates,
793 + link
794 + ){
795 + if(!candidates.length){
796 + return link;
797 + }
798 +
799 + var bordered=
800 + candidates.filter(function(el){
801 + return (
802 + num(
803 + getComputedStyle(el)
804 + .borderLeftWidth
805 + )>=1
806 + );
807 + });
808 +
809 + var pool=
810 + bordered.length
811 + ?bordered
812 + :candidates;
813 +
814 + pool.sort(function(a,b){
815 + var ar=
816 + a.getBoundingClientRect();
817 +
818 + var br=
819 + b.getBoundingClientRect();
820 +
821 + return (
822 + ar.left-br.left||
823 + br.width-ar.width
824 + );
375 375   });
376 - managed.clear();
826 +
827 + return pool[0]||link;
377 377   }
378 378  
379 - function horizontalLayout(parent){
380 - if(!visible(parent))return false;
381 - var s=getComputedStyle(parent);
382 - if(s.display==="grid"||s.display==="inline-grid")return true;
383 - if(s.display==="flex"||s.display==="inline-flex"){
384 - return s.flexDirection==="row"||s.flexDirection==="row-reverse";
830 + function applyOverviewPalette(){
831 + if(PAGE_KIND!=="overview"){
832 + return [];
385 385   }
386 - return false;
834 +
835 + var headers=
836 + smallestThemeHeaders()
837 + .map(function(el){
838 + return {
839 + el:el,
840 + theme:
841 + themeFor(
842 + el.textContent
843 + ),
844 + card:
845 + findOverviewCard(
846 + el
847 + )
848 + };
849 + })
850 + .filter(function(row){
851 + return !!row.card;
852 + });
853 +
854 + var unique=[];
855 + var seenHeaders=new Set();
856 +
857 + headers.forEach(function(row){
858 + var key=
859 + row.theme.name+
860 + "|"+
861 + Math.round(
862 + row.card
863 + .getBoundingClientRect()
864 + .left
865 + )+
866 + "|"+
867 + Math.round(
868 + row.el
869 + .getBoundingClientRect()
870 + .top
871 + );
872 +
873 + if(!seenHeaders.has(key)){
874 + seenHeaders.add(key);
875 + unique.push(row);
876 + }
877 + });
878 +
879 + unique.forEach(function(row){
880 + var headerRect=
881 + row.el
882 + .getBoundingClientRect();
883 +
884 + row.el.style.setProperty(
885 + "background",
886 + row.theme.bg,
887 + "important"
888 + );
889 +
890 + row.el.style.setProperty(
891 + "color",
892 + row.theme.text,
893 + "important"
894 + );
895 +
896 + row.el.style.setProperty(
897 + "text-align",
898 + "left",
899 + "important"
900 + );
901 +
902 + row.el.style.setProperty(
903 + "word-spacing",
904 + "normal",
905 + "important"
906 + );
907 +
908 + var later=
909 + unique
910 + .filter(function(other){
911 + return (
912 + other.card===row.card&&
913 + other.el
914 + .getBoundingClientRect()
915 + .top>
916 + headerRect.top+2
917 + );
918 + })
919 + .sort(function(a,b){
920 + return (
921 + a.el
922 + .getBoundingClientRect()
923 + .top-
924 + b.el
925 + .getBoundingClientRect()
926 + .top
927 + );
928 + });
929 +
930 + var stopTop=
931 + later.length
932 + ?later[0].el
933 + .getBoundingClientRect()
934 + .top
935 + :Infinity;
936 +
937 + Array.from(
938 + row.card.querySelectorAll("a")
939 + ).forEach(function(link){
940 + if(!visible(link))return;
941 +
942 + var rect=
943 + link.getBoundingClientRect();
944 +
945 + if(
946 + rect.top<=
947 + headerRect.bottom-2||
948 + rect.top>=
949 + stopTop-2
950 + ){
951 + return;
952 + }
953 +
954 + var candidates=
955 + rowCandidates(
956 + link,
957 + row.card
958 + );
959 +
960 + var target=
961 + chooseOuterRow(
962 + candidates,
963 + link
964 + );
965 +
966 + candidates.forEach(function(el){
967 + el.style.setProperty(
968 + "border-left",
969 + "0 solid transparent",
970 + "important"
971 + );
972 + });
973 +
974 + target.style.setProperty(
975 + "border-left",
976 + "3px solid "+
977 + row.theme.accent,
978 + "important"
979 + );
980 +
981 + target.style.setProperty(
982 + "box-sizing",
983 + "border-box",
984 + "important"
985 + );
986 + });
987 + });
988 +
989 + return unique;
387 387   }
388 388  
389 - function rowGroups(entries){
992 + /* =======================================================
993 + OVERVIEW CARD HEIGHT + FIRST THEMATIC ROW
994 + ======================================================= */
995 +
996 + function alignOverviewCards(headers){
997 + if(
998 + PAGE_KIND!=="overview"||
999 + window.innerWidth<=MOBILE_MAX
1000 + ){
1001 + return;
1002 + }
1003 +
1004 + var cards=[];
1005 + var seen=new Set();
1006 +
1007 + headers.forEach(function(row){
1008 + if(!seen.has(row.card)){
1009 + seen.add(row.card);
1010 + cards.push(row.card);
1011 + }
1012 + });
1013 +
1014 + if(cards.length<2){
1015 + return;
1016 + }
1017 +
1018 + // Group cards by actual top position.
390 390   var groups=[];
391 - entries.slice().sort(function(a,b){
392 - return a.rect.top-b.rect.top||a.rect.left-b.rect.left;
393 - }).forEach(function(entry){
1020 +
1021 + cards.forEach(function(card){
1022 + var top=
1023 + card.getBoundingClientRect().top;
1024 +
394 394   var group=null;
1026 +
395 395   for(var i=0;i<groups.length;i++){
396 - if(Math.abs(groups[i].top-entry.rect.top)<=ROW_TOLERANCE){
1028 + if(
1029 + Math.abs(
1030 + groups[i].top-top
1031 + )<=ROW_TOLERANCE
1032 + ){
397 397   group=groups[i];
398 398   break;
399 399   }
400 400   }
1037 +
401 401   if(!group){
402 - group={top:entry.rect.top,entries:[]};
1039 + group={
1040 + top:top,
1041 + cards:[]
1042 + };
403 403   groups.push(group);
404 404   }
405 - group.entries.push(entry);
1045 +
1046 + group.cards.push(card);
406 406   });
407 - return groups;
408 - }
409 409  
410 - function run(){
411 - reset();
1049 + groups.forEach(function(group){
1050 + if(group.cards.length<2){
1051 + return;
1052 + }
412 412  
413 - if(window.innerWidth<=MOBILE_MAX)return;
1054 + var firstHeaders=
1055 + group.cards.map(function(card){
1056 + var candidates=
1057 + headers
1058 + .filter(function(row){
1059 + return row.card===card;
1060 + })
1061 + .sort(function(a,b){
1062 + return (
1063 + a.el
1064 + .getBoundingClientRect()
1065 + .top-
1066 + b.el
1067 + .getBoundingClientRect()
1068 + .top
1069 + );
1070 + });
414 414  
415 - var parents=Array.from(root.querySelectorAll("*")).filter(function(el){
416 - return el.children&&el.children.length>=2&&horizontalLayout(el);
417 - });
1072 + return candidates.length
1073 + ?candidates[0]
1074 + :null;
1075 + });
418 418  
419 - parents.forEach(function(parent){
420 - var entries=[];
1077 + if(
1078 + !firstHeaders.some(function(row){
1079 + return !row;
1080 + })
1081 + ){
1082 + var targetTop=
1083 + Math.max.apply(
1084 + Math,
1085 + firstHeaders.map(function(row){
1086 + return (
1087 + row.el
1088 + .getBoundingClientRect()
1089 + .top-
1090 + row.card
1091 + .getBoundingClientRect()
1092 + .top
1093 + );
1094 + })
1095 + );
421 421  
422 - Array.from(parent.children).forEach(function(child){
423 - if(!visible(child))return;
424 - var target=pickTarget(child);
425 - if(!target)return;
426 - entries.push({
427 - target:target,
428 - rect:target.getBoundingClientRect()
1097 + firstHeaders.forEach(function(row){
1098 + var relativeTop=
1099 + row.el
1100 + .getBoundingClientRect()
1101 + .top-
1102 + row.card
1103 + .getBoundingClientRect()
1104 + .top;
1105 +
1106 + var delta=
1107 + targetTop-relativeTop;
1108 +
1109 + if(delta>1){
1110 + saveStyle(
1111 + row.el,
1112 + originalMargin,
1113 + "margin-top"
1114 + );
1115 +
1116 + var current=
1117 + num(
1118 + getComputedStyle(
1119 + row.el
1120 + ).marginTop
1121 + );
1122 +
1123 + row.el.style.setProperty(
1124 + "margin-top",
1125 + (
1126 + current+delta
1127 + )+"px"
1128 + );
1129 +
1130 + row.el.setAttribute(
1131 + "data-sn-master-first-row",
1132 + "1"
1133 + );
1134 +
1135 + managedMargin.add(
1136 + row.el
1137 + );
1138 + }
429 429   });
1140 + }
1141 +
1142 + var maxHeight=0;
1143 +
1144 + group.cards.forEach(function(card){
1145 + maxHeight=
1146 + Math.max(
1147 + maxHeight,
1148 + card
1149 + .getBoundingClientRect()
1150 + .height
1151 + );
430 430   });
431 431  
432 - if(entries.length<2)return;
1154 + maxHeight=
1155 + Math.ceil(maxHeight);
433 433  
434 - rowGroups(entries).forEach(function(group){
435 - if(group.entries.length<2)return;
1157 + group.cards.forEach(function(card){
1158 + saveStyle(
1159 + card,
1160 + originalHeight,
1161 + "min-height"
1162 + );
436 436  
437 - var lefts=group.entries.map(function(e){return e.rect.left;}).sort(function(a,b){return a-b;});
438 - if(lefts[lefts.length-1]-lefts[0]<80)return;
1164 + card.style.setProperty(
1165 + "min-height",
1166 + maxHeight+"px"
1167 + );
439 439  
440 - var targets=[];
441 - var seen=new Set();
1169 + card.setAttribute(
1170 + "data-sn-master-equal-height",
1171 + "1"
1172 + );
442 442  
443 - group.entries.forEach(function(e){
444 - if(!seen.has(e.target)){
445 - seen.add(e.target);
446 - targets.push(e.target);
1174 + managedHeight.add(
1175 + card
1176 + );
1177 + });
1178 + });
1179 + }
1180 +
1181 + /* =======================================================
1182 + DETAIL GRID EQUAL HEIGHT, DESKTOP ONLY
1183 + ======================================================= */
1184 +
1185 + function equaliseDetailGrids(){
1186 + if(
1187 + PAGE_KIND!=="detail"||
1188 + window.innerWidth<=MOBILE_MAX
1189 + ){
1190 + return;
1191 + }
1192 +
1193 + var selectors=[
1194 + ".arsn-grid",
1195 + ".arsn-grid-2",
1196 + ".arsn-grid-3",
1197 + ".dmp-grid",
1198 + ".ido-grid",
1199 + ".pp-grid"
1200 + ];
1201 +
1202 + selectors.forEach(function(selector){
1203 + Array.from(
1204 + root.querySelectorAll(selector)
1205 + ).forEach(function(grid){
1206 + var children=
1207 + Array.from(
1208 + grid.children||[]
1209 + ).filter(visible);
1210 +
1211 + if(children.length<2){
1212 + return;
1213 + }
1214 +
1215 + var groups=[];
1216 +
1217 + children.forEach(function(child){
1218 + var top=
1219 + child
1220 + .getBoundingClientRect()
1221 + .top;
1222 +
1223 + var group=null;
1224 +
1225 + for(var i=0;i<groups.length;i++){
1226 + if(
1227 + Math.abs(
1228 + groups[i].top-top
1229 + )<=ROW_TOLERANCE
1230 + ){
1231 + group=groups[i];
1232 + break;
1233 + }
447 447   }
448 - });
449 449  
450 - if(targets.length<2)return;
1236 + if(!group){
1237 + group={
1238 + top:top,
1239 + items:[]
1240 + };
1241 + groups.push(group);
1242 + }
451 451  
452 - var max=0;
453 - targets.forEach(function(el){
454 - max=Math.max(max,el.getBoundingClientRect().height);
1244 + group.items.push(child);
455 455   });
456 456  
457 - max=Math.ceil(max);
458 - if(max<MIN_H)return;
1247 + groups.forEach(function(group){
1248 + if(group.items.length<2){
1249 + return;
1250 + }
459 459  
460 - targets.forEach(function(el){
461 - el.style.setProperty("min-height",max+"px");
462 - el.setAttribute("data-sn-equal-height-managed","1");
463 - managed.add(el);
1252 + var maxHeight=0;
1253 +
1254 + group.items.forEach(function(item){
1255 + maxHeight=
1256 + Math.max(
1257 + maxHeight,
1258 + item
1259 + .getBoundingClientRect()
1260 + .height
1261 + );
1262 + });
1263 +
1264 + maxHeight=
1265 + Math.ceil(maxHeight);
1266 +
1267 + group.items.forEach(function(item){
1268 + saveStyle(
1269 + item,
1270 + originalHeight,
1271 + "min-height"
1272 + );
1273 +
1274 + item.style.setProperty(
1275 + "min-height",
1276 + maxHeight+"px"
1277 + );
1278 +
1279 + item.setAttribute(
1280 + "data-sn-master-equal-height",
1281 + "1"
1282 + );
1283 +
1284 + managedHeight.add(item);
1285 + });
464 464   });
465 465   });
466 466   });
467 467   }
468 468  
469 - function schedule(){
470 - if(raf)cancelAnimationFrame(raf);
471 - raf=requestAnimationFrame(function(){
472 - raf=requestAnimationFrame(function(){
473 - raf=0;
474 - run();
475 - });
476 - });
1291 + /* =======================================================
1292 + RUN / RESPONSIVE SCHEDULING
1293 + ======================================================= */
1294 +
1295 + function run(){
1296 + if(running)return;
1297 +
1298 + running=true;
1299 +
1300 + try{
1301 + resetRuntime();
1302 + applyPlaceholderBadge();
1303 + propagateDetailAccents();
1304 +
1305 + var headers=
1306 + applyOverviewPalette();
1307 +
1308 + if(
1309 + window.innerWidth>
1310 + MOBILE_MAX
1311 + ){
1312 + alignOverviewCards(
1313 + headers
1314 + );
1315 +
1316 + equaliseDetailGrids();
1317 + }
1318 + }finally{
1319 + running=false;
1320 + }
477 477   }
478 478  
479 - addEventListener("resize",schedule,{passive:true});
480 - addEventListener("load",schedule,{once:true});
1323 + function onResize(){
1324 + if(resizeTimer){
1325 + clearTimeout(
1326 + resizeTimer
1327 + );
1328 + }
481 481  
482 - root.addEventListener("click",function(){
483 - setTimeout(schedule,0);
484 - },true);
1330 + resizeTimer=
1331 + setTimeout(
1332 + function(){
1333 + resizeTimer=0;
1334 + run();
1335 + },
1336 + RESIZE_DEBOUNCE
1337 + );
1338 + }
485 485  
486 - if(document.fonts&&document.fonts.ready){
487 - document.fonts.ready.then(schedule);
1340 + async function waitForReady(){
1341 + if(
1342 + document.readyState!=="complete"
1343 + ){
1344 + await new Promise(function(resolve){
1345 + window.addEventListener(
1346 + "load",
1347 + resolve,
1348 + {once:true}
1349 + );
1350 + });
1351 + }
1352 +
1353 + if(
1354 + document.fonts&&
1355 + document.fonts.ready
1356 + ){
1357 + try{
1358 + await document.fonts.ready;
1359 + }catch(error){}
1360 + }
1361 +
1362 + var images=
1363 + Array.from(
1364 + root.querySelectorAll("img")
1365 + );
1366 +
1367 + await Promise.all(
1368 + images.map(function(img){
1369 + if(img.complete){
1370 + return Promise.resolve();
1371 + }
1372 +
1373 + return new Promise(function(resolve){
1374 + var done=function(){
1375 + resolve();
1376 + };
1377 +
1378 + img.addEventListener(
1379 + "load",
1380 + done,
1381 + {once:true}
1382 + );
1383 +
1384 + img.addEventListener(
1385 + "error",
1386 + done,
1387 + {once:true}
1388 + );
1389 + });
1390 + })
1391 + );
1392 +
1393 + run();
488 488   }
489 489  
490 - schedule();
491 - setTimeout(schedule,250);
492 - setTimeout(schedule,900);
1396 + window.addEventListener(
1397 + "resize",
1398 + onResize,
1399 + {passive:true}
1400 + );
1401 +
1402 + waitForReady();
493 493  })();
494 494  </script>
495 -<!-- SN_HORIZONTAL_BOX_HARMONIZER_END -->
1405 +
1406 +<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_END -->
496 496  {{/html}}
497 497