Changes for page Service Navigator
Last modified by Veronika Kocher on Thursday, 03 Sep 2026 14:15
From version 22.17
edited by Veronika Kocher
on Thursday, 03 Sep 2026 14:15
on Thursday, 03 Sep 2026 14:15
Change comment:
There is no comment for this version
To version 22.15
edited by Veronika Kocher
on Thursday, 03 Sep 2026 10:09
on Thursday, 03 Sep 2026 10:09
Change comment:
There is no comment for this version
Summary
-
Page properties (1 modified, 0 added, 0 removed)
Details
- Page properties
-
- Content
-
... ... @@ -285,13 +285,12 @@ 285 285 </div> 286 286 {{/html}} 287 287 288 -{{html clean="false"}} 289 -<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_START --> 288 +\n\n 289 +\n\n{{html clean="false"}} 290 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_START --> 290 290 291 -<style data-sn-service-navigator-master="1"> 292 -/* ========================================================= 293 - MASTER TYPOGRAPHY 294 - ========================================================= */ 292 +<style data-sn-horizontal-box-harmonizer="7"> 293 +/* ---------- Typography: never justify headings ---------- */ 295 295 #xwikicontent h1, 296 296 #xwikicontent h2, 297 297 #xwikicontent h3, ... ... @@ -313,105 +313,88 @@ 313 313 word-spacing:normal!important; 314 314 } 315 315 316 -/* ========================================================= 317 - COMING SOON / IN VORBEREITUNG 318 - ========================================================= */ 319 -.sn-coming-soon-badge{ 320 - display:inline-block; 321 - vertical-align:middle; 322 - margin-left:10px; 323 - padding:4px 8px; 324 - border-radius:14px; 325 - border:1px solid #efd9cc; 326 - background:#fff4ee; 327 - color:#8a4d36; 328 - font-size:11px; 329 - font-weight:700; 330 - letter-spacing:.055em; 331 - line-height:1.2; 332 - white-space:nowrap; 333 -} 334 - 335 -/* ========================================================= 336 - NATIVE / DETAIL CALLOUT GEOMETRY 337 - Preserve existing backgrounds. 338 - ========================================================= */ 339 -#xwikicontent .arsn-info, 340 -#xwikicontent .dmp-info, 341 -#xwikicontent .ido-info, 342 -#xwikicontent .pp-info, 343 -#xwikicontent .infomessage{ 315 +/* ---------- Native XWiki semantic callouts ---------- */ 316 +#xwikicontent .box.infomessage, 317 +#xwikicontent .infomessage, 318 +#xwikicontent .box.warningmessage, 319 +#xwikicontent .warningmessage, 320 +#xwikicontent .box.successmessage, 321 +#xwikicontent .successmessage, 322 +#xwikicontent .box.errormessage, 323 +#xwikicontent .errormessage, 324 +#xwikicontent [data-sn-callout-harmonized="1"]{ 344 344 box-sizing:border-box!important; 345 - border-left:4px solid #21b6d7!important; 346 - border-radius:8px; 326 + border-radius:8px!important; 327 + border-top:1px solid rgba(0,0,0,.08)!important; 328 + border-right:1px solid rgba(0,0,0,.08)!important; 329 + border-bottom:1px solid rgba(0,0,0,.08)!important; 330 + border-left:4px solid var(--sn-callout-accent,#21b6d7)!important; 331 + padding:14px 16px!important; 347 347 text-align:left!important; 333 + text-justify:auto!important; 348 348 word-spacing:normal!important; 335 + box-shadow:none!important; 349 349 } 350 350 351 -#xwikicontent .arsn-warn, 352 -#xwikicontent .dmp-warn, 353 -#xwikicontent .ido-warn, 354 -#xwikicontent .pp-warn, 355 -#xwikicontent .warn, 356 -#xwikicontent .warning, 357 -#xwikicontent .warningmessage, 338 +#xwikicontent .box.infomessage, 339 +#xwikicontent .infomessage{ 340 + --sn-callout-accent:#21b6d7; 341 + background:#eaf7fb!important; 342 +} 343 + 344 +#xwikicontent .box.warningmessage, 345 +#xwikicontent .warningmessage{ 346 + --sn-callout-accent:#f0aa00; 347 + background:#fff8e7!important; 348 +} 349 + 350 +#xwikicontent .box.successmessage, 351 +#xwikicontent .successmessage{ 352 + --sn-callout-accent:#38b76a; 353 + background:#edf9f1!important; 354 +} 355 + 356 +#xwikicontent .box.errormessage, 358 358 #xwikicontent .errormessage{ 359 - box-sizing:border-box!important; 360 - border-left:4px solid #e94b13!important; 361 - border-radius:8px; 362 - text-align:left!important; 363 - word-spacing:normal!important; 358 + --sn-callout-accent:#e94b13; 359 + background:#fff1ec!important; 364 364 } 365 365 366 -[data-sn-master-equal-height], 367 -[data-sn-master-first-row]{ 368 - box-sizing:border-box; 362 +#xwikicontent [data-sn-callout-harmonized="1"] > :first-child, 363 +#xwikicontent .infomessage > :first-child, 364 +#xwikicontent .warningmessage > :first-child, 365 +#xwikicontent .successmessage > :first-child, 366 +#xwikicontent .errormessage > :first-child{ 367 + margin-top:0!important; 369 369 } 370 370 371 -/* ========================================================= 372 - FULL-WIDTH THREE-LINE NUMBER / TITLE / SUBTITLE BLOCKS 373 - ========================================================= */ 374 -#xwikicontent .arsn-area-label[data-sn-three-line="1"]{ 375 - display:grid!important; 376 - grid-template-columns:minmax(0,1fr)!important; 377 - grid-auto-rows:auto!important; 378 - width:100%!important; 379 - max-width:none!important; 380 - box-sizing:border-box!important; 381 - justify-items:start!important; 382 - align-items:start!important; 383 - gap:2px!important; 384 - text-align:left!important; 385 - text-align-last:left!important; 386 - text-justify:auto!important; 387 - word-spacing:normal!important; 388 - white-space:normal!important; 370 +#xwikicontent [data-sn-callout-harmonized="1"] > :last-child, 371 +#xwikicontent .infomessage > :last-child, 372 +#xwikicontent .warningmessage > :last-child, 373 +#xwikicontent .successmessage > :last-child, 374 +#xwikicontent .errormessage > :last-child{ 375 + margin-bottom:0!important; 389 389 } 390 -#xwikicontent .arsn-area-label[data-sn-three-line="1"] > .arsn-area-number, 391 -#xwikicontent .arsn-area-label[data-sn-three-line="1"] > .sn-area-label-title, 392 -#xwikicontent .arsn-area-label[data-sn-three-line="1"] > .arsn-area-action{ 393 - display:block!important; 394 - width:100%!important; 395 - margin:0!important; 396 - text-align:left!important; 397 - text-align-last:left!important; 398 - text-justify:auto!important; 399 - word-spacing:normal!important; 400 - white-space:normal!important; 377 + 378 +#xwikicontent [data-sn-equal-height-managed], 379 +#xwikicontent [data-sn-first-section-aligned], 380 +#xwikicontent [data-sn-first-content-aligned]{ 381 + box-sizing:border-box; 401 401 } 402 402 </style> 403 403 404 -<script data-sn- service-navigator-master="1">385 +<script data-sn-horizontal-box-harmonizer="7"> 405 405 (function(){ 406 406 "use strict"; 407 407 408 - var PAGE_KIND="overview"; 409 - var PLACEHOLDER=false; 410 - var PLACEHOLDER_LABEL="COMING SOON"; 411 - 412 412 var MOBILE_MAX=767; 413 413 var ROW_TOLERANCE=6; 391 + var MIN_W=150; 392 + var MIN_H=36; 393 + var MAX_PARENT_CHILDREN=18; 394 + var SEARCH_DEPTH=5; 414 414 var RESIZE_DEBOUNCE=220; 396 + var MIN_WIDTH_CHANGE=2; 415 415 416 416 var root= 417 417 document.getElementById("xwikicontent")|| ... ... @@ -421,114 +421,142 @@ 421 421 422 422 if(!root)return; 423 423 424 - var managedHeight=new Set(); 425 - var managedMargin=new Set(); 426 - var originalHeight=new WeakMap(); 427 - var originalMargin=new WeakMap(); 406 + var heightManaged=new Set(); 407 + var sectionManaged=new Set(); 408 + var contentManaged=new Set(); 428 428 410 + var originalMinHeight=new WeakMap(); 411 + var originalMarginTop=new WeakMap(); 412 + 429 429 var resizeTimer=0; 430 - var running=false; 414 + var lastWidth=-1; 415 + var hasApplied=false; 416 + var applying=false; 431 431 432 - var THEMES=[ 433 - { 434 - name:"BLUE", 435 - accent:"#21b6d7", 436 - bg:"#eaf7fb", 437 - text:"#315d68", 438 - labels:[ 439 - "HIER STARTEN", 440 - "ENTSCHEIDEN", 441 - "ÜBERPRÜFEN & ANPASSEN", 442 - "START HERE", 443 - "DECIDE", 444 - "REVIEW & ADAPT" 445 - ] 446 - }, 447 - { 448 - name:"RED", 449 - accent:"#e94b13", 450 - bg:"#fff1ec", 451 - text:"#8a4d36", 452 - labels:[ 453 - "PLANEN & ORGANISIEREN", 454 - "ORGANISIEREN & DOKUMENTIEREN", 455 - "PUBLIZIEREN & PRÄSENTIEREN", 456 - "PLAN & ORGANISE", 457 - "PLAN & ORGANIZE", 458 - "ORGANISE & DOCUMENT", 459 - "ORGANIZE & DOCUMENT", 460 - "PUBLISH & PRESENT" 461 - ] 462 - }, 463 - { 464 - name:"YELLOW", 465 - accent:"#f0aa00", 466 - bg:"#fff8e7", 467 - text:"#785b17", 468 - labels:[ 469 - "SCHÜTZEN & KLÄREN", 470 - "STANDARDISIEREN & IDENTIFIZIEREN", 471 - "ÖFFNEN, NACHNUTZEN & AUFFINDBAR MACHEN", 472 - "PROTECT & CLARIFY", 473 - "STANDARDISE & IDENTIFY", 474 - "STANDARDIZE & IDENTIFY", 475 - "OPEN, REUSE & MAKE FINDABLE" 476 - ] 477 - }, 478 - { 479 - name:"GREEN", 480 - accent:"#38b76a", 481 - bg:"#edf9f1", 482 - text:"#3f7451", 483 - labels:[ 484 - "INFRASTRUKTUR EINRICHTEN", 485 - "INFRASTRUKTUR & ZUSAMMENARBEIT EINRICHTEN", 486 - "SPEICHERN & ZUGRIFF STEUERN", 487 - "REPOSITORIUM, ERHALTEN & ÜBERGEBEN", 488 - "SET UP INFRASTRUCTURE", 489 - "SET UP INFRASTRUCTURE & COLLABORATION", 490 - "STORE & CONTROL ACCESS", 491 - "REPOSITORY, PRESERVE & HAND OVER" 492 - ] 418 + function num(v){ 419 + var n=parseFloat(v); 420 + return Number.isFinite(n)?n:0; 421 + } 422 + 423 + function visible(el,minW,minH){ 424 + if(!el||el.nodeType!==1)return false; 425 + 426 + var s=getComputedStyle(el); 427 + 428 + if( 429 + s.display==="none"|| 430 + s.visibility==="hidden"|| 431 + Number(s.opacity)===0 432 + ){ 433 + return false; 493 493 } 494 - ]; 495 495 496 - function num(value){ 497 - var n=parseFloat(value); 498 - return Number.isFinite(n)?n:0; 436 + var r=el.getBoundingClientRect(); 437 + 438 + return ( 439 + r.width>=(minW||1)&& 440 + r.height>=(minH||1) 441 + ); 499 499 } 500 500 501 - function norm (value){502 - return String( value||"")444 + function normalizeText(text){ 445 + return String(text||"") 503 503 .replace(/\s+/g," ") 504 504 .trim() 505 505 .toUpperCase(); 506 506 } 507 507 508 - function visible(el){ 509 - if(!el||el.nodeType!==1)return false; 451 + function excluded(el){ 452 + return ( 453 + !el.matches|| 454 + el.matches( 455 + "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]" 456 + ) 457 + ); 458 + } 510 510 511 - var style=getComputedStyle(el); 512 - var rect=el.getBoundingClientRect(); 460 + /* ---------- Custom coloured callouts ---------- */ 513 513 462 + function nativeCallout(el){ 463 + var c= 464 + typeof el.className==="string" 465 + ? el.className.toLowerCase() 466 + : ""; 467 + 514 514 return ( 515 - style.display!=="none"&& 516 - style.visibility!=="hidden"&& 517 - rect.width>20&& 518 - rect.height>4 469 + /(^|\s)(infomessage|warningmessage|successmessage|errormessage)(\s|$)/.test(c) 519 519 ); 520 520 } 521 521 522 - function saveStyle(el,map,property){ 473 + function customCallout(el){ 474 + if(!visible(el,220,42)||excluded(el))return false; 475 + 476 + var r=el.getBoundingClientRect(); 477 + 478 + if(r.height>520)return false; 479 + 480 + var s=getComputedStyle(el); 481 + 482 + var bg= 483 + s.backgroundColor&& 484 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 485 + s.backgroundColor!=="transparent"&& 486 + s.backgroundColor!=="rgb(255, 255, 255)"; 487 + 488 + var left= 489 + num(s.borderLeftWidth); 490 + 491 + return ( 492 + bg&& 493 + left>=2 494 + ); 495 + } 496 + 497 + function harmoniseCustomCallouts(){ 498 + Array.from( 499 + root.querySelectorAll( 500 + "div,aside,section" 501 + ) 502 + ).forEach(function(el){ 503 + if(nativeCallout(el))return; 504 + if(!customCallout(el))return; 505 + 506 + var s=getComputedStyle(el); 507 + 508 + el.setAttribute( 509 + "data-sn-callout-harmonized", 510 + "1" 511 + ); 512 + 513 + if( 514 + s.borderLeftColor 515 + ){ 516 + el.style.setProperty( 517 + "--sn-callout-accent", 518 + s.borderLeftColor 519 + ); 520 + } 521 + }); 522 + } 523 + 524 + /* ---------- Restore only values V7 itself changed ---------- */ 525 + 526 + function saveOriginal(el,map,property){ 523 523 if(map.has(el))return; 524 524 525 525 map.set(el,{ 526 - value:el.style.getPropertyValue(property), 527 - priority:el.style.getPropertyPriority(property) 530 + value: 531 + el.style.getPropertyValue( 532 + property 533 + ), 534 + priority: 535 + el.style.getPropertyPriority( 536 + property 537 + ) 528 528 }); 529 529 } 530 530 531 - function restore Style(el,map,property){541 + function restoreOriginal(el,map,property){ 532 532 var original=map.get(el); 533 533 534 534 if(original&&original.value){ ... ... @@ -538,1069 +538,770 @@ 538 538 original.priority||"" 539 539 ); 540 540 }else{ 541 - el.style.removeProperty(property); 551 + el.style.removeProperty( 552 + property 553 + ); 542 542 } 543 543 } 544 544 545 545 function resetRuntime(){ 546 - managedHeight.forEach(function(el){547 - restore Style(558 + heightManaged.forEach(function(el){ 559 + restoreOriginal( 548 548 el, 549 - originalHeight, 561 + originalMinHeight, 550 550 "min-height" 551 551 ); 564 + 552 552 el.removeAttribute( 553 - "data-sn- master-equal-height"566 + "data-sn-equal-height-managed" 554 554 ); 555 555 }); 556 556 557 - managedMargin.forEach(function(el){558 - restore Style(570 + sectionManaged.forEach(function(el){ 571 + restoreOriginal( 559 559 el, 560 - originalMargin, 573 + originalMarginTop, 561 561 "margin-top" 562 562 ); 576 + 563 563 el.removeAttribute( 564 - "data-sn- master-first-row"578 + "data-sn-first-section-aligned" 565 565 ); 566 566 }); 567 567 568 - managedHeight.clear(); 569 - managedMargin.clear(); 570 - } 582 + contentManaged.forEach(function(el){ 583 + restoreOriginal( 584 + el, 585 + originalMarginTop, 586 + "margin-top" 587 + ); 571 571 572 - function themeFor(text){ 573 - var value=norm(text); 589 + el.removeAttribute( 590 + "data-sn-first-content-aligned" 591 + ); 592 + }); 574 574 575 - for(var i=0;i<THEMES.length;i++){ 576 - for(var j=0;j<THEMES[i].labels.length;j++){ 577 - var label=THEMES[i].labels[j]; 578 - 579 - if( 580 - value===label|| 581 - value.indexOf(label+" ")===0|| 582 - value.indexOf(label+" -")===0|| 583 - value.indexOf(label+" ·")===0 584 - ){ 585 - return THEMES[i]; 586 - } 587 - } 588 - } 589 - 590 - return null; 594 + heightManaged.clear(); 595 + sectionManaged.clear(); 596 + contentManaged.clear(); 591 591 } 592 592 593 - /* ======================================================= 594 - BORDERLESS FILLED RED/ORANGE CTA BUTTONS 595 - ======================================================= */ 599 + /* ---------- Card detection ---------- */ 596 596 597 - function colourDistance(a,b){ 598 - return Math.sqrt( 599 - Math.pow(a[0]-b[0],2)+ 600 - Math.pow(a[1]-b[1],2)+ 601 - Math.pow(a[2]-b[2],2) 602 - ); 601 + function namedLikeBox(el){ 602 + var c= 603 + typeof el.className==="string" 604 + ? el.className 605 + : ""; 606 + 607 + return /(^|[\s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([\s_-]|$)/i.test(c); 603 603 } 604 604 605 - function makeFilledRedOrangeCTAsBorderless(){ 606 - var RED_ORANGE=[233,75,19]; 610 + function boxLike(el){ 611 + if( 612 + !visible(el,MIN_W,MIN_H)|| 613 + excluded(el) 614 + ){ 615 + return false; 616 + } 607 607 608 - Array.from( 609 - root.querySelectorAll( 610 - 'a,button,[role="button"],input[type="submit"],input[type="button"]' 611 - ) 612 - ).forEach(function(el){ 613 - if(!visible(el))return; 618 + var s=getComputedStyle(el); 619 + var r=el.getBoundingClientRect(); 614 614 615 - var style=getComputedStyle(el); 616 - var rgb=parseRGB(style.backgroundColor); 621 + var border= 622 + num(s.borderTopWidth)+ 623 + num(s.borderRightWidth)+ 624 + num(s.borderBottomWidth)+ 625 + num(s.borderLeftWidth); 617 617 618 - if(!rgb)return; 627 + var radius=Math.max( 628 + num(s.borderTopLeftRadius), 629 + num(s.borderTopRightRadius), 630 + num(s.borderBottomLeftRadius), 631 + num(s.borderBottomRightRadius) 632 + ); 619 619 620 - if( 621 - colourDistance( 622 - rgb, 623 - RED_ORANGE 624 - )>55 625 - ){ 626 - return; 627 - } 634 + var bg= 635 + s.backgroundColor&& 636 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 637 + s.backgroundColor!=="transparent"; 628 628 629 - var rect=el.getBoundingClientRect(); 639 + var shadow= 640 + s.boxShadow&& 641 + s.boxShadow!=="none"; 630 630 631 - if( 632 - rect.width<80|| 633 - rect.height<24 634 - ){ 635 - return; 636 - } 643 + return ( 644 + namedLikeBox(el)|| 645 + border>=1|| 646 + (bg&&radius>=3)|| 647 + (shadow&&r.width>=180) 648 + ); 649 + } 637 637 638 - el.style.setProperty( 639 - "border", 640 - "none", 641 - "important" 642 - ); 651 + function pickTarget(child){ 652 + if(!visible(child,MIN_W,MIN_H))return null; 643 643 644 - el.style.setProperty( 645 - "border-left", 646 - "none", 647 - "important" 648 - ); 654 + if(boxLike(child))return child; 649 649 650 - el.style.setProperty( 651 - "border-top", 652 - "none", 653 - "important" 654 - ); 656 + var cr=child.getBoundingClientRect(); 657 + var q=[]; 655 655 656 - el.style.setProperty( 657 - "border-right", 658 - "none", 659 - "important" 660 - ); 661 - 662 - el.style.setProperty( 663 - "border-bottom", 664 - "none", 665 - "important" 666 - ); 667 - 668 - el.style.setProperty( 669 - "box-shadow", 670 - "none", 671 - "important" 672 - ); 659 + Array.from(child.children||[]).forEach(function(el){ 660 + q.push({el:el,depth:1}); 673 673 }); 674 - } 675 675 676 - /* ======================================================= 677 - FULL-WIDTH THREE-LINE AREA LABELS 678 - ======================================================= */ 663 + var best=null; 664 + var bestScore=-Infinity; 679 679 680 - function compactText(value){ 681 - return String(value||"") 682 - .replace(/\s+/g," ") 683 - .trim(); 684 - } 666 + while(q.length){ 667 + var item=q.shift(); 668 + var el=item.el; 685 685 686 - function makeThreeLineAreaLabels(){ 687 - Array.from( 688 - root.querySelectorAll( 689 - ".arsn-area-label" 690 - ) 691 - ).forEach(function(label){ 692 - if( 693 - label.getAttribute( 694 - "data-sn-three-line" 695 - )==="1" 696 - ){ 697 - return; 698 - } 670 + if(!visible(el,MIN_W,MIN_H))continue; 699 699 700 - var number= 701 - label.querySelector( 702 - ":scope > .arsn-area-number" 703 - ); 672 + var r=el.getBoundingClientRect(); 704 704 705 - var action= 706 - label.querySelector( 707 - ":scope > .arsn-area-action" 708 - ); 709 - 710 710 if( 711 - !number||712 - !action675 + r.width>=cr.width*.68&& 676 + boxLike(el) 713 713 ){ 714 - return; 715 - } 678 + var widthFit= 679 + 1-Math.min( 680 + 1, 681 + Math.abs(cr.width-r.width)/ 682 + Math.max(1,cr.width) 683 + ); 716 716 717 - var clone= 718 - label.cloneNode(true); 685 + var topFit= 686 + 1-Math.min( 687 + 1, 688 + Math.abs(cr.top-r.top)/100 689 + ); 719 719 720 - var cloneNumber= 721 - clone.querySelector( 722 - ":scope > .arsn-area-number" 723 - ); 691 + var score= 692 + widthFit*6+ 693 + topFit*3+ 694 + Math.min(r.height,900)/450+ 695 + Math.min(r.width*r.height,900000)/900000; 724 724 725 - var cloneAction= 726 - clone.querySelector( 727 - ":scope > .arsn-area-action" 728 - ); 729 - 730 - if(cloneNumber){ 731 - cloneNumber.remove(); 697 + if(score>bestScore){ 698 + best=el; 699 + bestScore=score; 700 + } 732 732 } 733 733 734 - if(cloneAction){ 735 - cloneAction.remove(); 703 + if(item.depth<SEARCH_DEPTH){ 704 + Array.from(el.children||[]).forEach(function(next){ 705 + q.push({ 706 + el:next, 707 + depth:item.depth+1 708 + }); 709 + }); 736 736 } 711 + } 737 737 738 - var titleText= 739 - compactText( 740 - clone.textContent 741 - ); 713 + return best; 714 + } 742 742 743 - if(!titleText){ 744 - return; 745 - } 716 + function groupRows(entries){ 717 + var groups=[]; 746 746 747 - var numberNode= 748 - number.cloneNode(true); 749 - 750 - var actionNode= 751 - action.cloneNode(true); 752 - 753 - var titleNode= 754 - document.createElement( 755 - "span" 719 + entries 720 + .slice() 721 + .sort(function(a,b){ 722 + return ( 723 + a.rect.top-b.rect.top|| 724 + a.rect.left-b.rect.left 756 756 ); 726 + }) 727 + .forEach(function(entry){ 728 + var group=null; 757 757 758 - titleNode.className= 759 - "sn-area-label-title"; 730 + for(var i=0;i<groups.length;i++){ 731 + if( 732 + Math.abs( 733 + groups[i].top- 734 + entry.rect.top 735 + )<=ROW_TOLERANCE 736 + ){ 737 + group=groups[i]; 738 + break; 739 + } 740 + } 760 760 761 - titleNode.textContent= 762 - titleText; 742 + if(!group){ 743 + group={ 744 + top:entry.rect.top, 745 + entries:[] 746 + }; 747 + groups.push(group); 748 + } 763 763 764 - while(label.firstChild){ 765 - label.removeChild( 766 - label.firstChild 767 - ); 768 - } 750 + group.entries.push(entry); 751 + }); 769 769 770 - label.appendChild( 771 - numberNode 772 - ); 773 - 774 - label.appendChild( 775 - titleNode 776 - ); 777 - 778 - label.appendChild( 779 - actionNode 780 - ); 781 - 782 - label.setAttribute( 783 - "data-sn-three-line", 784 - "1" 785 - ); 786 - 787 - var head= 788 - label.closest( 789 - ".arsn-area-head" 790 - ); 791 - 792 - if(head){ 793 - head.style.setProperty( 794 - "width", 795 - "100%", 796 - "important" 797 - ); 798 - 799 - head.style.setProperty( 800 - "max-width", 801 - "100%", 802 - "important" 803 - ); 804 - 805 - head.style.setProperty( 806 - "box-sizing", 807 - "border-box", 808 - "important" 809 - ); 810 - } 811 - }); 753 + return groups; 812 812 } 813 813 814 - /* ======================================================= 815 - PLACEHOLDER BADGE 816 - ======================================================= */ 756 + function validRow(group){ 757 + if(group.entries.length<2)return false; 817 817 818 - function applyPlaceholderBadge(){ 819 - if(!PLACEHOLDER)return; 759 + var lefts= 760 + group.entries 761 + .map(function(e){return e.rect.left;}) 762 + .sort(function(a,b){return a-b;}); 820 820 821 821 if( 822 - document.querySelector(823 - ".sn-coming-soon-badge"824 - )765 + lefts[lefts.length-1]- 766 + lefts[0]< 767 + 80 825 825 ){ 826 - return; 769 + return false; 827 827 } 828 828 829 - var title= 830 - document.querySelector( 831 - "#document-title" 832 - )|| 833 - document.querySelector( 834 - "h1" 835 - ); 772 + var widths= 773 + group.entries 774 + .map(function(e){return e.rect.width;}) 775 + .filter(function(w){return w>0;}); 836 836 837 - if( !title)return;777 + if(widths.length<2)return false; 838 838 839 - var badge= 840 - document.createElement( 841 - "span" 842 - ); 779 + var minW= 780 + Math.min.apply(Math,widths); 843 843 844 - badge.className=845 - "sn-coming-soon-badge";782 + var maxW= 783 + Math.max.apply(Math,widths); 846 846 847 - badge.textContent= 848 - PLACEHOLDER_LABEL; 849 - 850 - badge.setAttribute( 851 - "aria-label", 852 - PLACEHOLDER_LABEL 785 + return ( 786 + maxW/ 787 + Math.max(1,minW)<= 788 + 1.9 853 853 ); 790 + } 854 854 855 - title.appendChild( 856 - badge 792 + /* ---------- Known ARSN first section bars ---------- */ 793 + 794 + function knownBar(el){ 795 + var text= 796 + normalizeText( 797 + el.textContent 798 + ); 799 + 800 + return ( 801 + text==="HIER STARTEN"|| 802 + text==="ORGANISIEREN & DOKUMENTIEREN"|| 803 + text==="ENTSCHEIDEN"|| 804 + text==="START HERE"|| 805 + text==="GET STARTED"|| 806 + text==="ORGANISE & DOCUMENT"|| 807 + text==="ORGANIZE & DOCUMENT"|| 808 + text==="DECIDE" 857 857 ); 858 858 } 859 859 860 - /*=======================================================861 - DETAIL PAGE OWN-ACCENT PROPAGATION862 - =======================================================*/812 + function findKnownBar(card){ 813 + var cardRect= 814 + card.getBoundingClientRect(); 863 863 864 - function parseRGB(value){ 865 - var match=String(value||"").match( 866 - /rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i 867 - ); 816 + var rows= 817 + Array.from( 818 + card.querySelectorAll( 819 + "div,p,span,strong,h3,h4,h5,h6" 820 + ) 821 + ) 822 + .filter(function(el){ 823 + if(!visible(el,20,6))return false; 824 + if(!knownBar(el))return false; 868 868 869 - if(!match)returnnull;826 + var r=el.getBoundingClientRect(); 870 870 871 - return [ 872 - Number(match[1]), 873 - Number(match[2]), 874 - Number(match[3]) 875 - ]; 876 - } 828 + var rel= 829 + r.top- 830 + cardRect.top; 877 877 878 - function distance(a,b){ 879 - return Math.sqrt( 880 - Math.pow(a[0]-b[0],2)+ 881 - Math.pow(a[1]-b[1],2)+ 882 - Math.pow(a[2]-b[2],2) 883 - ); 832 + return ( 833 + rel>=35&& 834 + rel<= 835 + cardRect.height*.75 836 + ); 837 + }) 838 + .sort(function(a,b){ 839 + return ( 840 + a.getBoundingClientRect().top- 841 + b.getBoundingClientRect().top 842 + ); 843 + }); 844 + 845 + return rows[0]||null; 884 884 } 885 885 886 - function paletteMatch(cssColor){ 887 - var rgb=parseRGB(cssColor); 848 + function alignKnownBars(cards){ 849 + var rows= 850 + cards.map(function(card){ 851 + var bar= 852 + findKnownBar(card); 888 888 889 - if(! rgb)return null;854 + if(!bar)return null; 890 890 891 - var palette=[ 892 - {hex:"#21b6d7",rgb:[33,182,215]}, 893 - {hex:"#e94b13",rgb:[233,75,19]}, 894 - {hex:"#f0aa00",rgb:[240,170,0]}, 895 - {hex:"#38b76a",rgb:[56,183,106]} 896 - ]; 856 + var cr= 857 + card.getBoundingClientRect(); 897 897 898 - var b est=null;899 - varbestDistance=Infinity;859 + var br= 860 + bar.getBoundingClientRect(); 900 900 901 - palette.forEach(function(item){ 902 - var d=distance(rgb,item.rgb); 862 + return { 863 + bar:bar, 864 + relativeTop: 865 + br.top- 866 + cr.top 867 + }; 868 + }); 903 903 904 - if(d<bestDistance){ 905 - best=item; 906 - bestDistance=d; 907 - } 908 - }); 870 + if( 871 + rows.some(function(row){ 872 + return !row; 873 + }) 874 + ){ 875 + return false; 876 + } 909 909 910 - return bestDistance<=30 911 - ?best 912 - :null; 913 - } 878 + var target= 879 + Math.max.apply( 880 + Math, 881 + rows.map(function(row){ 882 + return row.relativeTop; 883 + }) 884 + ); 914 914 915 - function propagateDetailAccents(){ 916 - if(PAGE_KIND!=="detail")return; 886 + rows.forEach(function(row){ 887 + var delta= 888 + target- 889 + row.relativeTop; 917 917 918 - Array.from( 919 - root.querySelectorAll( 920 - ".arsn-call,.dmp-call,.ido-call,.pp-call,"+ 921 - ".arsn-source,.dmp-source,.ido-source,.pp-source" 922 - ) 923 - ).forEach(function(el){ 924 - if(!visible(el))return; 891 + if(delta<=1)return; 925 925 926 - var style=getComputedStyle(el); 893 + saveOriginal( 894 + row.bar, 895 + originalMarginTop, 896 + "margin-top" 897 + ); 927 927 928 - if( 929 - num(style.borderTopWidth)>=2 930 - ){ 931 - var match= 932 - paletteMatch( 933 - style.borderTopColor 934 - ); 899 + var current= 900 + num( 901 + getComputedStyle( 902 + row.bar 903 + ).marginTop 904 + ); 935 935 936 - if(match){ 937 - el.style.setProperty( 938 - "border-left", 939 - "4px solid "+match.hex, 940 - "important" 941 - ); 942 - } 943 - } 944 - }); 906 + row.bar.style.setProperty( 907 + "margin-top", 908 + ( 909 + current+ 910 + delta 911 + )+"px" 912 + ); 945 945 946 - // Warning families: explicit safety override. 947 - Array.from( 948 - root.querySelectorAll( 949 - ".arsn-warn,.dmp-warn,.ido-warn,.pp-warn,"+ 950 - ".warn,.warning,.warningmessage,.errormessage" 951 - ) 952 - ).forEach(function(el){ 953 - if(!visible(el))return; 954 - 955 - el.style.setProperty( 956 - "border-left", 957 - "4px solid #e94b13", 958 - "important" 914 + row.bar.setAttribute( 915 + "data-sn-first-section-aligned", 916 + "7" 959 959 ); 960 - }); 961 961 962 - // Info families: explicit orientation override. 963 - Array.from( 964 - root.querySelectorAll( 965 - ".arsn-info,.dmp-info,.ido-info,.pp-info,.infomessage" 966 - ) 967 - ).forEach(function(el){ 968 - if(!visible(el))return; 969 - 970 - el.style.setProperty( 971 - "border-left", 972 - "4px solid #21b6d7", 973 - "important" 919 + sectionManaged.add( 920 + row.bar 974 974 ); 975 975 }); 923 + 924 + return true; 976 976 } 977 977 978 - /* ======================================================= 979 - OVERVIEW SEMANTIC THEME PALETTE 980 - ======================================================= */ 927 + /* ---------- Generic first content after heading ---------- */ 981 981 982 - function smallestThemeHeaders(){ 983 - return Array.from( 984 - root.querySelectorAll( 985 - "div,span,p,strong,h3,h4,h5,h6" 929 + function heading(card){ 930 + var cr= 931 + card.getBoundingClientRect(); 932 + 933 + var rows= 934 + Array.from( 935 + card.querySelectorAll( 936 + "h1,h2,h3,h4,h5,h6,.box-title,[role=heading]" 937 + ) 986 986 ) 987 - ).filter(function(el){ 988 - if(!visible(el))return false; 989 - if(!themeFor(el.textContent))return false; 939 + .filter(function(el){ 940 + if(!visible(el,20,8))return false; 990 990 991 - return !Array.from( 992 - el.children||[] 993 - ).some(function(child){ 994 - return !!themeFor( 995 - child.textContent 942 + var r=el.getBoundingClientRect(); 943 + 944 + var rel= 945 + r.top- 946 + cr.top; 947 + 948 + return ( 949 + rel>=0&& 950 + rel<= 951 + Math.min( 952 + 160, 953 + cr.height*.45 954 + ) 996 996 ); 956 + }) 957 + .sort(function(a,b){ 958 + return ( 959 + a.getBoundingClientRect().top- 960 + b.getBoundingClientRect().top 961 + ); 997 997 }); 998 - }); 963 + 964 + return rows[0]||null; 999 999 } 1000 1000 1001 - function findOverviewCard(header){ 1002 - var node=header.parentElement; 1003 - var candidates=[]; 967 + function firstContent(card,h){ 968 + if(!h)return null; 1004 1004 1005 - while(node&&node!==root){ 1006 - var rect=node.getBoundingClientRect(); 1007 - var style=getComputedStyle(node); 970 + var cr= 971 + card.getBoundingClientRect(); 1008 1008 1009 - var border= 1010 - num(style.borderTopWidth)+ 1011 - num(style.borderRightWidth)+ 1012 - num(style.borderBottomWidth)+ 1013 - num(style.borderLeftWidth); 973 + var hr= 974 + h.getBoundingClientRect(); 1014 1014 1015 - if( 1016 - rect.width>=220&& 1017 - rect.width<=800&& 1018 - rect.height>=120&& 1019 - border>=1 1020 - ){ 1021 - candidates.push(node); 1022 - } 976 + var rows= 977 + Array.from( 978 + card.querySelectorAll( 979 + "p,div,ul,ol,dl,blockquote" 980 + ) 981 + ) 982 + .filter(function(el){ 983 + if( 984 + el===h|| 985 + h.contains(el)|| 986 + el.contains(h) 987 + ){ 988 + return false; 989 + } 1023 1023 1024 - node=node.parentElement; 1025 - } 991 + if(!visible(el,30,8))return false; 1026 1026 1027 - if(!candidates.length)return null; 993 + var text= 994 + String(el.textContent||"") 995 + .replace(/\s+/g," ") 996 + .trim(); 1028 1028 1029 - candidates.sort(function(a,b){ 1030 - return ( 1031 - b.getBoundingClientRect().height- 1032 - a.getBoundingClientRect().height 1033 - ); 1034 - }); 998 + if(text.length<3)return false; 1035 1035 1036 - return candidates[0]; 1037 - } 1000 + var r=el.getBoundingClientRect(); 1038 1038 1039 - function rowCandidates(link,card){ 1040 - var result=[]; 1041 - var cardRect= 1042 - card.getBoundingClientRect(); 1002 + if( 1003 + r.top< 1004 + hr.bottom-1 1005 + ){ 1006 + return false; 1007 + } 1043 1043 1044 - var node=link; 1009 + if( 1010 + r.top-cr.top> 1011 + Math.min( 1012 + 280, 1013 + cr.height*.65 1014 + ) 1015 + ){ 1016 + return false; 1017 + } 1045 1045 1046 - while(node&&node!==card){ 1047 - if(visible(node)){ 1048 - var rect= 1049 - node.getBoundingClientRect(); 1050 - 1051 1051 if( 1052 - rect.height<=105&& 1053 - rect.width>= 1054 - cardRect.width*.50&& 1055 - rect.width<= 1056 - cardRect.width*1.03 1020 + r.height> 1021 + cr.height*.58 1057 1057 ){ 1058 - re sult.push(node);1023 + return false; 1059 1059 } 1060 - } 1061 1061 1062 - node=node.parentElement; 1063 - } 1026 + return true; 1027 + }) 1028 + .sort(function(a,b){ 1029 + var ar= 1030 + a.getBoundingClientRect(); 1064 1064 1065 - r eturnresult;1066 - }1032 + var br= 1033 + b.getBoundingClientRect(); 1067 1067 1068 - function chooseOuterRow( 1069 - candidates, 1070 - link 1071 - ){ 1072 - if(!candidates.length){ 1073 - return link; 1074 - } 1075 - 1076 - var bordered= 1077 - candidates.filter(function(el){ 1078 1078 return ( 1079 - num( 1080 - getComputedStyle(el) 1081 - .borderLeftWidth 1082 - )>=1 1036 + ar.top-br.top|| 1037 + ar.height-br.height 1083 1083 ); 1084 1084 }); 1085 1085 1086 - var pool= 1087 - bordered.length 1088 - ?bordered 1089 - :candidates; 1041 + return rows[0]||null; 1042 + } 1090 1090 1091 - pool.sort(function(a,b){ 1092 - var ar= 1093 - a.getBoundingClientRect(); 1044 + function alignGeneric(cards){ 1045 + var rows= 1046 + cards.map(function(card){ 1047 + var h= 1048 + heading(card); 1094 1094 1095 - var br= 1096 - b.getBoundingClientRect(); 1050 + var c= 1051 + firstContent( 1052 + card, 1053 + h 1054 + ); 1097 1097 1098 - return ( 1099 - ar.left-br.left|| 1100 - br.width-ar.width 1101 - ); 1102 - }); 1056 + if(!h||!c)return null; 1103 1103 1104 - r eturnpool[0]||link;1105 - }1058 + var cr= 1059 + card.getBoundingClientRect(); 1106 1106 1107 - function applyOverviewPalette(){ 1108 - if(PAGE_KIND!=="overview"){ 1109 - return []; 1061 + var rr= 1062 + c.getBoundingClientRect(); 1063 + 1064 + return { 1065 + content:c, 1066 + relativeTop: 1067 + rr.top-cr.top 1068 + }; 1069 + }); 1070 + 1071 + if( 1072 + rows.some(function(row){ 1073 + return !row; 1074 + }) 1075 + ){ 1076 + return false; 1110 1110 } 1111 1111 1112 - var headers= 1113 - smallestThemeHeaders() 1114 - .map(function(el){ 1115 - return { 1116 - el:el, 1117 - theme: 1118 - themeFor( 1119 - el.textContent 1120 - ), 1121 - card: 1122 - findOverviewCard( 1123 - el 1124 - ) 1125 - }; 1079 + var target= 1080 + Math.max.apply( 1081 + Math, 1082 + rows.map(function(row){ 1083 + return row.relativeTop; 1126 1126 }) 1127 - .filter(function(row){ 1128 - return !!row.card; 1129 - }); 1085 + ); 1130 1130 1131 - var unique=[]; 1132 - var seenHeaders=new Set(); 1087 + rows.forEach(function(row){ 1088 + var delta= 1089 + target- 1090 + row.relativeTop; 1133 1133 1134 - headers.forEach(function(row){ 1135 - var key= 1136 - row.theme.name+ 1137 - "|"+ 1138 - Math.round( 1139 - row.card 1140 - .getBoundingClientRect() 1141 - .left 1142 - )+ 1143 - "|"+ 1144 - Math.round( 1145 - row.el 1146 - .getBoundingClientRect() 1147 - .top 1148 - ); 1092 + if(delta<=1)return; 1149 1149 1150 - if(!seenHeaders.has(key)){ 1151 - seenHeaders.add(key); 1152 - unique.push(row); 1153 - } 1154 - }); 1155 - 1156 - unique.forEach(function(row){ 1157 - var headerRect= 1158 - row.el 1159 - .getBoundingClientRect(); 1160 - 1161 - row.el.style.setProperty( 1162 - "background", 1163 - row.theme.bg, 1164 - "important" 1094 + saveOriginal( 1095 + row.content, 1096 + originalMarginTop, 1097 + "margin-top" 1165 1165 ); 1166 1166 1167 - row.el.style.setProperty( 1168 - "color", 1169 - row.theme.text, 1170 - "important" 1171 - ); 1100 + var current= 1101 + num( 1102 + getComputedStyle( 1103 + row.content 1104 + ).marginTop 1105 + ); 1172 1172 1173 - row.el.style.setProperty( 1174 - "text-align", 1175 - "left", 1176 - "important" 1107 + row.content.style.setProperty( 1108 + "margin-top", 1109 + ( 1110 + current+ 1111 + delta 1112 + )+"px" 1177 1177 ); 1178 1178 1179 - row.el.style.setProperty( 1180 - "word-spacing", 1181 - "normal", 1182 - "important" 1115 + row.content.setAttribute( 1116 + "data-sn-first-content-aligned", 1117 + "7" 1183 1183 ); 1184 1184 1185 - var later= 1186 - unique 1187 - .filter(function(other){ 1188 - return ( 1189 - other.card===row.card&& 1190 - other.el 1191 - .getBoundingClientRect() 1192 - .top> 1193 - headerRect.top+2 1194 - ); 1195 - }) 1196 - .sort(function(a,b){ 1197 - return ( 1198 - a.el 1199 - .getBoundingClientRect() 1200 - .top- 1201 - b.el 1202 - .getBoundingClientRect() 1203 - .top 1204 - ); 1205 - }); 1206 - 1207 - var stopTop= 1208 - later.length 1209 - ?later[0].el 1210 - .getBoundingClientRect() 1211 - .top 1212 - :Infinity; 1213 - 1214 - Array.from( 1215 - row.card.querySelectorAll("a") 1216 - ).forEach(function(link){ 1217 - if(!visible(link))return; 1218 - 1219 - var rect= 1220 - link.getBoundingClientRect(); 1221 - 1222 - if( 1223 - rect.top<= 1224 - headerRect.bottom-2|| 1225 - rect.top>= 1226 - stopTop-2 1227 - ){ 1228 - return; 1229 - } 1230 - 1231 - var candidates= 1232 - rowCandidates( 1233 - link, 1234 - row.card 1235 - ); 1236 - 1237 - var target= 1238 - chooseOuterRow( 1239 - candidates, 1240 - link 1241 - ); 1242 - 1243 - candidates.forEach(function(el){ 1244 - el.style.setProperty( 1245 - "border-left", 1246 - "0 solid transparent", 1247 - "important" 1248 - ); 1249 - }); 1250 - 1251 - target.style.setProperty( 1252 - "border-left", 1253 - "3px solid "+ 1254 - row.theme.accent, 1255 - "important" 1256 - ); 1257 - 1258 - target.style.setProperty( 1259 - "box-sizing", 1260 - "border-box", 1261 - "important" 1262 - ); 1263 - }); 1120 + contentManaged.add( 1121 + row.content 1122 + ); 1264 1264 }); 1265 1265 1266 - return u nique;1125 + return true; 1267 1267 } 1268 1268 1269 - /* ======================================================= 1270 - OVERVIEW CARD HEIGHT + FIRST THEMATIC ROW 1271 - ======================================================= */ 1128 + function applyRow(group){ 1129 + if(!validRow(group))return false; 1272 1272 1273 - function alignOverviewCards(headers){ 1274 - if( 1275 - PAGE_KIND!=="overview"|| 1276 - window.innerWidth<=MOBILE_MAX 1277 - ){ 1278 - return; 1279 - } 1280 - 1281 1281 var cards=[]; 1282 1282 var seen=new Set(); 1283 1283 1284 - headers.forEach(function(row){1285 - if(!seen.has(r ow.card)){1286 - seen.add(r ow.card);1287 - cards.push(r ow.card);1134 + group.entries.forEach(function(entry){ 1135 + if(!seen.has(entry.target)){ 1136 + seen.add(entry.target); 1137 + cards.push(entry.target); 1288 1288 } 1289 1289 }); 1290 1290 1291 - if(cards.length<2){ 1292 - return; 1141 + if(cards.length<2)return false; 1142 + 1143 + if( 1144 + !alignKnownBars(cards) 1145 + ){ 1146 + alignGeneric(cards); 1293 1293 } 1294 1294 1295 - // Group cards by actual top position. 1296 - var groups=[]; 1149 + var maxHeight=0; 1297 1297 1298 1298 cards.forEach(function(card){ 1299 - var top= 1300 - card.getBoundingClientRect().top; 1301 - 1302 - var group=null; 1303 - 1304 - for(var i=0;i<groups.length;i++){ 1305 - if( 1306 - Math.abs( 1307 - groups[i].top-top 1308 - )<=ROW_TOLERANCE 1309 - ){ 1310 - group=groups[i]; 1311 - break; 1312 - } 1313 - } 1314 - 1315 - if(!group){ 1316 - group={ 1317 - top:top, 1318 - cards:[] 1319 - }; 1320 - groups.push(group); 1321 - } 1322 - 1323 - group.cards.push(card); 1152 + maxHeight= 1153 + Math.max( 1154 + maxHeight, 1155 + card.getBoundingClientRect().height 1156 + ); 1324 1324 }); 1325 1325 1326 - groups.forEach(function(group){1327 - if(group.cards.length<2){1328 - return;1329 - }1159 + maxHeight= 1160 + Math.ceil( 1161 + maxHeight 1162 + ); 1330 1330 1331 - var firstHeaders= 1332 - group.cards.map(function(card){ 1333 - var candidates= 1334 - headers 1335 - .filter(function(row){ 1336 - return row.card===card; 1337 - }) 1338 - .sort(function(a,b){ 1339 - return ( 1340 - a.el 1341 - .getBoundingClientRect() 1342 - .top- 1343 - b.el 1344 - .getBoundingClientRect() 1345 - .top 1346 - ); 1347 - }); 1164 + if(maxHeight<MIN_H)return false; 1348 1348 1349 - return candidates.length 1350 - ?candidates[0] 1351 - :null; 1352 - }); 1166 + cards.forEach(function(card){ 1167 + saveOriginal( 1168 + card, 1169 + originalMinHeight, 1170 + "min-height" 1171 + ); 1353 1353 1354 - if( 1355 - !firstHeaders.some(function(row){ 1356 - return !row; 1357 - }) 1358 - ){ 1359 - var targetTop= 1360 - Math.max.apply( 1361 - Math, 1362 - firstHeaders.map(function(row){ 1363 - return ( 1364 - row.el 1365 - .getBoundingClientRect() 1366 - .top- 1367 - row.card 1368 - .getBoundingClientRect() 1369 - .top 1370 - ); 1371 - }) 1372 - ); 1173 + card.style.setProperty( 1174 + "min-height", 1175 + maxHeight+"px" 1176 + ); 1373 1373 1374 - firstHeaders.forEach(function(row){ 1375 - var relativeTop= 1376 - row.el 1377 - .getBoundingClientRect() 1378 - .top- 1379 - row.card 1380 - .getBoundingClientRect() 1381 - .top; 1178 + card.setAttribute( 1179 + "data-sn-equal-height-managed", 1180 + "7" 1181 + ); 1382 1382 1383 - var delta=1384 - targetTop-relativeTop;1183 + heightManaged.add(card); 1184 + }); 1385 1385 1386 - if(delta>1){ 1387 - saveStyle( 1388 - row.el, 1389 - originalMargin, 1390 - "margin-top" 1391 - ); 1186 + return true; 1187 + } 1392 1392 1393 - var current= 1394 - num( 1395 - getComputedStyle( 1396 - row.el 1397 - ).marginTop 1398 - ); 1189 + function calculate(force){ 1190 + if(applying)return; 1399 1399 1400 - row.el.style.setProperty( 1401 - "margin-top", 1402 - ( 1403 - current+delta 1404 - )+"px" 1405 - ); 1192 + var width= 1193 + Math.round( 1194 + window.innerWidth 1195 + ); 1406 1406 1407 - row.el.setAttribute( 1408 - "data-sn-master-first-row", 1409 - "1" 1410 - ); 1197 + var meaningful= 1198 + lastWidth<0|| 1199 + Math.abs( 1200 + width- 1201 + lastWidth 1202 + )>= 1203 + MIN_WIDTH_CHANGE; 1411 1411 1412 - managedMargin.add( 1413 - row.el 1414 - ); 1415 - } 1416 - }); 1417 - } 1418 - 1419 - var maxHeight=0; 1420 - 1421 - group.cards.forEach(function(card){ 1422 - maxHeight= 1423 - Math.max( 1424 - maxHeight, 1425 - card 1426 - .getBoundingClientRect() 1427 - .height 1428 - ); 1429 - }); 1430 - 1431 - maxHeight= 1432 - Math.ceil(maxHeight); 1433 - 1434 - group.cards.forEach(function(card){ 1435 - saveStyle( 1436 - card, 1437 - originalHeight, 1438 - "min-height" 1439 - ); 1440 - 1441 - card.style.setProperty( 1442 - "min-height", 1443 - maxHeight+"px" 1444 - ); 1445 - 1446 - card.setAttribute( 1447 - "data-sn-master-equal-height", 1448 - "1" 1449 - ); 1450 - 1451 - managedHeight.add( 1452 - card 1453 - ); 1454 - }); 1455 - }); 1456 - } 1457 - 1458 - /* ======================================================= 1459 - DETAIL GRID EQUAL HEIGHT, DESKTOP ONLY 1460 - ======================================================= */ 1461 - 1462 - function equaliseDetailGrids(){ 1463 1463 if( 1464 - PAGE_KIND!=="detail"|| 1465 - window.innerWidth<=MOBILE_MAX 1206 + hasApplied&& 1207 + !force&& 1208 + !meaningful 1466 1466 ){ 1467 1467 return; 1468 1468 } 1469 1469 1470 - var selectors=[ 1471 - ".arsn-grid", 1472 - ".arsn-grid-2", 1473 - ".arsn-grid-3", 1474 - ".dmp-grid", 1475 - ".ido-grid", 1476 - ".pp-grid" 1477 - ]; 1213 + applying=true; 1478 1478 1479 - selectors.forEach(function(selector){ 1480 - Array.from( 1481 - root.querySelectorAll(selector) 1482 - ).forEach(function(grid){ 1483 - var children= 1484 - Array.from( 1485 - grid.children||[] 1486 - ).filter(visible); 1215 + try{ 1216 + harmoniseCustomCallouts(); 1487 1487 1488 - if(children.length<2){ 1489 - return; 1218 + if(width<=MOBILE_MAX){ 1219 + if(hasApplied){ 1220 + resetRuntime(); 1490 1490 } 1491 1491 1492 - var groups=[]; 1223 + hasApplied=false; 1224 + lastWidth=width; 1225 + return; 1226 + } 1493 1493 1494 - children.forEach(function(child){ 1495 - var top= 1496 - child 1497 - .getBoundingClientRect() 1498 - .top; 1228 + if(hasApplied){ 1229 + resetRuntime(); 1230 + } 1499 1499 1500 - var group=null; 1232 + var parents= 1233 + Array.from( 1234 + root.querySelectorAll("*") 1235 + ) 1236 + .filter(function(parent){ 1237 + return ( 1238 + visible( 1239 + parent, 1240 + MIN_W, 1241 + MIN_H 1242 + )&& 1243 + parent.children&& 1244 + parent.children.length>=2&& 1245 + parent.children.length<= 1246 + MAX_PARENT_CHILDREN 1247 + ); 1248 + }); 1501 1501 1502 - for(var i=0;i<groups.length;i++){ 1503 - if( 1504 - Math.abs( 1505 - groups[i].top-top 1506 - )<=ROW_TOLERANCE 1507 - ){ 1508 - group=groups[i]; 1509 - break; 1510 - } 1511 - } 1250 + var touched= 1251 + new Set(); 1512 1512 1513 - if(!group){ 1514 - group={ 1515 - top:top, 1516 - items:[] 1517 - }; 1518 - groups.push(group); 1519 - } 1253 + parents.forEach(function(parent){ 1254 + var entries=[]; 1520 1520 1521 - group.items.push(child); 1522 - }); 1523 - 1524 - groups.forEach(function(group){ 1525 - if(group.items.length<2){ 1256 + Array.from( 1257 + parent.children 1258 + ).forEach(function(child){ 1259 + if( 1260 + !visible( 1261 + child, 1262 + MIN_W, 1263 + MIN_H 1264 + ) 1265 + ){ 1526 1526 return; 1527 1527 } 1528 1528 1529 - var maxHeight=0; 1269 + var target= 1270 + pickTarget(child); 1530 1530 1531 - group.items.forEach(function(item){ 1532 - maxHeight= 1533 - Math.max( 1534 - maxHeight, 1535 - item 1536 - .getBoundingClientRect() 1537 - .height 1538 - ); 1272 + if(!target)return; 1273 + 1274 + entries.push({ 1275 + target:target, 1276 + rect: 1277 + target.getBoundingClientRect() 1539 1539 }); 1279 + }); 1540 1540 1541 - maxHeight= 1542 - Math.ceil(maxHeight); 1281 + groupRows( 1282 + entries 1283 + ).forEach(function(group){ 1284 + if(!validRow(group))return; 1543 1543 1544 - group.items.forEach(function(item){ 1545 - saveStyle( 1546 - item, 1547 - originalHeight, 1548 - "min-height" 1549 - ); 1286 + var targets= 1287 + group.entries.map(function(entry){ 1288 + return entry.target; 1289 + }); 1550 1550 1551 - item.style.setProperty( 1552 - "min-height", 1553 - maxHeight+"px" 1554 - ); 1291 + if( 1292 + !targets.some(function(el){ 1293 + return !touched.has(el); 1294 + }) 1295 + ){ 1296 + return; 1297 + } 1555 1555 1556 - item.setAttribute( 1557 - "data-sn-master-equal-height", 1558 - "1" 1559 - ); 1560 - 1561 - managedHeight.add(item); 1562 - }); 1299 + if(applyRow(group)){ 1300 + targets.forEach(function(el){ 1301 + touched.add(el); 1302 + }); 1303 + } 1563 1563 }); 1564 1564 }); 1565 - }); 1566 - } 1567 1567 1568 - /* ======================================================= 1569 - RUN / RESPONSIVE SCHEDULING 1570 - ======================================================= */ 1571 - 1572 - function run(){ 1573 - if(running)return; 1574 - 1575 - running=true; 1576 - 1577 - try{ 1578 - resetRuntime(); 1579 - applyPlaceholderBadge(); 1580 - propagateDetailAccents(); 1581 - 1582 - var headers= 1583 - applyOverviewPalette(); 1584 - 1585 - makeThreeLineAreaLabels(); 1586 - makeFilledRedOrangeCTAsBorderless(); 1587 - 1588 - if( 1589 - window.innerWidth> 1590 - MOBILE_MAX 1591 - ){ 1592 - alignOverviewCards( 1593 - headers 1594 - ); 1595 - 1596 - equaliseDetailGrids(); 1597 - } 1307 + lastWidth=width; 1308 + hasApplied=true; 1598 1598 }finally{ 1599 - running=false;1310 + applying=false; 1600 1600 } 1601 1601 } 1602 1602 1603 - function onResize(){1314 + function resize(){ 1604 1604 if(resizeTimer){ 1605 1605 clearTimeout( 1606 1606 resizeTimer ... ... @@ -1611,40 +1611,19 @@ 1611 1611 setTimeout( 1612 1612 function(){ 1613 1613 resizeTimer=0; 1614 - run();1325 + calculate(false); 1615 1615 }, 1616 1616 RESIZE_DEBOUNCE 1617 1617 ); 1618 1618 } 1619 1619 1620 - async function waitForReady(){ 1621 - if( 1622 - document.readyState!=="complete" 1623 - ){ 1624 - await new Promise(function(resolve){ 1625 - window.addEventListener( 1626 - "load", 1627 - resolve, 1628 - {once:true} 1629 - ); 1630 - }); 1631 - } 1632 - 1633 - if( 1634 - document.fonts&& 1635 - document.fonts.ready 1636 - ){ 1637 - try{ 1638 - await document.fonts.ready; 1639 - }catch(error){} 1640 - } 1641 - 1331 + function waitImages(){ 1642 1642 var images= 1643 1643 Array.from( 1644 1644 root.querySelectorAll("img") 1645 1645 ); 1646 1646 1647 - await Promise.all(1337 + return Promise.all( 1648 1648 images.map(function(img){ 1649 1649 if(img.complete){ 1650 1650 return Promise.resolve(); ... ... @@ -1669,20 +1669,46 @@ 1669 1669 }); 1670 1670 }) 1671 1671 ); 1362 + } 1672 1672 1673 - run(); 1364 + async function initial(){ 1365 + if( 1366 + document.readyState!== 1367 + "complete" 1368 + ){ 1369 + await new Promise(function(resolve){ 1370 + addEventListener( 1371 + "load", 1372 + resolve, 1373 + {once:true} 1374 + ); 1375 + }); 1376 + } 1377 + 1378 + if( 1379 + document.fonts&& 1380 + document.fonts.ready 1381 + ){ 1382 + try{ 1383 + await document.fonts.ready; 1384 + }catch(error){} 1385 + } 1386 + 1387 + await waitImages(); 1388 + 1389 + // Exactly one initial layout calculation. 1390 + calculate(true); 1674 1674 } 1675 1675 1676 - window.addEventListener(1393 + addEventListener( 1677 1677 "resize", 1678 - onResize,1395 + resize, 1679 1679 {passive:true} 1680 1680 ); 1681 1681 1682 - waitForReady();1399 + initial(); 1683 1683 })(); 1684 1684 </script> 1685 1685 1686 -<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_END --> 1687 -{{/html}} 1688 - 1403 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_END --> 1404 +{{/html}}\n