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

From version 5.14
edited by Veronika Kocher
on Friday, 04 Sep 2026 14:23
Change comment: There is no comment for this version
To version 5.10
edited by Veronika Kocher
on Thursday, 03 Sep 2026 10:09
Change comment: There is no comment for this version

Summary

Details

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