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

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