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.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,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>
... ... @@ -286,13 +286,12 @@
286 286  </div>
287 287  {{/html}}
288 288  
289 -{{html clean="false"}}
290 -<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_START -->
264 +\n\n
265 +\n\n{{html clean="false"}}
266 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_START -->
291 291  
292 -<style data-sn-service-navigator-master="1">
293 -/* =========================================================
294 - MASTER TYPOGRAPHY
295 - ========================================================= */
268 +<style data-sn-horizontal-box-harmonizer="7">
269 +/* ---------- Typography: never justify headings ---------- */
296 296  #xwikicontent h1,
297 297  #xwikicontent h2,
298 298  #xwikicontent h3,
... ... @@ -314,105 +314,88 @@
314 314   word-spacing:normal!important;
315 315  }
316 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{
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"]{
345 345   box-sizing:border-box!important;
346 - border-left:4px solid #21b6d7!important;
347 - 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;
348 348   text-align:left!important;
309 + text-justify:auto!important;
349 349   word-spacing:normal!important;
311 + box-shadow:none!important;
350 350  }
351 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,
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,
359 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;
334 + --sn-callout-accent:#e94b13;
335 + background:#fff1ec!important;
365 365  }
366 366  
367 -[data-sn-master-equal-height],
368 -[data-sn-master-first-row]{
369 - 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;
370 370  }
371 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;
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;
390 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;
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;
402 402  }
403 403  </style>
404 404  
405 -<script data-sn-service-navigator-master="1">
361 +<script data-sn-horizontal-box-harmonizer="7">
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;
367 + var MIN_W=150;
368 + var MIN_H=36;
369 + var MAX_PARENT_CHILDREN=18;
370 + var SEARCH_DEPTH=5;
415 415   var RESIZE_DEBOUNCE=220;
372 + var MIN_WIDTH_CHANGE=2;
416 416  
417 417   var root=
418 418   document.getElementById("xwikicontent")||
... ... @@ -422,114 +422,142 @@
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();
382 + var heightManaged=new Set();
383 + var sectionManaged=new Set();
384 + var contentManaged=new Set();
429 429  
386 + var originalMinHeight=new WeakMap();
387 + var originalMarginTop=new WeakMap();
388 +
430 430   var resizeTimer=0;
431 - var running=false;
390 + var lastWidth=-1;
391 + var hasApplied=false;
392 + var applying=false;
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 - ]
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;
494 494   }
495 - ];
496 496  
497 - function num(value){
498 - var n=parseFloat(value);
499 - 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 + );
500 500   }
501 501  
502 - function norm(value){
503 - return String(value||"")
420 + function normalizeText(text){
421 + return String(text||"")
504 504   .replace(/\s+/g," ")
505 505   .trim()
506 506   .toUpperCase();
507 507   }
508 508  
509 - function visible(el){
510 - 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 + }
511 511  
512 - var style=getComputedStyle(el);
513 - var rect=el.getBoundingClientRect();
436 + /* ---------- Custom coloured callouts ---------- */
514 514  
438 + function nativeCallout(el){
439 + var c=
440 + typeof el.className==="string"
441 + ? el.className.toLowerCase()
442 + : "";
443 +
515 515   return (
516 - style.display!=="none"&&
517 - style.visibility!=="hidden"&&
518 - rect.width>20&&
519 - rect.height>4
445 + /(^|\s)(infomessage|warningmessage|successmessage|errormessage)(\s|$)/.test(c)
520 520   );
521 521   }
522 522  
523 - 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){
524 524   if(map.has(el))return;
525 525  
526 526   map.set(el,{
527 - value:el.style.getPropertyValue(property),
528 - priority:el.style.getPropertyPriority(property)
506 + value:
507 + el.style.getPropertyValue(
508 + property
509 + ),
510 + priority:
511 + el.style.getPropertyPriority(
512 + property
513 + )
529 529   });
530 530   }
531 531  
532 - function restoreStyle(el,map,property){
517 + function restoreOriginal(el,map,property){
533 533   var original=map.get(el);
534 534  
535 535   if(original&&original.value){
... ... @@ -539,1069 +539,770 @@
539 539   original.priority||""
540 540   );
541 541   }else{
542 - el.style.removeProperty(property);
527 + el.style.removeProperty(
528 + property
529 + );
543 543   }
544 544   }
545 545  
546 546   function resetRuntime(){
547 - managedHeight.forEach(function(el){
548 - restoreStyle(
534 + heightManaged.forEach(function(el){
535 + restoreOriginal(
549 549   el,
550 - originalHeight,
537 + originalMinHeight,
551 551   "min-height"
552 552   );
540 +
553 553   el.removeAttribute(
554 - "data-sn-master-equal-height"
542 + "data-sn-equal-height-managed"
555 555   );
556 556   });
557 557  
558 - managedMargin.forEach(function(el){
559 - restoreStyle(
546 + sectionManaged.forEach(function(el){
547 + restoreOriginal(
560 560   el,
561 - originalMargin,
549 + originalMarginTop,
562 562   "margin-top"
563 563   );
552 +
564 564   el.removeAttribute(
565 - "data-sn-master-first-row"
554 + "data-sn-first-section-aligned"
566 566   );
567 567   });
568 568  
569 - managedHeight.clear();
570 - managedMargin.clear();
571 - }
558 + contentManaged.forEach(function(el){
559 + restoreOriginal(
560 + el,
561 + originalMarginTop,
562 + "margin-top"
563 + );
572 572  
573 - function themeFor(text){
574 - var value=norm(text);
565 + el.removeAttribute(
566 + "data-sn-first-content-aligned"
567 + );
568 + });
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 - }
589 - }
590 -
591 - return null;
570 + heightManaged.clear();
571 + sectionManaged.clear();
572 + contentManaged.clear();
592 592   }
593 593  
594 - /* =======================================================
595 - BORDERLESS FILLED RED/ORANGE CTA BUTTONS
596 - ======================================================= */
575 + /* ---------- Card detection ---------- */
597 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 - );
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);
604 604   }
605 605  
606 - function makeFilledRedOrangeCTAsBorderless(){
607 - 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 + }
608 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;
594 + var s=getComputedStyle(el);
595 + var r=el.getBoundingClientRect();
615 615  
616 - var style=getComputedStyle(el);
617 - var rgb=parseRGB(style.backgroundColor);
597 + var border=
598 + num(s.borderTopWidth)+
599 + num(s.borderRightWidth)+
600 + num(s.borderBottomWidth)+
601 + num(s.borderLeftWidth);
618 618  
619 - 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 + );
620 620  
621 - if(
622 - colourDistance(
623 - rgb,
624 - RED_ORANGE
625 - )>55
626 - ){
627 - return;
628 - }
610 + var bg=
611 + s.backgroundColor&&
612 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&&
613 + s.backgroundColor!=="transparent";
629 629  
630 - var rect=el.getBoundingClientRect();
615 + var shadow=
616 + s.boxShadow&&
617 + s.boxShadow!=="none";
631 631  
632 - if(
633 - rect.width<80||
634 - rect.height<24
635 - ){
636 - return;
637 - }
619 + return (
620 + namedLikeBox(el)||
621 + border>=1||
622 + (bg&&radius>=3)||
623 + (shadow&&r.width>=180)
624 + );
625 + }
638 638  
639 - el.style.setProperty(
640 - "border",
641 - "none",
642 - "important"
643 - );
627 + function pickTarget(child){
628 + if(!visible(child,MIN_W,MIN_H))return null;
644 644  
645 - el.style.setProperty(
646 - "border-left",
647 - "none",
648 - "important"
649 - );
630 + if(boxLike(child))return child;
650 650  
651 - el.style.setProperty(
652 - "border-top",
653 - "none",
654 - "important"
655 - );
632 + var cr=child.getBoundingClientRect();
633 + var q=[];
656 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 - );
635 + Array.from(child.children||[]).forEach(function(el){
636 + q.push({el:el,depth:1});
674 674   });
675 - }
676 676  
677 - /* =======================================================
678 - FULL-WIDTH THREE-LINE AREA LABELS
679 - ======================================================= */
639 + var best=null;
640 + var bestScore=-Infinity;
680 680  
681 - function compactText(value){
682 - return String(value||"")
683 - .replace(/\s+/g," ")
684 - .trim();
685 - }
642 + while(q.length){
643 + var item=q.shift();
644 + 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 - }
646 + if(!visible(el,MIN_W,MIN_H))continue;
700 700  
701 - var number=
702 - label.querySelector(
703 - ":scope > .arsn-area-number"
704 - );
648 + 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
651 + r.width>=cr.width*.68&&
652 + boxLike(el)
714 714   ){
715 - return;
716 - }
654 + var widthFit=
655 + 1-Math.min(
656 + 1,
657 + Math.abs(cr.width-r.width)/
658 + Math.max(1,cr.width)
659 + );
717 717  
718 - var clone=
719 - label.cloneNode(true);
661 + var topFit=
662 + 1-Math.min(
663 + 1,
664 + Math.abs(cr.top-r.top)/100
665 + );
720 720  
721 - var cloneNumber=
722 - clone.querySelector(
723 - ":scope > .arsn-area-number"
724 - );
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;
725 725  
726 - var cloneAction=
727 - clone.querySelector(
728 - ":scope > .arsn-area-action"
729 - );
730 -
731 - if(cloneNumber){
732 - cloneNumber.remove();
673 + if(score>bestScore){
674 + best=el;
675 + bestScore=score;
676 + }
733 733   }
734 734  
735 - if(cloneAction){
736 - 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 + });
737 737   }
687 + }
738 738  
739 - var titleText=
740 - compactText(
741 - clone.textContent
742 - );
689 + return best;
690 + }
743 743  
744 - if(!titleText){
745 - return;
746 - }
692 + function groupRows(entries){
693 + 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"
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
757 757   );
702 + })
703 + .forEach(function(entry){
704 + var group=null;
758 758  
759 - titleNode.className=
760 - "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 + }
761 761  
762 - titleNode.textContent=
763 - titleText;
718 + if(!group){
719 + group={
720 + top:entry.rect.top,
721 + entries:[]
722 + };
723 + groups.push(group);
724 + }
764 764  
765 - while(label.firstChild){
766 - label.removeChild(
767 - label.firstChild
768 - );
769 - }
726 + group.entries.push(entry);
727 + });
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 - });
729 + return groups;
813 813   }
814 814  
815 - /* =======================================================
816 - PLACEHOLDER BADGE
817 - ======================================================= */
732 + function validRow(group){
733 + if(group.entries.length<2)return false;
818 818  
819 - function applyPlaceholderBadge(){
820 - 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;});
821 821  
822 822   if(
823 - document.querySelector(
824 - ".sn-coming-soon-badge"
825 - )
741 + lefts[lefts.length-1]-
742 + lefts[0]<
743 + 80
826 826   ){
827 - return;
745 + return false;
828 828   }
829 829  
830 - var title=
831 - document.querySelector(
832 - "#document-title"
833 - )||
834 - document.querySelector(
835 - "h1"
836 - );
748 + var widths=
749 + group.entries
750 + .map(function(e){return e.rect.width;})
751 + .filter(function(w){return w>0;});
837 837  
838 - if(!title)return;
753 + if(widths.length<2)return false;
839 839  
840 - var badge=
841 - document.createElement(
842 - "span"
843 - );
755 + var minW=
756 + Math.min.apply(Math,widths);
844 844  
845 - badge.className=
846 - "sn-coming-soon-badge";
758 + var maxW=
759 + Math.max.apply(Math,widths);
847 847  
848 - badge.textContent=
849 - PLACEHOLDER_LABEL;
850 -
851 - badge.setAttribute(
852 - "aria-label",
853 - PLACEHOLDER_LABEL
761 + return (
762 + maxW/
763 + Math.max(1,minW)<=
764 + 1.9
854 854   );
766 + }
855 855  
856 - title.appendChild(
857 - 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"
858 858   );
859 859   }
860 860  
861 - /* =======================================================
862 - DETAIL PAGE OWN-ACCENT PROPAGATION
863 - ======================================================= */
788 + function findKnownBar(card){
789 + var cardRect=
790 + card.getBoundingClientRect();
864 864  
865 - function parseRGB(value){
866 - var match=String(value||"").match(
867 - /rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i
868 - );
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;
869 869  
870 - if(!match)return null;
802 + var r=el.getBoundingClientRect();
871 871  
872 - return [
873 - Number(match[1]),
874 - Number(match[2]),
875 - Number(match[3])
876 - ];
877 - }
804 + var rel=
805 + r.top-
806 + cardRect.top;
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 - );
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;
885 885   }
886 886  
887 - function paletteMatch(cssColor){
888 - var rgb=parseRGB(cssColor);
824 + function alignKnownBars(cards){
825 + var rows=
826 + cards.map(function(card){
827 + var bar=
828 + findKnownBar(card);
889 889  
890 - if(!rgb)return null;
830 + if(!bar)return null;
891 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 - ];
832 + var cr=
833 + card.getBoundingClientRect();
898 898  
899 - var best=null;
900 - var bestDistance=Infinity;
835 + var br=
836 + bar.getBoundingClientRect();
901 901  
902 - palette.forEach(function(item){
903 - var d=distance(rgb,item.rgb);
838 + return {
839 + bar:bar,
840 + relativeTop:
841 + br.top-
842 + cr.top
843 + };
844 + });
904 904  
905 - if(d<bestDistance){
906 - best=item;
907 - bestDistance=d;
908 - }
909 - });
846 + if(
847 + rows.some(function(row){
848 + return !row;
849 + })
850 + ){
851 + return false;
852 + }
910 910  
911 - return bestDistance<=30
912 - ?best
913 - :null;
914 - }
854 + var target=
855 + Math.max.apply(
856 + Math,
857 + rows.map(function(row){
858 + return row.relativeTop;
859 + })
860 + );
915 915  
916 - function propagateDetailAccents(){
917 - if(PAGE_KIND!=="detail")return;
862 + rows.forEach(function(row){
863 + var delta=
864 + target-
865 + row.relativeTop;
918 918  
919 - Array.from(
920 - root.querySelectorAll(
921 - ".arsn-call,.dmp-call,.ido-call,.pp-call,"+
922 - ".arsn-source,.dmp-source,.ido-source,.pp-source"
923 - )
924 - ).forEach(function(el){
925 - if(!visible(el))return;
867 + if(delta<=1)return;
926 926  
927 - var style=getComputedStyle(el);
869 + saveOriginal(
870 + row.bar,
871 + originalMarginTop,
872 + "margin-top"
873 + );
928 928  
929 - if(
930 - num(style.borderTopWidth)>=2
931 - ){
932 - var match=
933 - paletteMatch(
934 - style.borderTopColor
935 - );
875 + var current=
876 + num(
877 + getComputedStyle(
878 + row.bar
879 + ).marginTop
880 + );
936 936  
937 - if(match){
938 - el.style.setProperty(
939 - "border-left",
940 - "4px solid "+match.hex,
941 - "important"
942 - );
943 - }
944 - }
945 - });
882 + row.bar.style.setProperty(
883 + "margin-top",
884 + (
885 + current+
886 + delta
887 + )+"px"
888 + );
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;
955 -
956 - el.style.setProperty(
957 - "border-left",
958 - "4px solid #e94b13",
959 - "important"
890 + row.bar.setAttribute(
891 + "data-sn-first-section-aligned",
892 + "7"
960 960   );
961 - });
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;
970 -
971 - el.style.setProperty(
972 - "border-left",
973 - "4px solid #21b6d7",
974 - "important"
895 + sectionManaged.add(
896 + row.bar
975 975   );
976 976   });
899 +
900 + return true;
977 977   }
978 978  
979 - /* =======================================================
980 - OVERVIEW SEMANTIC THEME PALETTE
981 - ======================================================= */
903 + /* ---------- Generic first content after heading ---------- */
982 982  
983 - function smallestThemeHeaders(){
984 - return Array.from(
985 - root.querySelectorAll(
986 - "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 + )
987 987   )
988 - ).filter(function(el){
989 - if(!visible(el))return false;
990 - if(!themeFor(el.textContent))return false;
915 + .filter(function(el){
916 + if(!visible(el,20,8))return false;
991 991  
992 - return !Array.from(
993 - el.children||[]
994 - ).some(function(child){
995 - return !!themeFor(
996 - 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 + )
997 997   );
932 + })
933 + .sort(function(a,b){
934 + return (
935 + a.getBoundingClientRect().top-
936 + b.getBoundingClientRect().top
937 + );
998 998   });
999 - });
939 +
940 + return rows[0]||null;
1000 1000   }
1001 1001  
1002 - function findOverviewCard(header){
1003 - var node=header.parentElement;
1004 - var candidates=[];
943 + function firstContent(card,h){
944 + if(!h)return null;
1005 1005  
1006 - while(node&&node!==root){
1007 - var rect=node.getBoundingClientRect();
1008 - var style=getComputedStyle(node);
946 + var cr=
947 + card.getBoundingClientRect();
1009 1009  
1010 - var border=
1011 - num(style.borderTopWidth)+
1012 - num(style.borderRightWidth)+
1013 - num(style.borderBottomWidth)+
1014 - num(style.borderLeftWidth);
949 + var hr=
950 + h.getBoundingClientRect();
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 - }
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 + }
1024 1024  
1025 - node=node.parentElement;
1026 - }
967 + if(!visible(el,30,8))return false;
1027 1027  
1028 - if(!candidates.length)return null;
969 + var text=
970 + String(el.textContent||"")
971 + .replace(/\s+/g," ")
972 + .trim();
1029 1029  
1030 - candidates.sort(function(a,b){
1031 - return (
1032 - b.getBoundingClientRect().height-
1033 - a.getBoundingClientRect().height
1034 - );
1035 - });
974 + if(text.length<3)return false;
1036 1036  
1037 - return candidates[0];
1038 - }
976 + var r=el.getBoundingClientRect();
1039 1039  
1040 - function rowCandidates(link,card){
1041 - var result=[];
1042 - var cardRect=
1043 - card.getBoundingClientRect();
978 + if(
979 + r.top<
980 + hr.bottom-1
981 + ){
982 + return false;
983 + }
1044 1044  
1045 - 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 + }
1046 1046  
1047 - while(node&&node!==card){
1048 - if(visible(node)){
1049 - var rect=
1050 - node.getBoundingClientRect();
1051 -
1052 1052   if(
1053 - rect.height<=105&&
1054 - rect.width>=
1055 - cardRect.width*.50&&
1056 - rect.width<=
1057 - cardRect.width*1.03
996 + r.height>
997 + cr.height*.58
1058 1058   ){
1059 - result.push(node);
999 + return false;
1060 1060   }
1061 - }
1062 1062  
1063 - node=node.parentElement;
1064 - }
1002 + return true;
1003 + })
1004 + .sort(function(a,b){
1005 + var ar=
1006 + a.getBoundingClientRect();
1065 1065  
1066 - return result;
1067 - }
1008 + var br=
1009 + b.getBoundingClientRect();
1068 1068  
1069 - function chooseOuterRow(
1070 - candidates,
1071 - link
1072 - ){
1073 - if(!candidates.length){
1074 - return link;
1075 - }
1076 -
1077 - var bordered=
1078 - candidates.filter(function(el){
1079 1079   return (
1080 - num(
1081 - getComputedStyle(el)
1082 - .borderLeftWidth
1083 - )>=1
1012 + ar.top-br.top||
1013 + ar.height-br.height
1084 1084   );
1085 1085   });
1086 1086  
1087 - var pool=
1088 - bordered.length
1089 - ?bordered
1090 - :candidates;
1017 + return rows[0]||null;
1018 + }
1091 1091  
1092 - pool.sort(function(a,b){
1093 - var ar=
1094 - a.getBoundingClientRect();
1020 + function alignGeneric(cards){
1021 + var rows=
1022 + cards.map(function(card){
1023 + var h=
1024 + heading(card);
1095 1095  
1096 - var br=
1097 - b.getBoundingClientRect();
1026 + var c=
1027 + firstContent(
1028 + card,
1029 + h
1030 + );
1098 1098  
1099 - return (
1100 - ar.left-br.left||
1101 - br.width-ar.width
1102 - );
1103 - });
1032 + if(!h||!c)return null;
1104 1104  
1105 - return pool[0]||link;
1106 - }
1034 + var cr=
1035 + card.getBoundingClientRect();
1107 1107  
1108 - function applyOverviewPalette(){
1109 - if(PAGE_KIND!=="overview"){
1110 - 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;
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 - };
1055 + var target=
1056 + Math.max.apply(
1057 + Math,
1058 + rows.map(function(row){
1059 + return row.relativeTop;
1127 1127   })
1128 - .filter(function(row){
1129 - return !!row.card;
1130 - });
1061 + );
1131 1131  
1132 - var unique=[];
1133 - var seenHeaders=new Set();
1063 + rows.forEach(function(row){
1064 + var delta=
1065 + target-
1066 + 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 - );
1068 + 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"
1070 + saveOriginal(
1071 + row.content,
1072 + originalMarginTop,
1073 + "margin-top"
1166 1166   );
1167 1167  
1168 - row.el.style.setProperty(
1169 - "color",
1170 - row.theme.text,
1171 - "important"
1172 - );
1076 + var current=
1077 + num(
1078 + getComputedStyle(
1079 + row.content
1080 + ).marginTop
1081 + );
1173 1173  
1174 - row.el.style.setProperty(
1175 - "text-align",
1176 - "left",
1177 - "important"
1083 + row.content.style.setProperty(
1084 + "margin-top",
1085 + (
1086 + current+
1087 + delta
1088 + )+"px"
1178 1178   );
1179 1179  
1180 - row.el.style.setProperty(
1181 - "word-spacing",
1182 - "normal",
1183 - "important"
1091 + row.content.setAttribute(
1092 + "data-sn-first-content-aligned",
1093 + "7"
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 - });
1096 + contentManaged.add(
1097 + row.content
1098 + );
1265 1265   });
1266 1266  
1267 - return unique;
1101 + return true;
1268 1268   }
1269 1269  
1270 - /* =======================================================
1271 - OVERVIEW CARD HEIGHT + FIRST THEMATIC ROW
1272 - ======================================================= */
1104 + function applyRow(group){
1105 + if(!validRow(group))return false;
1273 1273  
1274 - function alignOverviewCards(headers){
1275 - if(
1276 - PAGE_KIND!=="overview"||
1277 - window.innerWidth<=MOBILE_MAX
1278 - ){
1279 - return;
1280 - }
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);
1110 + group.entries.forEach(function(entry){
1111 + if(!seen.has(entry.target)){
1112 + seen.add(entry.target);
1113 + cards.push(entry.target);
1289 1289   }
1290 1290   });
1291 1291  
1292 - if(cards.length<2){
1293 - return;
1117 + if(cards.length<2)return false;
1118 +
1119 + if(
1120 + !alignKnownBars(cards)
1121 + ){
1122 + alignGeneric(cards);
1294 1294   }
1295 1295  
1296 - // Group cards by actual top position.
1297 - var groups=[];
1125 + var maxHeight=0;
1298 1298  
1299 1299   cards.forEach(function(card){
1300 - var top=
1301 - card.getBoundingClientRect().top;
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);
1128 + maxHeight=
1129 + Math.max(
1130 + maxHeight,
1131 + card.getBoundingClientRect().height
1132 + );
1325 1325   });
1326 1326  
1327 - groups.forEach(function(group){
1328 - if(group.cards.length<2){
1329 - return;
1330 - }
1135 + maxHeight=
1136 + Math.ceil(
1137 + maxHeight
1138 + );
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 - });
1140 + if(maxHeight<MIN_H)return false;
1349 1349  
1350 - return candidates.length
1351 - ?candidates[0]
1352 - :null;
1353 - });
1142 + cards.forEach(function(card){
1143 + saveOriginal(
1144 + card,
1145 + originalMinHeight,
1146 + "min-height"
1147 + );
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 - );
1149 + card.style.setProperty(
1150 + "min-height",
1151 + maxHeight+"px"
1152 + );
1374 1374  
1375 - firstHeaders.forEach(function(row){
1376 - var relativeTop=
1377 - row.el
1378 - .getBoundingClientRect()
1379 - .top-
1380 - row.card
1381 - .getBoundingClientRect()
1382 - .top;
1154 + card.setAttribute(
1155 + "data-sn-equal-height-managed",
1156 + "7"
1157 + );
1383 1383  
1384 - var delta=
1385 - targetTop-relativeTop;
1159 + heightManaged.add(card);
1160 + });
1386 1386  
1387 - if(delta>1){
1388 - saveStyle(
1389 - row.el,
1390 - originalMargin,
1391 - "margin-top"
1392 - );
1162 + return true;
1163 + }
1393 1393  
1394 - var current=
1395 - num(
1396 - getComputedStyle(
1397 - row.el
1398 - ).marginTop
1399 - );
1165 + function calculate(force){
1166 + if(applying)return;
1400 1400  
1401 - row.el.style.setProperty(
1402 - "margin-top",
1403 - (
1404 - current+delta
1405 - )+"px"
1406 - );
1168 + var width=
1169 + Math.round(
1170 + window.innerWidth
1171 + );
1407 1407  
1408 - row.el.setAttribute(
1409 - "data-sn-master-first-row",
1410 - "1"
1411 - );
1173 + var meaningful=
1174 + lastWidth<0||
1175 + Math.abs(
1176 + width-
1177 + lastWidth
1178 + )>=
1179 + MIN_WIDTH_CHANGE;
1412 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 - });
1456 - });
1457 - }
1458 -
1459 - /* =======================================================
1460 - DETAIL GRID EQUAL HEIGHT, DESKTOP ONLY
1461 - ======================================================= */
1462 -
1463 - function equaliseDetailGrids(){
1464 1464   if(
1465 - PAGE_KIND!=="detail"||
1466 - window.innerWidth<=MOBILE_MAX
1182 + hasApplied&&
1183 + !force&&
1184 + !meaningful
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 - ];
1189 + applying=true;
1479 1479  
1480 - selectors.forEach(function(selector){
1481 - Array.from(
1482 - root.querySelectorAll(selector)
1483 - ).forEach(function(grid){
1484 - var children=
1485 - Array.from(
1486 - grid.children||[]
1487 - ).filter(visible);
1191 + try{
1192 + harmoniseCustomCallouts();
1488 1488  
1489 - if(children.length<2){
1490 - return;
1194 + if(width<=MOBILE_MAX){
1195 + if(hasApplied){
1196 + resetRuntime();
1491 1491   }
1492 1492  
1493 - var groups=[];
1199 + hasApplied=false;
1200 + lastWidth=width;
1201 + return;
1202 + }
1494 1494  
1495 - children.forEach(function(child){
1496 - var top=
1497 - child
1498 - .getBoundingClientRect()
1499 - .top;
1204 + if(hasApplied){
1205 + resetRuntime();
1206 + }
1500 1500  
1501 - 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 + });
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 - }
1226 + var touched=
1227 + new Set();
1513 1513  
1514 - if(!group){
1515 - group={
1516 - top:top,
1517 - items:[]
1518 - };
1519 - groups.push(group);
1520 - }
1229 + parents.forEach(function(parent){
1230 + var entries=[];
1521 1521  
1522 - group.items.push(child);
1523 - });
1524 -
1525 - groups.forEach(function(group){
1526 - 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 + ){
1527 1527   return;
1528 1528   }
1529 1529  
1530 - var maxHeight=0;
1245 + var target=
1246 + pickTarget(child);
1531 1531  
1532 - group.items.forEach(function(item){
1533 - maxHeight=
1534 - Math.max(
1535 - maxHeight,
1536 - item
1537 - .getBoundingClientRect()
1538 - .height
1539 - );
1248 + if(!target)return;
1249 +
1250 + entries.push({
1251 + target:target,
1252 + rect:
1253 + target.getBoundingClientRect()
1540 1540   });
1255 + });
1541 1541  
1542 - maxHeight=
1543 - Math.ceil(maxHeight);
1257 + groupRows(
1258 + entries
1259 + ).forEach(function(group){
1260 + if(!validRow(group))return;
1544 1544  
1545 - group.items.forEach(function(item){
1546 - saveStyle(
1547 - item,
1548 - originalHeight,
1549 - "min-height"
1550 - );
1262 + var targets=
1263 + group.entries.map(function(entry){
1264 + return entry.target;
1265 + });
1551 1551  
1552 - item.style.setProperty(
1553 - "min-height",
1554 - maxHeight+"px"
1555 - );
1267 + if(
1268 + !targets.some(function(el){
1269 + return !touched.has(el);
1270 + })
1271 + ){
1272 + return;
1273 + }
1556 1556  
1557 - item.setAttribute(
1558 - "data-sn-master-equal-height",
1559 - "1"
1560 - );
1561 -
1562 - managedHeight.add(item);
1563 - });
1275 + if(applyRow(group)){
1276 + targets.forEach(function(el){
1277 + touched.add(el);
1278 + });
1279 + }
1564 1564   });
1565 1565   });
1566 - });
1567 - }
1568 1568  
1569 - /* =======================================================
1570 - RUN / RESPONSIVE SCHEDULING
1571 - ======================================================= */
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 - }
1283 + lastWidth=width;
1284 + hasApplied=true;
1599 1599   }finally{
1600 - running=false;
1286 + applying=false;
1601 1601   }
1602 1602   }
1603 1603  
1604 - function onResize(){
1290 + function resize(){
1605 1605   if(resizeTimer){
1606 1606   clearTimeout(
1607 1607   resizeTimer
... ... @@ -1612,40 +1612,19 @@
1612 1612   setTimeout(
1613 1613   function(){
1614 1614   resizeTimer=0;
1615 - run();
1301 + calculate(false);
1616 1616   },
1617 1617   RESIZE_DEBOUNCE
1618 1618   );
1619 1619   }
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 - });
1632 - }
1633 -
1634 - if(
1635 - document.fonts&&
1636 - document.fonts.ready
1637 - ){
1638 - try{
1639 - await document.fonts.ready;
1640 - }catch(error){}
1641 - }
1642 -
1307 + function waitImages(){
1643 1643   var images=
1644 1644   Array.from(
1645 1645   root.querySelectorAll("img")
1646 1646   );
1647 1647  
1648 - await Promise.all(
1313 + return Promise.all(
1649 1649   images.map(function(img){
1650 1650   if(img.complete){
1651 1651   return Promise.resolve();
... ... @@ -1670,20 +1670,46 @@
1670 1670   });
1671 1671   })
1672 1672   );
1338 + }
1673 1673  
1674 - 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);
1675 1675   }
1676 1676  
1677 - window.addEventListener(
1369 + addEventListener(
1678 1678   "resize",
1679 - onResize,
1371 + resize,
1680 1680   {passive:true}
1681 1681   );
1682 1682  
1683 - waitForReady();
1375 + initial();
1684 1684  })();
1685 1685  </script>
1686 1686  
1687 -<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_END -->
1688 -{{/html}}
1689 -
1379 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_END -->
1380 +{{/html}}\n