Änderungen von Dokument Prepare
Zuletzt geändert von Veronika Kocher am Freitag, 18 Sep. 2026 16:47
Von Version 1.7
bearbeitet von Veronika Kocher
am Donnerstag, 03 Sep. 2026 9:34
am Donnerstag, 03 Sep. 2026 9:34
Änderungskommentar:
Es gibt keinen Kommentar für diese Version
Auf Version 1.9
bearbeitet von Veronika Kocher
am Donnerstag, 03 Sep. 2026 13:04
am Donnerstag, 03 Sep. 2026 13:04
Änderungskommentar:
Es gibt keinen Kommentar für diese Version
Zusammenfassung
-
Seiteneigenschaften (1 geändert, 0 hinzugefügt, 0 gelöscht)
Details
- Seiteneigenschaften
-
- Inhalt
-
... ... @@ -484,23 +484,100 @@ 484 484 {{/html}} 485 485 486 486 {{html clean="false"}} 487 -<!-- SN_HORIZONTAL_BOX_HARMONIZER_START --> 488 -<style data-sn-horizontal-box-harmonizer="4"> 489 -[data-sn-equal-height-managed], 490 -[data-sn-first-section-aligned]{ 487 +<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_START --> 488 + 489 +<style data-sn-service-navigator-master="1"> 490 +/* ========================================================= 491 + MASTER TYPOGRAPHY 492 + ========================================================= */ 493 +#xwikicontent h1, 494 +#xwikicontent h2, 495 +#xwikicontent h3, 496 +#xwikicontent h4, 497 +#xwikicontent h5, 498 +#xwikicontent h6, 499 +#xwikicontent .box-title, 500 +#xwikicontent [role="heading"], 501 +#xwikicontent h1 a, 502 +#xwikicontent h2 a, 503 +#xwikicontent h3 a, 504 +#xwikicontent h4 a, 505 +#xwikicontent h5 a, 506 +#xwikicontent h6 a, 507 +#xwikicontent .box-title a, 508 +#xwikicontent [role="heading"] a{ 509 + text-align:left!important; 510 + text-justify:auto!important; 511 + word-spacing:normal!important; 512 +} 513 + 514 +/* ========================================================= 515 + COMING SOON / IN VORBEREITUNG 516 + ========================================================= */ 517 +.sn-coming-soon-badge{ 518 + display:inline-block; 519 + vertical-align:middle; 520 + margin-left:10px; 521 + padding:4px 8px; 522 + border-radius:14px; 523 + border:1px solid #efd9cc; 524 + background:#fff4ee; 525 + color:#8a4d36; 526 + font-size:11px; 527 + font-weight:700; 528 + letter-spacing:.055em; 529 + line-height:1.2; 530 + white-space:nowrap; 531 +} 532 + 533 +/* ========================================================= 534 + NATIVE / DETAIL CALLOUT GEOMETRY 535 + Preserve existing backgrounds. 536 + ========================================================= */ 537 +#xwikicontent .arsn-info, 538 +#xwikicontent .dmp-info, 539 +#xwikicontent .ido-info, 540 +#xwikicontent .pp-info, 541 +#xwikicontent .infomessage{ 542 + box-sizing:border-box!important; 543 + border-left:4px solid #21b6d7!important; 544 + border-radius:8px; 545 + text-align:left!important; 546 + word-spacing:normal!important; 547 +} 548 + 549 +#xwikicontent .arsn-warn, 550 +#xwikicontent .dmp-warn, 551 +#xwikicontent .ido-warn, 552 +#xwikicontent .pp-warn, 553 +#xwikicontent .warn, 554 +#xwikicontent .warning, 555 +#xwikicontent .warningmessage, 556 +#xwikicontent .errormessage{ 557 + box-sizing:border-box!important; 558 + border-left:4px solid #e94b13!important; 559 + border-radius:8px; 560 + text-align:left!important; 561 + word-spacing:normal!important; 562 +} 563 + 564 +[data-sn-master-equal-height], 565 +[data-sn-master-first-row]{ 491 491 box-sizing:border-box; 492 492 } 493 493 </style> 494 -<script data-sn-horizontal-box-harmonizer="4"> 569 + 570 +<script data-sn-service-navigator-master="1"> 495 495 (function(){ 496 496 "use strict"; 497 497 574 + var PAGE_KIND="overview"; 575 + var PLACEHOLDER=false; 576 + var PLACEHOLDER_LABEL="IN VORBEREITUNG"; 577 + 498 498 var MOBILE_MAX=767; 499 499 var ROW_TOLERANCE=6; 500 - var MIN_W=150; 501 - var MIN_H=36; 502 - var MAX_PARENT_CHILDREN=16; 503 - var SEARCH_DEPTH=5; 580 + var RESIZE_DEBOUNCE=220; 504 504 505 505 var root= 506 506 document.getElementById("xwikicontent")|| ... ... @@ -510,93 +510,105 @@ 510 510 511 511 if(!root)return; 512 512 513 - var heightManaged=new Set(); 514 - var sectionManaged=new Set(); 515 - var originalMinHeight=new WeakMap(); 516 - var originalMarginTop=new WeakMap(); 517 - var raf=0; 590 + var managedHeight=new Set(); 591 + var managedMargin=new Set(); 592 + var originalHeight=new WeakMap(); 593 + var originalMargin=new WeakMap(); 518 518 519 - function num(v){ 520 - var n=parseFloat(v); 521 - return Number.isFinite(n)?n:0; 522 - } 595 + var resizeTimer=0; 596 + var running=false; 523 523 524 - function visible(el,minW,minH){ 525 - if(!el||el.nodeType!==1)return false; 526 - 527 - var s=getComputedStyle(el); 528 - 529 - if( 530 - s.display==="none"|| 531 - s.visibility==="hidden"|| 532 - Number(s.opacity)===0 533 - ){ 534 - return false; 598 + var THEMES=[ 599 + { 600 + name:"BLUE", 601 + accent:"#21b6d7", 602 + bg:"#eaf7fb", 603 + text:"#315d68", 604 + labels:[ 605 + "HIER STARTEN", 606 + "ENTSCHEIDEN", 607 + "ÜBERPRÜFEN & ANPASSEN", 608 + "START HERE", 609 + "DECIDE", 610 + "REVIEW & ADAPT" 611 + ] 612 + }, 613 + { 614 + name:"RED", 615 + accent:"#e94b13", 616 + bg:"#fff1ec", 617 + text:"#8a4d36", 618 + labels:[ 619 + "PLANEN & ORGANISIEREN", 620 + "ORGANISIEREN & DOKUMENTIEREN", 621 + "PUBLIZIEREN & PRÄSENTIEREN", 622 + "PLAN & ORGANISE", 623 + "PLAN & ORGANIZE", 624 + "ORGANISE & DOCUMENT", 625 + "ORGANIZE & DOCUMENT", 626 + "PUBLISH & PRESENT" 627 + ] 628 + }, 629 + { 630 + name:"YELLOW", 631 + accent:"#f0aa00", 632 + bg:"#fff8e7", 633 + text:"#785b17", 634 + labels:[ 635 + "SCHÜTZEN & KLÄREN", 636 + "STANDARDISIEREN & IDENTIFIZIEREN", 637 + "ÖFFNEN, NACHNUTZEN & AUFFINDBAR MACHEN", 638 + "PROTECT & CLARIFY", 639 + "STANDARDISE & IDENTIFY", 640 + "STANDARDIZE & IDENTIFY", 641 + "OPEN, REUSE & MAKE FINDABLE" 642 + ] 643 + }, 644 + { 645 + name:"GREEN", 646 + accent:"#38b76a", 647 + bg:"#edf9f1", 648 + text:"#3f7451", 649 + labels:[ 650 + "INFRASTRUKTUR EINRICHTEN", 651 + "INFRASTRUKTUR & ZUSAMMENARBEIT EINRICHTEN", 652 + "SPEICHERN & ZUGRIFF STEUERN", 653 + "REPOSITORIUM, ERHALTEN & ÜBERGEBEN", 654 + "SET UP INFRASTRUCTURE", 655 + "SET UP INFRASTRUCTURE & COLLABORATION", 656 + "STORE & CONTROL ACCESS", 657 + "REPOSITORY, PRESERVE & HAND OVER" 658 + ] 535 535 } 660 + ]; 536 536 537 - var r=el.getBoundingClientRect(); 538 - 539 - return ( 540 - r.width>=(minW||1)&& 541 - r.height>=(minH||1) 542 - ); 662 + function num(value){ 663 + var n=parseFloat(value); 664 + return Number.isFinite(n)?n:0; 543 543 } 544 544 545 - function excluded(el){ 546 - return ( 547 - !el.matches|| 548 - el.matches( 549 - "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]" 550 - ) 551 - ); 667 + function norm(value){ 668 + return String(value||"") 669 + .replace(/\s+/g," ") 670 + .trim() 671 + .toUpperCase(); 552 552 } 553 553 554 - function namedLikeBox(el){ 555 - var c= 556 - typeof el.className==="string" 557 - ? el.className 558 - : ""; 674 + function visible(el){ 675 + if(!el||el.nodeType!==1)return false; 559 559 560 - r eturn/(^|[s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([s_-]|$)/i.test(c);561 - }677 + var style=getComputedStyle(el); 678 + var rect=el.getBoundingClientRect(); 562 562 563 - function boxLike(el){ 564 - if(!visible(el,MIN_W,MIN_H)||excluded(el))return false; 565 - 566 - var s=getComputedStyle(el); 567 - var r=el.getBoundingClientRect(); 568 - 569 - var border= 570 - num(s.borderTopWidth)+ 571 - num(s.borderRightWidth)+ 572 - num(s.borderBottomWidth)+ 573 - num(s.borderLeftWidth); 574 - 575 - var radius=Math.max( 576 - num(s.borderTopLeftRadius), 577 - num(s.borderTopRightRadius), 578 - num(s.borderBottomLeftRadius), 579 - num(s.borderBottomRightRadius) 580 - ); 581 - 582 - var bg= 583 - s.backgroundColor&& 584 - s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 585 - s.backgroundColor!=="transparent"; 586 - 587 - var shadow= 588 - s.boxShadow&& 589 - s.boxShadow!=="none"; 590 - 591 591 return ( 592 - namedLikeBox(el)||593 - b order>=1||594 - (bg&&radius>=3)||595 - (shadow&&r.width>=180)681 + style.display!=="none"&& 682 + style.visibility!=="hidden"&& 683 + rect.width>20&& 684 + rect.height>4 596 596 ); 597 597 } 598 598 599 - function save Original(el,map,property){688 + function saveStyle(el,map,property){ 600 600 if(map.has(el))return; 601 601 602 602 map.set(el,{ ... ... @@ -605,7 +605,7 @@ 605 605 }); 606 606 } 607 607 608 - function restore Original(el,map,property){697 + function restoreStyle(el,map,property){ 609 609 var original=map.get(el); 610 610 611 611 if(original&&original.value){ ... ... @@ -619,247 +619,249 @@ 619 619 } 620 620 } 621 621 622 - function reset(){ 623 - heightManaged.forEach(function(el){624 - restore Original(711 + function resetRuntime(){ 712 + managedHeight.forEach(function(el){ 713 + restoreStyle( 625 625 el, 626 - original MinHeight,715 + originalHeight, 627 627 "min-height" 628 628 ); 629 - 630 630 el.removeAttribute( 631 - "data-sn-equal-height -managed"719 + "data-sn-master-equal-height" 632 632 ); 633 633 }); 634 634 635 - sectionManaged.forEach(function(el){636 - restore Original(723 + managedMargin.forEach(function(el){ 724 + restoreStyle( 637 637 el, 638 - originalMargin Top,726 + originalMargin, 639 639 "margin-top" 640 640 ); 641 - 642 642 el.removeAttribute( 643 - "data-sn-first- section-aligned"730 + "data-sn-master-first-row" 644 644 ); 645 645 }); 646 646 647 - heightManaged.clear();648 - sectionManaged.clear();734 + managedHeight.clear(); 735 + managedMargin.clear(); 649 649 } 650 650 651 - function pickTarget(child){652 - if(!visible(child,MIN_W,MIN_H))return null;738 + function themeFor(text){ 739 + var value=norm(text); 653 653 654 - if(boxLike(child)){ 655 - return child; 741 + for(var i=0;i<THEMES.length;i++){ 742 + for(var j=0;j<THEMES[i].labels.length;j++){ 743 + var label=THEMES[i].labels[j]; 744 + 745 + if( 746 + value===label|| 747 + value.indexOf(label+" ")===0|| 748 + value.indexOf(label+" -")===0|| 749 + value.indexOf(label+" ·")===0 750 + ){ 751 + return THEMES[i]; 752 + } 753 + } 656 656 } 657 657 658 - varcr=child.getBoundingClientRect();659 - var q=[];756 + return null; 757 + } 660 660 661 - Array.from(child.children||[]).forEach(function(el){662 - q.push({el:el,depth:1});663 - });759 + /* ======================================================= 760 + PLACEHOLDER BADGE 761 + ======================================================= */ 664 664 665 - var best=null;666 - varbestScore=-Infinity;763 + function applyPlaceholderBadge(){ 764 + if(!PLACEHOLDER)return; 667 667 668 - while(q.length){ 669 - var item=q.shift(); 670 - var el=item.el; 766 + if( 767 + document.querySelector( 768 + ".sn-coming-soon-badge" 769 + ) 770 + ){ 771 + return; 772 + } 671 671 672 - if(!visible(el,MIN_W,MIN_H))continue; 774 + var title= 775 + document.querySelector( 776 + "#document-title" 777 + )|| 778 + document.querySelector( 779 + "h1" 780 + ); 673 673 674 - var r=el.getBoundingClientRect();782 + if(!title)return; 675 675 676 - if( 677 - r.width>=cr.width*.68&& 678 - boxLike(el) 679 - ){ 680 - var widthFit= 681 - 1-Math.min( 682 - 1, 683 - Math.abs(cr.width-r.width)/ 684 - Math.max(1,cr.width) 685 - ); 784 + var badge= 785 + document.createElement( 786 + "span" 787 + ); 686 686 687 - var topFit= 688 - 1-Math.min( 689 - 1, 690 - Math.abs(cr.top-r.top)/100 691 - ); 789 + badge.className= 790 + "sn-coming-soon-badge"; 692 692 693 - var score= 694 - widthFit*6+ 695 - topFit*3+ 696 - Math.min(r.height,900)/450+ 697 - Math.min(r.width*r.height,900000)/900000; 792 + badge.textContent= 793 + PLACEHOLDER_LABEL; 698 698 699 - if(score>bestScore){ 700 - best=el; 701 - bestScore=score; 702 - } 703 - } 795 + badge.setAttribute( 796 + "aria-label", 797 + PLACEHOLDER_LABEL 798 + ); 704 704 705 - if(item.depth<SEARCH_DEPTH){ 706 - Array.from(el.children||[]).forEach(function(next){ 707 - q.push({ 708 - el:next, 709 - depth:item.depth+1 710 - }); 711 - }); 712 - } 713 - } 714 - 715 - return best; 800 + title.appendChild( 801 + badge 802 + ); 716 716 } 717 717 718 - function groupsByVisualRow(entries){ 719 - var groups=[]; 805 + /* ======================================================= 806 + DETAIL PAGE OWN-ACCENT PROPAGATION 807 + ======================================================= */ 720 720 721 - entries 722 - .slice() 723 - .sort(function(a,b){ 724 - return ( 725 - a.rect.top-b.rect.top|| 726 - a.rect.left-b.rect.left 727 - ); 728 - }) 729 - .forEach(function(entry){ 730 - var group=null; 809 + function parseRGB(value){ 810 + var match=String(value||"").match( 811 + /rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i 812 + ); 731 731 732 - for(var i=0;i<groups.length;i++){ 733 - if( 734 - Math.abs( 735 - groups[i].top- 736 - entry.rect.top 737 - )<=ROW_TOLERANCE 738 - ){ 739 - group=groups[i]; 740 - break; 741 - } 742 - } 814 + if(!match)return null; 743 743 744 - if(!group){ 745 - group={ 746 - top:entry.rect.top, 747 - entries:[] 748 - }; 749 - groups.push(group); 750 - } 816 + return [ 817 + Number(match[1]), 818 + Number(match[2]), 819 + Number(match[3]) 820 + ]; 821 + } 751 751 752 - group.entries.push(entry); 753 - }); 754 - 755 - return groups; 823 + function distance(a,b){ 824 + return Math.sqrt( 825 + Math.pow(a[0]-b[0],2)+ 826 + Math.pow(a[1]-b[1],2)+ 827 + Math.pow(a[2]-b[2],2) 828 + ); 756 756 } 757 757 758 - function validHorizontalGroup(group){759 - if(group.entries.length<2)return false;831 + function paletteMatch(cssColor){ 832 + var rgb=parseRGB(cssColor); 760 760 761 - var lefts= 762 - group.entries 763 - .map(function(e){return e.rect.left;}) 764 - .sort(function(a,b){return a-b;}); 834 + if(!rgb)return null; 765 765 766 - if( 767 - lefts[lefts.length-1]- 768 - lefts[0]< 769 - 80 770 - ){ 771 - return false; 772 - } 836 + var palette=[ 837 + {hex:"#21b6d7",rgb:[33,182,215]}, 838 + {hex:"#e94b13",rgb:[233,75,19]}, 839 + {hex:"#f0aa00",rgb:[240,170,0]}, 840 + {hex:"#38b76a",rgb:[56,183,106]} 841 + ]; 773 773 774 - var widths= 775 - group.entries 776 - .map(function(e){return e.rect.width;}) 777 - .filter(function(w){return w>0;}); 843 + var best=null; 844 + var bestDistance=Infinity; 778 778 779 - if(widths.length<2)return false; 846 + palette.forEach(function(item){ 847 + var d=distance(rgb,item.rgb); 780 780 781 - var minWidth=Math.min.apply(Math,widths); 782 - var maxWidth=Math.max.apply(Math,widths); 849 + if(d<bestDistance){ 850 + best=item; 851 + bestDistance=d; 852 + } 853 + }); 783 783 784 - return ( 785 - maxWidth/ 786 - Math.max(1,minWidth)<= 787 - 1.9 788 - ); 855 + return bestDistance<=30 856 + ?best 857 + :null; 789 789 } 790 790 791 - function normalizeText(text){ 792 - return String(text||"") 793 - .replace(/s+/g," ") 794 - .trim() 795 - .toUpperCase(); 796 - } 860 + function propagateDetailAccents(){ 861 + if(PAGE_KIND!=="detail")return; 797 797 798 - function exactKnownFirstSection(el){ 799 - var text=normalizeText(el.textContent); 800 - 801 - return ( 802 - text==="HIER STARTEN"|| 803 - text==="ORGANISIEREN & DOKUMENTIEREN"|| 804 - text==="ENTSCHEIDEN"|| 805 - text==="START HERE"|| 806 - text==="GET STARTED"|| 807 - text==="ORGANISE & DOCUMENT"|| 808 - text==="ORGANIZE & DOCUMENT"|| 809 - text==="DECIDE" 810 - ); 811 - } 812 - 813 - function visuallyFirstSectionBar(card){ 814 - var cardRect=card.getBoundingClientRect(); 815 - var candidates=[]; 816 - 817 817 Array.from( 818 - card.querySelectorAll( 819 - "div,p,span,strong,h3,h4,h5,h6" 864 + root.querySelectorAll( 865 + ".arsn-call,.dmp-call,.ido-call,.pp-call,"+ 866 + ".arsn-source,.dmp-source,.ido-source,.pp-source" 820 820 ) 821 821 ).forEach(function(el){ 822 - if(!visible(el,20,6))return; 823 - if(excluded(el))return; 869 + if(!visible(el))return; 824 824 825 - var r=el.getBoundingClientRect(); 826 - var relativeTop=r.top-cardRect.top; 871 + var style=getComputedStyle(el); 827 827 828 828 if( 829 - relativeTop<45|| 830 - relativeTop>cardRect.height*.72 874 + num(style.borderTopWidth)>=2 831 831 ){ 832 - return; 876 + var match= 877 + paletteMatch( 878 + style.borderTopColor 879 + ); 880 + 881 + if(match){ 882 + el.style.setProperty( 883 + "border-left", 884 + "4px solid "+match.hex, 885 + "important" 886 + ); 887 + } 833 833 } 889 + }); 834 834 835 - var widthRatio= 836 - r.width/ 837 - Math.max(1,cardRect.width); 891 + // Warning families: explicit safety override. 892 + Array.from( 893 + root.querySelectorAll( 894 + ".arsn-warn,.dmp-warn,.ido-warn,.pp-warn,"+ 895 + ".warn,.warning,.warningmessage,.errormessage" 896 + ) 897 + ).forEach(function(el){ 898 + if(!visible(el))return; 838 838 839 - if( 840 - widthRatio<.55|| 841 - widthRatio>1.05|| 842 - r.height>54 843 - ){ 844 - return; 845 - } 900 + el.style.setProperty( 901 + "border-left", 902 + "4px solid #e94b13", 903 + "important" 904 + ); 905 + }); 846 846 847 - var text=normalizeText(el.textContent); 907 + // Info families: explicit orientation override. 908 + Array.from( 909 + root.querySelectorAll( 910 + ".arsn-info,.dmp-info,.ido-info,.pp-info,.infomessage" 911 + ) 912 + ).forEach(function(el){ 913 + if(!visible(el))return; 848 848 849 - if( 850 - text.length<2|| 851 - text.length>90 852 - ){ 853 - return; 854 - } 915 + el.style.setProperty( 916 + "border-left", 917 + "4px solid #21b6d7", 918 + "important" 919 + ); 920 + }); 921 + } 855 855 856 - var style=getComputedStyle(el); 923 + /* ======================================================= 924 + OVERVIEW SEMANTIC THEME PALETTE 925 + ======================================================= */ 857 857 858 - var bg= 859 - style.backgroundColor&& 860 - style.backgroundColor!=="rgba(0, 0, 0, 0)"&& 861 - style.backgroundColor!=="transparent"; 927 + function smallestThemeHeaders(){ 928 + return Array.from( 929 + root.querySelectorAll( 930 + "div,span,p,strong,h3,h4,h5,h6" 931 + ) 932 + ).filter(function(el){ 933 + if(!visible(el))return false; 934 + if(!themeFor(el.textContent))return false; 862 862 936 + return !Array.from( 937 + el.children||[] 938 + ).some(function(child){ 939 + return !!themeFor( 940 + child.textContent 941 + ); 942 + }); 943 + }); 944 + } 945 + 946 + function findOverviewCard(header){ 947 + var node=header.parentElement; 948 + var candidates=[]; 949 + 950 + while(node&&node!==root){ 951 + var rect=node.getBoundingClientRect(); 952 + var style=getComputedStyle(node); 953 + 863 863 var border= 864 864 num(style.borderTopWidth)+ 865 865 num(style.borderRightWidth)+ ... ... @@ -866,315 +866,674 @@ 866 866 num(style.borderBottomWidth)+ 867 867 num(style.borderLeftWidth); 868 868 869 - var mostlyUpper= 870 - text.length>=3&& 871 - text===text.toUpperCase(); 872 - 873 - var exact=exactKnownFirstSection(el); 874 - 875 - var score= 876 - (exact?20:0)+ 877 - (bg?6:0)+ 878 - (border>=1?2:0)+ 879 - (mostlyUpper?4:0)+ 880 - (num(style.fontWeight)>=600?1:0); 881 - 882 - if(score>=7){ 883 - candidates.push({ 884 - el:el, 885 - relativeTop:relativeTop, 886 - width:r.width, 887 - score:score 888 - }); 960 + if( 961 + rect.width>=220&& 962 + rect.width<=800&& 963 + rect.height>=120&& 964 + border>=1 965 + ){ 966 + candidates.push(node); 889 889 } 890 - }); 891 891 969 + node=node.parentElement; 970 + } 971 + 892 892 if(!candidates.length)return null; 893 893 894 894 candidates.sort(function(a,b){ 895 - if(a.score!==b.score)return b.score-a.score; 896 - if(Math.abs(a.relativeTop-b.relativeTop)>3){ 897 - return a.relativeTop-b.relativeTop; 898 - } 899 - return b.width-a.width; 975 + return ( 976 + b.getBoundingClientRect().height- 977 + a.getBoundingClientRect().height 978 + ); 900 900 }); 901 901 902 - // For exact known labels always prefer the earliest exact match. 903 - var exacts=candidates.filter(function(c){ 904 - return exactKnownFirstSection(c.el); 905 - }); 981 + return candidates[0]; 982 + } 906 906 907 - if(exacts.length){ 908 - exacts.sort(function(a,b){ 909 - return a.relativeTop-b.relativeTop||b.width-a.width; 910 - }); 911 - return exacts[0].el; 912 - } 984 + function rowCandidates(link,card){ 985 + var result=[]; 986 + var cardRect= 987 + card.getBoundingClientRect(); 913 913 914 - // Generic fallback: earliest high-confidence bar. 915 - candidates.sort(function(a,b){ 916 - return a.relativeTop-b.relativeTop||b.score-a.score||b.width-a.width; 917 - }); 989 + var node=link; 918 918 919 - return candidates[0].el; 920 - } 991 + while(node&&node!==card){ 992 + if(visible(node)){ 993 + var rect= 994 + node.getBoundingClientRect(); 921 921 922 - function alignFirstSections(cards){ 923 - var rows= 924 - cards.map(function(card){ 925 - var bar= 926 - visuallyFirstSectionBar(card); 996 + if( 997 + rect.height<=105&& 998 + rect.width>= 999 + cardRect.width*.50&& 1000 + rect.width<= 1001 + cardRect.width*1.03 1002 + ){ 1003 + result.push(node); 1004 + } 1005 + } 927 927 928 - if(!bar)return null; 1007 + node=node.parentElement; 1008 + } 929 929 930 - varcardRect=931 - card.getBoundingClientRect();1010 + return result; 1011 + } 932 932 933 - var barRect= 934 - bar.getBoundingClientRect(); 1013 + function chooseOuterRow( 1014 + candidates, 1015 + link 1016 + ){ 1017 + if(!candidates.length){ 1018 + return link; 1019 + } 935 935 936 - return {937 - card:card,938 - bar:bar,939 - relativeTop:940 - barRect.top-cardRect.top,941 - label:942 - normalizeText(bar.textContent)943 - };1021 + var bordered= 1022 + candidates.filter(function(el){ 1023 + return ( 1024 + num( 1025 + getComputedStyle(el) 1026 + .borderLeftWidth 1027 + )>=1 1028 + ); 944 944 }); 945 945 946 - // Conservative: only align when every card in the horizontal row 947 - // has a reliable first section bar. 948 - if( 949 - rows.some(function(row){ 950 - return !row; 951 - }) 952 - ){ 953 - return null; 1031 + var pool= 1032 + bordered.length 1033 + ?bordered 1034 + :candidates; 1035 + 1036 + pool.sort(function(a,b){ 1037 + var ar= 1038 + a.getBoundingClientRect(); 1039 + 1040 + var br= 1041 + b.getBoundingClientRect(); 1042 + 1043 + return ( 1044 + ar.left-br.left|| 1045 + br.width-ar.width 1046 + ); 1047 + }); 1048 + 1049 + return pool[0]||link; 1050 + } 1051 + 1052 + function applyOverviewPalette(){ 1053 + if(PAGE_KIND!=="overview"){ 1054 + return []; 954 954 } 955 955 956 - var targetTop= 957 - Math.max.apply( 958 - Math, 959 - rows.map(function(row){ 960 - return row.relativeTop; 1057 + var headers= 1058 + smallestThemeHeaders() 1059 + .map(function(el){ 1060 + return { 1061 + el:el, 1062 + theme: 1063 + themeFor( 1064 + el.textContent 1065 + ), 1066 + card: 1067 + findOverviewCard( 1068 + el 1069 + ) 1070 + }; 961 961 }) 962 - ); 1072 + .filter(function(row){ 1073 + return !!row.card; 1074 + }); 963 963 964 - rows.forEach(function(row){ 965 - var delta= 966 - targetTop- 967 - row.relativeTop; 1076 + var unique=[]; 1077 + var seenHeaders=new Set(); 968 968 969 - if(delta<=1)return; 1079 + headers.forEach(function(row){ 1080 + var key= 1081 + row.theme.name+ 1082 + "|"+ 1083 + Math.round( 1084 + row.card 1085 + .getBoundingClientRect() 1086 + .left 1087 + )+ 1088 + "|"+ 1089 + Math.round( 1090 + row.el 1091 + .getBoundingClientRect() 1092 + .top 1093 + ); 970 970 971 - saveOriginal( 972 - row.bar, 973 - originalMarginTop, 974 - "margin-top" 1095 + if(!seenHeaders.has(key)){ 1096 + seenHeaders.add(key); 1097 + unique.push(row); 1098 + } 1099 + }); 1100 + 1101 + unique.forEach(function(row){ 1102 + var headerRect= 1103 + row.el 1104 + .getBoundingClientRect(); 1105 + 1106 + row.el.style.setProperty( 1107 + "background", 1108 + row.theme.bg, 1109 + "important" 975 975 ); 976 976 977 - var currentMargin= 978 - num( 979 - getComputedStyle( 980 - row.bar 981 - ).marginTop 982 - ); 1112 + row.el.style.setProperty( 1113 + "color", 1114 + row.theme.text, 1115 + "important" 1116 + ); 983 983 984 - row.bar.style.setProperty( 985 - "margin-top", 986 - ( 987 - currentMargin+ 988 - delta 989 - )+"px" 1118 + row.el.style.setProperty( 1119 + "text-align", 1120 + "left", 1121 + "important" 990 990 ); 991 991 992 - row.bar.setAttribute( 993 - "data-sn-first-section-aligned", 994 - "4" 1124 + row.el.style.setProperty( 1125 + "word-spacing", 1126 + "normal", 1127 + "important" 995 995 ); 996 996 997 - sectionManaged.add(row.bar); 1130 + var later= 1131 + unique 1132 + .filter(function(other){ 1133 + return ( 1134 + other.card===row.card&& 1135 + other.el 1136 + .getBoundingClientRect() 1137 + .top> 1138 + headerRect.top+2 1139 + ); 1140 + }) 1141 + .sort(function(a,b){ 1142 + return ( 1143 + a.el 1144 + .getBoundingClientRect() 1145 + .top- 1146 + b.el 1147 + .getBoundingClientRect() 1148 + .top 1149 + ); 1150 + }); 1151 + 1152 + var stopTop= 1153 + later.length 1154 + ?later[0].el 1155 + .getBoundingClientRect() 1156 + .top 1157 + :Infinity; 1158 + 1159 + Array.from( 1160 + row.card.querySelectorAll("a") 1161 + ).forEach(function(link){ 1162 + if(!visible(link))return; 1163 + 1164 + var rect= 1165 + link.getBoundingClientRect(); 1166 + 1167 + if( 1168 + rect.top<= 1169 + headerRect.bottom-2|| 1170 + rect.top>= 1171 + stopTop-2 1172 + ){ 1173 + return; 1174 + } 1175 + 1176 + var candidates= 1177 + rowCandidates( 1178 + link, 1179 + row.card 1180 + ); 1181 + 1182 + var target= 1183 + chooseOuterRow( 1184 + candidates, 1185 + link 1186 + ); 1187 + 1188 + candidates.forEach(function(el){ 1189 + el.style.setProperty( 1190 + "border-left", 1191 + "0 solid transparent", 1192 + "important" 1193 + ); 1194 + }); 1195 + 1196 + target.style.setProperty( 1197 + "border-left", 1198 + "3px solid "+ 1199 + row.theme.accent, 1200 + "important" 1201 + ); 1202 + 1203 + target.style.setProperty( 1204 + "box-sizing", 1205 + "border-box", 1206 + "important" 1207 + ); 1208 + }); 998 998 }); 999 999 1000 - return { 1001 - labels: 1002 - rows.map(function(row){ 1003 - return row.label; 1004 - }), 1005 - targetRelativeTop: 1006 - Math.round(targetTop) 1007 - }; 1211 + return unique; 1008 1008 } 1009 1009 1010 - function applyGroup(group){ 1011 - if(!validHorizontalGroup(group)){ 1012 - return null; 1214 + /* ======================================================= 1215 + OVERVIEW CARD HEIGHT + FIRST THEMATIC ROW 1216 + ======================================================= */ 1217 + 1218 + function alignOverviewCards(headers){ 1219 + if( 1220 + PAGE_KIND!=="overview"|| 1221 + window.innerWidth<=MOBILE_MAX 1222 + ){ 1223 + return; 1013 1013 } 1014 1014 1015 1015 var cards=[]; 1016 1016 var seen=new Set(); 1017 1017 1018 - group.entries.forEach(function(entry){1019 - if(!seen.has( entry.target)){1020 - seen.add( entry.target);1021 - cards.push( entry.target);1229 + headers.forEach(function(row){ 1230 + if(!seen.has(row.card)){ 1231 + seen.add(row.card); 1232 + cards.push(row.card); 1022 1022 } 1023 1023 }); 1024 1024 1025 - if(cards.length<2)return null; 1236 + if(cards.length<2){ 1237 + return; 1238 + } 1026 1026 1027 - varfirstSection=1028 - alignFirstSections(cards);1240 + // Group cards by actual top position. 1241 + var groups=[]; 1029 1029 1030 - // The section alignment can change natural card heights. 1031 - // Measure only afterwards. 1032 - var maxHeight=0; 1033 - 1034 1034 cards.forEach(function(card){ 1035 - maxHeight=Math.max( 1036 - maxHeight, 1037 - card.getBoundingClientRect().height 1038 - ); 1244 + var top= 1245 + card.getBoundingClientRect().top; 1246 + 1247 + var group=null; 1248 + 1249 + for(var i=0;i<groups.length;i++){ 1250 + if( 1251 + Math.abs( 1252 + groups[i].top-top 1253 + )<=ROW_TOLERANCE 1254 + ){ 1255 + group=groups[i]; 1256 + break; 1257 + } 1258 + } 1259 + 1260 + if(!group){ 1261 + group={ 1262 + top:top, 1263 + cards:[] 1264 + }; 1265 + groups.push(group); 1266 + } 1267 + 1268 + group.cards.push(card); 1039 1039 }); 1040 1040 1041 - maxHeight=Math.ceil(maxHeight); 1271 + groups.forEach(function(group){ 1272 + if(group.cards.length<2){ 1273 + return; 1274 + } 1042 1042 1043 - if(maxHeight<MIN_H)return null; 1276 + var firstHeaders= 1277 + group.cards.map(function(card){ 1278 + var candidates= 1279 + headers 1280 + .filter(function(row){ 1281 + return row.card===card; 1282 + }) 1283 + .sort(function(a,b){ 1284 + return ( 1285 + a.el 1286 + .getBoundingClientRect() 1287 + .top- 1288 + b.el 1289 + .getBoundingClientRect() 1290 + .top 1291 + ); 1292 + }); 1044 1044 1045 - cards.forEach(function(card){ 1046 - saveOriginal( 1047 - card, 1048 - originalMinHeight, 1049 - "min-height" 1050 - ); 1294 + return candidates.length 1295 + ?candidates[0] 1296 + :null; 1297 + }); 1051 1051 1052 - card.style.setProperty( 1053 - "min-height", 1054 - maxHeight+"px" 1055 - ); 1299 + if( 1300 + !firstHeaders.some(function(row){ 1301 + return !row; 1302 + }) 1303 + ){ 1304 + var targetTop= 1305 + Math.max.apply( 1306 + Math, 1307 + firstHeaders.map(function(row){ 1308 + return ( 1309 + row.el 1310 + .getBoundingClientRect() 1311 + .top- 1312 + row.card 1313 + .getBoundingClientRect() 1314 + .top 1315 + ); 1316 + }) 1317 + ); 1056 1056 1057 - card.setAttribute( 1058 - "data-sn-equal-height-managed", 1059 - "4" 1060 - ); 1319 + firstHeaders.forEach(function(row){ 1320 + var relativeTop= 1321 + row.el 1322 + .getBoundingClientRect() 1323 + .top- 1324 + row.card 1325 + .getBoundingClientRect() 1326 + .top; 1061 1061 1062 - heightManaged.add(card);1063 - });1328 + var delta= 1329 + targetTop-relativeTop; 1064 1064 1065 - return { 1066 - cards:cards.length, 1067 - height:maxHeight, 1068 - firstSection:firstSection 1069 - }; 1331 + if(delta>1){ 1332 + saveStyle( 1333 + row.el, 1334 + originalMargin, 1335 + "margin-top" 1336 + ); 1337 + 1338 + var current= 1339 + num( 1340 + getComputedStyle( 1341 + row.el 1342 + ).marginTop 1343 + ); 1344 + 1345 + row.el.style.setProperty( 1346 + "margin-top", 1347 + ( 1348 + current+delta 1349 + )+"px" 1350 + ); 1351 + 1352 + row.el.setAttribute( 1353 + "data-sn-master-first-row", 1354 + "1" 1355 + ); 1356 + 1357 + managedMargin.add( 1358 + row.el 1359 + ); 1360 + } 1361 + }); 1362 + } 1363 + 1364 + var maxHeight=0; 1365 + 1366 + group.cards.forEach(function(card){ 1367 + maxHeight= 1368 + Math.max( 1369 + maxHeight, 1370 + card 1371 + .getBoundingClientRect() 1372 + .height 1373 + ); 1374 + }); 1375 + 1376 + maxHeight= 1377 + Math.ceil(maxHeight); 1378 + 1379 + group.cards.forEach(function(card){ 1380 + saveStyle( 1381 + card, 1382 + originalHeight, 1383 + "min-height" 1384 + ); 1385 + 1386 + card.style.setProperty( 1387 + "min-height", 1388 + maxHeight+"px" 1389 + ); 1390 + 1391 + card.setAttribute( 1392 + "data-sn-master-equal-height", 1393 + "1" 1394 + ); 1395 + 1396 + managedHeight.add( 1397 + card 1398 + ); 1399 + }); 1400 + }); 1070 1070 } 1071 1071 1072 - function run(){ 1073 - reset(); 1403 + /* ======================================================= 1404 + DETAIL GRID EQUAL HEIGHT, DESKTOP ONLY 1405 + ======================================================= */ 1074 1074 1407 + function equaliseDetailGrids(){ 1075 1075 if( 1409 + PAGE_KIND!=="detail"|| 1076 1076 window.innerWidth<=MOBILE_MAX 1077 1077 ){ 1078 1078 return; 1079 1079 } 1080 1080 1081 - var parents= 1415 + var selectors=[ 1416 + ".arsn-grid", 1417 + ".arsn-grid-2", 1418 + ".arsn-grid-3", 1419 + ".dmp-grid", 1420 + ".ido-grid", 1421 + ".pp-grid" 1422 + ]; 1423 + 1424 + selectors.forEach(function(selector){ 1082 1082 Array.from( 1083 - root.querySelectorAll("*") 1084 - ).filter(function(parent){ 1085 - return ( 1086 - visible(parent,MIN_W,MIN_H)&& 1087 - parent.children&& 1088 - parent.children.length>=2&& 1089 - parent.children.length<=MAX_PARENT_CHILDREN 1090 - ); 1091 - }); 1426 + root.querySelectorAll(selector) 1427 + ).forEach(function(grid){ 1428 + var children= 1429 + Array.from( 1430 + grid.children||[] 1431 + ).filter(visible); 1092 1092 1093 - var touched=new Set(); 1433 + if(children.length<2){ 1434 + return; 1435 + } 1094 1094 1095 - parents.forEach(function(parent){ 1096 - var entries=[]; 1437 + var groups=[]; 1097 1097 1098 - Array.from(parent.children).forEach(function(child){ 1099 - if(!visible(child,MIN_W,MIN_H))return; 1439 + children.forEach(function(child){ 1440 + var top= 1441 + child 1442 + .getBoundingClientRect() 1443 + .top; 1100 1100 1101 - var target=pickTarget(child); 1102 - if(!target)return; 1445 + var group=null; 1103 1103 1104 - entries.push({ 1105 - target:target, 1106 - rect:target.getBoundingClientRect() 1447 + for(var i=0;i<groups.length;i++){ 1448 + if( 1449 + Math.abs( 1450 + groups[i].top-top 1451 + )<=ROW_TOLERANCE 1452 + ){ 1453 + group=groups[i]; 1454 + break; 1455 + } 1456 + } 1457 + 1458 + if(!group){ 1459 + group={ 1460 + top:top, 1461 + items:[] 1462 + }; 1463 + groups.push(group); 1464 + } 1465 + 1466 + group.items.push(child); 1107 1107 }); 1108 - }); 1109 1109 1110 - if(entries.length<2)return; 1469 + groups.forEach(function(group){ 1470 + if(group.items.length<2){ 1471 + return; 1472 + } 1111 1111 1112 - groupsByVisualRow(entries).forEach(function(group){ 1113 - if(!validHorizontalGroup(group))return; 1474 + var maxHeight=0; 1114 1114 1115 - var signature= 1116 - group.entries.map(function(entry){ 1117 - return entry.target; 1476 + group.items.forEach(function(item){ 1477 + maxHeight= 1478 + Math.max( 1479 + maxHeight, 1480 + item 1481 + .getBoundingClientRect() 1482 + .height 1483 + ); 1118 1118 }); 1119 1119 1120 - if( 1121 - !signature.some(function(el){ 1122 - return !touched.has(el); 1123 - }) 1124 - ){ 1125 - return; 1126 - } 1486 + maxHeight= 1487 + Math.ceil(maxHeight); 1127 1127 1128 - var applied= 1129 - applyGroup(group); 1489 + group.items.forEach(function(item){ 1490 + saveStyle( 1491 + item, 1492 + originalHeight, 1493 + "min-height" 1494 + ); 1130 1130 1131 - if(applied){ 1132 - signature.forEach(function(el){ 1133 - touched.add(el); 1496 + item.style.setProperty( 1497 + "min-height", 1498 + maxHeight+"px" 1499 + ); 1500 + 1501 + item.setAttribute( 1502 + "data-sn-master-equal-height", 1503 + "1" 1504 + ); 1505 + 1506 + managedHeight.add(item); 1134 1134 }); 1135 - } 1508 + }); 1136 1136 }); 1137 1137 }); 1138 1138 } 1139 1139 1140 - function schedule(){ 1141 - if(raf)cancelAnimationFrame(raf); 1513 + /* ======================================================= 1514 + RUN / RESPONSIVE SCHEDULING 1515 + ======================================================= */ 1142 1142 1143 - raf=requestAnimationFrame(function(){ 1144 - raf=requestAnimationFrame(function(){ 1145 - raf=0; 1146 - run(); 1147 - }); 1148 - }); 1517 + function run(){ 1518 + if(running)return; 1519 + 1520 + running=true; 1521 + 1522 + try{ 1523 + resetRuntime(); 1524 + applyPlaceholderBadge(); 1525 + propagateDetailAccents(); 1526 + 1527 + var headers= 1528 + applyOverviewPalette(); 1529 + 1530 + if( 1531 + window.innerWidth> 1532 + MOBILE_MAX 1533 + ){ 1534 + alignOverviewCards( 1535 + headers 1536 + ); 1537 + 1538 + equaliseDetailGrids(); 1539 + } 1540 + }finally{ 1541 + running=false; 1542 + } 1149 1149 } 1150 1150 1151 - addEventListener("resize",schedule,{passive:true}); 1152 - addEventListener("load",schedule,{once:true}); 1545 + function onResize(){ 1546 + if(resizeTimer){ 1547 + clearTimeout( 1548 + resizeTimer 1549 + ); 1550 + } 1153 1153 1154 - root.addEventListener( 1155 - "click", 1156 - function(){ 1157 - setTimeout(schedule,0); 1158 - }, 1159 - true 1160 - ); 1552 + resizeTimer= 1553 + setTimeout( 1554 + function(){ 1555 + resizeTimer=0; 1556 + run(); 1557 + }, 1558 + RESIZE_DEBOUNCE 1559 + ); 1560 + } 1161 1161 1162 - Array.from(root.querySelectorAll("img")).forEach(function(img){ 1163 - if(!img.complete){ 1164 - img.addEventListener("load",schedule,{once:true}); 1562 + async function waitForReady(){ 1563 + if( 1564 + document.readyState!=="complete" 1565 + ){ 1566 + await new Promise(function(resolve){ 1567 + window.addEventListener( 1568 + "load", 1569 + resolve, 1570 + {once:true} 1571 + ); 1572 + }); 1165 1165 } 1166 - }); 1167 1167 1168 - if(document.fonts&&document.fonts.ready){ 1169 - document.fonts.ready.then(schedule); 1575 + if( 1576 + document.fonts&& 1577 + document.fonts.ready 1578 + ){ 1579 + try{ 1580 + await document.fonts.ready; 1581 + }catch(error){} 1582 + } 1583 + 1584 + var images= 1585 + Array.from( 1586 + root.querySelectorAll("img") 1587 + ); 1588 + 1589 + await Promise.all( 1590 + images.map(function(img){ 1591 + if(img.complete){ 1592 + return Promise.resolve(); 1593 + } 1594 + 1595 + return new Promise(function(resolve){ 1596 + var done=function(){ 1597 + resolve(); 1598 + }; 1599 + 1600 + img.addEventListener( 1601 + "load", 1602 + done, 1603 + {once:true} 1604 + ); 1605 + 1606 + img.addEventListener( 1607 + "error", 1608 + done, 1609 + {once:true} 1610 + ); 1611 + }); 1612 + }) 1613 + ); 1614 + 1615 + run(); 1170 1170 } 1171 1171 1172 - schedule(); 1173 - setTimeout(schedule,200); 1174 - setTimeout(schedule,650); 1175 - setTimeout(schedule,1400); 1618 + window.addEventListener( 1619 + "resize", 1620 + onResize, 1621 + {passive:true} 1622 + ); 1623 + 1624 + waitForReady(); 1176 1176 })(); 1177 1177 </script> 1178 -<!-- SN_HORIZONTAL_BOX_HARMONIZER_END --> 1627 + 1628 +<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_END --> 1179 1179 {{/html}} 1180 1180