3rdUnknown / Spectre 5000

// ==UserScript==
// @name         Spectre 5000
// @namespace    https://spectre.5000
// @version      17.050
// @description  The feeling of not wanting to lose, everyone has it. If you find it unfair, you'll have to work harder yourself.
// @author       3rdUnknown
// @copyright    2025
// @license      MIT
// @homepageURL  https://openuserjs.org/scripts/3rdUnknown/Spectre_5000
// @supportURL   https://openuserjs.org/scripts/3rdUnknown/Spectre_5000
// @match        *://62.210.170.212:3000/projects*
// @match        *://spectre.autotests-xbees.wildix.com/projects*
// @require      https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.1.0/jszip-utils.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.0/FileSaver.min.js
// @require      https://unpkg.com/image-compare-viewer/dist/image-compare-viewer.min.js
// @resource     IMPORTED_CSS https://unpkg.com/image-compare-viewer/dist/image-compare-viewer.min.css
// @grant        GM_notification
// @grant        GM_xmlhttpRequest
// @grant        GM_openInTab
// @grant        GM_getResourceText
// @grant        GM_addStyle
// @run-at       document-idle
// @updateURL    https://openuserjs.org/meta/3rdUnknown/Spectre_5000.meta.js
// @downloadURL  https://openuserjs.org/install/3rdUnknown/Spectre_5000.user.js
// ==/UserScript==

(function() {
    'use strict';

    const my_css = GM_getResourceText('IMPORTED_CSS');
    GM_addStyle(my_css);
    GM_addStyle(`
/* ==== Modal Styling ==== */
.modal {
    display: none;
    position: fixed;
    z-index: 1;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: auto;
    background-color: rgba(0, 0, 0, 0.4);
}

.modal-content {
    background-color: #fefefe;
    margin: 3% auto;
    padding: 20px;
    border: 1px solid #888;
    width: 85%;
    height: 85%;
    text-align: center;
}

.imgModal1 img {
    height: 95%;
}

.imgModal2 img {
    max-width: 95%;
}

#image-compare {
    width: 100%;
    height: 95%;
}

/* Compare lightbox: no page/inner scroll (website keeps scroll for tall pages) */
body:has(.modal--compare.modal-show:not(.modal--website)) {
    overflow: hidden !important;
}

.modal--compare:not(.modal--website) {
    overflow: hidden !important;
}

.modal--compare:not(.modal--website) .modal-content {
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    height: 94vh;
    max-height: 94vh;
    margin: 3vh auto;
    overflow: hidden;
    position: relative;
}

.modal--compare:not(.modal--website) .compare-viewport {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    align-items: stretch;
}

.modal--compare:not(.modal--website) .compare-indicator-gutter {
    flex: 0 0 14px;
    width: 14px;
    position: relative;
    box-sizing: border-box;
}

.modal--compare:not(.modal--website) .close {
    float: none;
    position: absolute;
    top: 8px;
    right: 12px;
    z-index: 10;
}

.modal--compare:not(.modal--website) #image-compare {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    height: auto;
    overflow: hidden;
}

.modal--compare:not(.modal--website) #image-compare .icv {
    height: 100%;
    max-height: 100%;
}

/* ==== Modal Close Button ==== */
.close {
    color: #aaa;
    float: right;
    font-size: 28px;
    font-weight: bold;
    cursor: pointer;
}

.close:hover,
.close:focus {
    color: black;
    text-decoration: none;
}

/* ==== Image Compare Wrapper ==== */
.icv__wrapper,
div.icv__fluidwrapper {
    background-size: contain;
    background-repeat: no-repeat;
}

/* Image Compare Labels Styling */
.icv__label {
  font-size: 0.9rem !important;
  font-weight: 600 !important;
  padding: 4px 8px !important;
  border-radius: 4px !important;
  position: absolute !important;
  bottom: 10px !important;
  z-index: 1000 !important;
  text-shadow: 1px 1px 2px rgba(0,0,0,0.5) !important;
  box-shadow: 0 1px 3px rgba(0,0,0,0.2) !important;
}

/* Baseline label - зеленый, левый угол */
.icv__label-before,
.icv__label.icv__label-before {
  background-color: #28a745 !important;
  color: white !important;
  border: 1px solid #1e7e34 !important;
  left: 10px !important;
}

/* CSS переменные для динамической ширины линий */
:root {
  --before-line-width: 0px;
  --after-line-width: 0px;
}

.icv__label-before::before,
.icv__label.icv__label-before::before {
  content: '' !important;
  position: absolute !important;
  top: 50% !important;
  left: 100% !important;
  transform: translateY(-50%) !important;
  width: var(--before-line-width) !important;
  height: 2px !important;
  background-color: #28a745 !important;
  border-radius: 1px !important;
  z-index: 999 !important;
  transition: width 0.2s ease !important;
}

/* Comparison label - оранжевый, правый угол */
.icv__label-after,
.icv__label.icv__label-after {
  background-color: #ff8c00 !important;
  color: white !important;
  border: 1px solid #e07600 !important;
  right: 10px !important;
}

.icv__label-after::before,
.icv__label.icv__label-after::before {
  content: '' !important;
  position: absolute !important;
  top: 50% !important;
  right: 100% !important;
  transform: translateY(-50%) !important;
  width: var(--after-line-width) !important;
  height: 2px !important;
  background-color: #ff8c00 !important;
  border-radius: 1px !important;
  z-index: 999 !important;
  transition: width 0.2s ease !important;
}

/* ==== Metadata Styling ==== */
.date-time {
    color: black;
    font-size: 1.5rem;
}

.version {
    font-size: 0.8em;
    color: #909090;
    margin: -5px 0 -10px;
}



/* ==== ZIP Download Block ==== */
#download-block {
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* ==== Lightbox Border ==== */
.lightbox {
    border: 2px dashed red;
}

/* ==== Tabs: Product ==== */
#product-tabs {
  margin: 20px 0 5px 0;
  padding-left: 0;
  padding-bottom: 10px;
  border-bottom: 2px solid #666;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
}

.product-tab {
  padding: 12px 20px !important;
  margin-right: 8px !important;
  margin-bottom: 0 !important;
  border: 1px solid #ddd;
  border-bottom: none;
  background-color: #f8f8f8;
  border-radius: 5px 5px 0 0;
  font-size: 16px !important;
  font-weight: bold;
  min-width: 120px;
  text-align: center;
  cursor: pointer;
  transition: all 0.2s ease;
}

.product-tab:hover {
  background-color: #e9e9e9 !important;
}

.product-tab.x-bees-tab {
  color: #ff8c00 !important;
}

.product-tab.x-hoppers-tab {
  color: #006400 !important;
}

.product-tab.collaboration-tab {
  color: #00008b !important;
}

.product-tab.all-tab {
  color: #333 !important;
}

.product-tab.website-tab {
  color: #8b008b !important;
}

.active-tab {
  background-color: #f0f0f0 !important;
  border-bottom: 3px solid currentColor !important;
  font-weight: bold !important;
}

.hidden-project {
  display: none;
}

/* ==== Tabs: Environments ==== */
#environment-tabs {
  margin: 0;
  padding-left: 0;
  border-bottom: none;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
}

.environment-tab {
  padding: 8px 15px;
  margin-right: 6px;
  margin-bottom: 0;
  border: 1px solid #ddd;
  border-bottom: none;
  background-color: #f8f8f8;
  border-radius: 5px 5px 0 0;
  font-size: 14px;
  color: #333;
  cursor: pointer;
  transition: all 0.2s ease;
}

.environment-tab:hover {
  background-color: #e9e9e9 !important;
}

.environment-tab.active-env-tab {
  background-color: #f0f0f0 !important;
  border-bottom: 3px solid currentColor !important;
  font-weight: bold !important;
  color: black !important;
}

.environment-tab.stage-tab {
  color: #9c27b0 !important;
}

.environment-tab.stage-plus-tab {
  color: #6a5acd !important;
}

.environment-tab.stable-tab {
  color: #ff9800 !important;
}

/* ==== Category Filter ==== */
#category-filters {
    margin: 10px 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    padding-left: 15px;
}

.category-label {
    font-weight: bold;
    margin-right: 10px;
    font-size: 14px;
}

.category-button {
    padding: 6px 12px !important;
    margin: 0 8px 5px 0 !important;
    border: 1px solid #ddd;
    background-color: #f1f1f1;
    border-radius: 4px;
    font-size: 13px !important;
    color: #333 !important;
    cursor: pointer;
    transition: all 0.2s ease;
}

.category-button:hover {
    background-color: #e0e0e0;
}

.category-button.active-category {
    background-color: #4caf50;
    color: white !important;
    font-weight: bold;
    box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}

.report-button {
    margin-left: 48px !important;
    border-left: 4px solid rgb(250, 35, 100);
    color:rgb(200, 35, 100) !important;
}

.report-button:hover {
    background-color: #f3e5f5 !important;
}

.report-button:active,
.report-button:focus {
    background-color: #e1bee7 !important;
    color: #6a1b9a !important;
    outline: none !important;
    box-shadow: none !important;
}

.category-kite {
    border-left: 4px solid #2196F3;
}
.category-web {
    border-left: 4px solid #FF5722;
}
.category-android {
    border-left: 4px solid #4CAF50;
}
.category-ios {
    border-left: 4px solid #9C27B0;
}
.category-mobile-kite {
    border-left: 4px solid #FFC107;
}

/* ==== Project Rows ==== */
.old-project-row {
    background-color: #ffe5b4 !important;
    font-weight: bold;
}

.very-old-project-row {
    background-color: #f7e6e6 !important;
    font-weight: bold;
    border-left: 4px solid red;
}

/* ==== Test Labels and Stats ==== */
.label--fail,
.label--pass,
.label--warning,
a.total-tests {
    font-size: 1.65rem !important;
    font-weight: bold !important;
    text-align: center !important;
    vertical-align: middle !important;
    border-radius: 6px !important;
    margin: 2px !important;
    display: inline-block !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    height: 40px !important;
    line-height: 40px !important;
    padding: 0 8px !important;
    border: 1px solid transparent !important;
    box-sizing: border-box !important;
}

td.text-center {
    text-align: right !important;
    padding-left: 15px !important;
}

.label--fail,
.label--pass {
    width: 95px !important;
}

.label--warning {
    width: 70px !important;
}

a.total-tests {
    width: 105px !important;
    height: 40px !important;
    line-height: 40px !important;
}

/* ==== Custom Blue Fail Button ==== */
.fail-button-blue {
    width: 140px !important;
    height: 37px !important;
    line-height: 40px !important;
    background-color: #17a2b8 !important;
    color: white !important;
    border-color: #17a2b8 !important;
    font-size: 1.65rem !important;
    font-weight: bold !important;
    text-align: center !important;
    vertical-align: middle !important;
    border-radius: 6px !important;
    margin: 2px !important;
    display: inline-block !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    border: 1px solid #17a2b8 !important;
    box-sizing: border-box !important;
}

.fail-button-blue:hover {
    background-color: #138496 !important;
    border-color: #117a8b !important;
}

/* ==== Row Dividers in Project Table ==== */
tr.project {
    border-bottom: 2px solid black !important;
}

tr.project td,
tr.project th {
    padding-top: 8px !important;
    padding-bottom: 8px !important;
}

/* ==== Count and Percentage Styling ==== */
#test_count > span > span,
.count-number,
.count-sup {
    font-size: 1.4rem !important;
}

.count-number {
    vertical-align: middle;
    font-size: 1.65rem;
}

.count-sup {
    vertical-align: super;
}

.icon-span {
    font-size: 2.2rem;
    margin-left: 5px;
}

.percent-mark {
    display: inline-block;
    background-color: #FF8C00;
    color: white;
    padding: 0.1rem 0.3rem;
    border-radius: 0.25rem;
    font-size: 0.8rem;
    min-width: 45px;
    text-align: center;
}

/* ==== Difference Count ==== */
.low-difference-count {
    font-size: 0.8em;
    color: #909090;
    font-weight: bold;
    margin-top: -20px;
}

/* ==== Adjust Suite Column Width ==== */
table#projects th:first-child,
table#projects td:first-child,
#suite th:first-child,
#suite td:first-child {
    max-width: 150px !important;
    width: 150px !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
}

table#projects th:first-child a,
#suite th:first-child a {
    display: block !important;
    max-width: 100% !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
}

table#projects th:first-child *,
table#projects td:first-child *,
#suite th:first-child *,
#suite td:first-child * {
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
}

.download-button {
    width: 250px;
    height: 60px;
    background-color: #28a745;
    color: white;
    font-size: 1.75rem;
    font-weight: 600;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin: 4px;
    transition: background-color 0.2s ease-in-out;
}

.download-button:hover {
    background-color: #218838;
}

td#test_count {
    padding-left: 8px !important;
    padding-right: 8px !important;
}

#combined-filters {
    padding-left: 0;
    margin-bottom: 10px;
    border-bottom: 1px solid #ddd;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 20px;
}

#environment-tabs {
    margin: 0;
    padding-left: 0;
    border-bottom: none !important;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
}

#category-filters {
    margin: 0 !important;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
}

.category-label {
    margin-left: 0;
    margin-right: 10px;
}

/* ==== Table Header Color Override ==== */
table#projects thead th,
table#projects tr:first-child th,
.table-header,
thead th {
    background-color: #008080 !important;
    color: white !important;
}

/* ==== Set as Baseline Button Styling ==== */
.baseline-button-success,
button.baseline-button-success,
.btn.baseline-button-success,
a.baseline-button-success {
    background-color: #28a745 !important;
    color: white !important;
    border-color: #28a745 !important;
    border: 2px solid #28a745 !important;
}

.baseline-button-success:hover,
button.baseline-button-success:hover,
.btn.baseline-button-success:hover,
a.baseline-button-success:hover {
    background-color: #218838 !important;
    border-color: #1e7e34 !important;
}

.baseline-notification {
    position: fixed;
    top: 20px;
    right: 20px;
    background-color: #28a745;
    color: white;
    padding: 15px 20px;
    border-radius: 5px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.2);
    z-index: 10000;
    font-size: 14px;
    font-weight: bold;
    opacity: 0;
    transform: translateX(100%);
    transition: all 0.3s ease;
}

.baseline-notification.show {
    opacity: 1;
    transform: translateX(0);
}

/* ==== Difference Score Styling ==== */
.diff-score-low {
    color: #ff8c00 !important;
    font-size: 1.8rem !important;
    font-weight: bold !important;
}

.diff-score-high {
    color: #dc3545 !important;
    font-size: 2.0rem !important;
    font-weight: bold !important;
}

.diff-icon {
    width: 32px;
    height: 32px;
    vertical-align: middle;
    margin-right: 5px;
}

/* ==== Environment and Product Colors ==== */
.env-stage {
    color: #9932cc !important; /* darkviolet */
}

.env-stable {
    color: #ff8c00 !important; /* darkorange */
}

.product-x-bees {
    color: #ff8c00 !important; /* darkorange */
}

.product-x-hoppers {
    color: #006400 !important; /* darkgreen */
}

.product-collaboration {
    color: #00008b !important; /* darkblue */
}

/* ==== Test Count Colors ==== */
.count-warning {
    color: #ff8c00 !important;
    font-weight: bold !important;
}

.count-excess {
    color: #ff8c00 !important;
    font-weight: bold !important;
}

/* ==== Date and Project Age Styling ==== */
.date-old {
    color: red !important;
    font-weight: bold !important;
}

.project-old {
    background-color: #FDF5E6 !important;
}

.project-very-old {
    background-color: #D3D3D3 !important;
}

/* ==== New Baseline Styling ==== */
.new-baseline-link {
    color: red !important;
}

/* ==== Modal Display States ==== */
.modal-show {
    display: block !important;
}

.modal-hide {
    display: none !important;
}

/* ==== Utility Classes ==== */
.flex-container {
    display: flex !important;
    flex-wrap: wrap !important;
    align-items: center !important;
    margin-top: 10px !important;
    margin-bottom: 10px !important;
}

.hidden-element {
    display: none !important;
}

.column-name-width {
    max-width: 250px !important;
    width: 250px !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
}

.column-suite-width {
    max-width: 350px !important;
    width: 350px !important;
    white-space: normal !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
}

.column-last-run-width {
    width: 600px !important;
    min-width: 550px !important;
}

/* ==== Split Cell Styling ==== */
.split-cell-container {
    display: flex !important;
    width: 100% !important;
    min-height: 50px !important;
}

.split-cell-container > div:first-child {
    flex: 0 0 200px !important;
    border-right: 1px solid #ddd !important;
    padding-right: 8px !important;
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
}

.split-cell-container > div:last-child {
    flex: 1 !important;
    padding-left: 8px !important;
    display: flex !important;
    flex-wrap: wrap !important;
    align-items: center !important;
    gap: 2px !important;
}

/* ==== Date Info Header Styling ==== */
.date-info-header {
    background-color: #008080 !important;
    color: white !important;
    padding: 8px !important;
    width: 600px !important;
    min-width: 550px !important;
}

.date-info-header > div {
    display: flex !important;
    width: 100% !important;
}

.label-minimal-padding {
    padding: 1px 1px !important;
}



/* ==== Compare Button Styling ==== */
.compare-button {
    background-color: #ffc107 !important;
    color: #212529 !important;
    border-color: #ffc107 !important;
    min-width: 140px !important;
    width: 140px !important;
    height: 37px !important;
    line-height: 37px !important;
    padding: 0 8px !important;
    margin: 2px !important;
    border-radius: 4px !important;
    font-size: 16px !important;
    font-weight: bold !important;
    text-align: center !important;
    cursor: pointer !important;
    transition: all 0.2s ease !important;
    display: inline-block !important;
    text-decoration: none !important;
    border: 1px solid #ffc107 !important;
    box-sizing: border-box !important;
}

.compare-button:hover {
    background-color: #e0a800 !important;
    border-color: #d39e00 !important;
    color: #212529 !important;
}



/* ==== Baseline Button Styling ==== */
button[value*="baseline"],
input[value*="baseline"],
.test__set-baseline {
    background-color: #6c757d !important;
    color: white !important;
    border-color: #6c757d !important;
    min-width: 140px !important;
    width: 140px !important;
    height: 37px !important;
    line-height: 37px !important;
    padding: 0 8px !important;
    margin: 2px !important;
    border-radius: 4px !important;
    font-size: 16px !important;
    font-weight: bold !important;
    text-align: center !important;
    cursor: pointer !important;
    transition: all 0.2s ease !important;
    display: inline-block !important;
    text-decoration: none !important;
    border: 1px solid #6c757d !important;
    box-sizing: border-box !important;
}

button[value*="baseline"]:hover,
input[value*="baseline"]:hover,
.test__set-baseline:hover {
    background-color: #5a6268 !important;
    border-color: #545b62 !important;
}

/* ==== Unified Button Classes for Test Results ==== */
.test-compare-button {
    background-color: #ffc107 !important;
    color: #212529 !important;
    border-color: #ffc107 !important;
    width: 120px !important;
    height: 37px !important;
    line-height: 37px !important;
    padding: 0 8px !important;
    margin: 2px !important;
    border-radius: 4px !important;
    font-size: 16px !important;
    font-weight: bold !important;
    text-align: center !important;
    cursor: pointer !important;
    transition: all 0.2s ease !important;
    display: inline-block !important;
    text-decoration: none !important;
    border: 1px solid #ffc107 !important;
    box-sizing: border-box !important;
}

.test-compare-button:hover {
    background-color: #e0a800 !important;
    border-color: #d39e00 !important;
}

.test-fail-button {
    background-color: #dc3545 !important;
    color: white !important;
    border-color: #dc3545 !important;
    width: 140px !important;
    height: 37px !important;
    line-height: 37px !important;
    padding: 0 8px !important;
    margin: 2px !important;
    border-radius: 4px !important;
    font-size: 16px !important;
    font-weight: bold !important;
    text-align: center !important;
    cursor: pointer !important;
    transition: all 0.2s ease !important;
    display: inline-block !important;
    text-decoration: none !important;
    border: 1px solid #dc3545 !important;
    box-sizing: border-box !important;
}

.test-fail-button:hover {
    background-color: #c82333 !important;
    border-color: #bd2130 !important;
}

.test-baseline-button {
    background-color: #6c757d !important;
    color: white !important;
    border-color: #6c757d !important;
    width: 140px !important;
    height: 37px !important;
    line-height: 37px !important;
    padding: 0 8px !important;
    margin: 2px !important;
    border-radius: 4px !important;
    font-size: 16px !important;
    font-weight: bold !important;
    text-align: center !important;
    cursor: pointer !important;
    transition: all 0.2s ease !important;
    display: inline-block !important;
    text-decoration: none !important;
    border: 1px solid #6c757d !important;
    box-sizing: border-box !important;
}

.test-baseline-button:hover {
    background-color: #5a6268 !important;
    border-color: #545b62 !important;
}

/* Low diff button styling */
.low-diff-button {
    background-color: #C8A2C8 !important;
    border: 1px solid #C8A2C8 !important;
    color: white !important;
    padding: 0 8px !important;
    border-radius: 6px !important;
    text-decoration: none !important;
    font-size: 1.65rem !important;
    font-weight: bold !important;
    display: inline-block !important;
    margin: 2px !important;
    transition: all 0.2s ease !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    width: 50px !important;
    height: 40px !important;
    line-height: 40px !important;
    text-align: center !important;
    vertical-align: middle !important;
    box-sizing: border-box !important;
}

.low-diff-button:hover {
    background-color: #C8A2C8 !important;
    border-color: #C8A2C8 !important;
    color: white !important;
    text-decoration: none !important;
}

/* ==== Dynamic Styles for JavaScript Created Elements ==== */
.dynamic-split-container {
    display: flex !important;
    width: 100% !important;
    min-height: 50px !important;
}

.dynamic-date-section {
    flex: 0 0 200px !important;
    border-right: 1px solid #ddd !important;
    padding-right: 8px !important;
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
}

.dynamic-buttons-section {
    flex: 1 !important;
    padding-left: 8px !important;
    display: flex !important;
    flex-wrap: wrap !important;
    align-items: center !important;
    gap: 2px !important;
}

.dynamic-last-run-cell {
    width: 600px !important;
    min-width: 550px !important;
    padding: 4px !important;
}

.dynamic-header-style {
    background-color: #008080 !important;
    color: white !important;
    padding: 8px !important;
    width: 600px !important;
    min-width: 550px !important;
}

.dynamic-header-content {
    display: flex !important;
    width: 100% !important;
}

.dynamic-header-date {
    flex: 0 0 200px !important;
    text-align: center !important;
    border-right: 1px solid #ddd !important;
    padding-right: 8px !important;
}

.dynamic-header-results {
    flex: 1 !important;
    text-align: center !important;
    padding-left: 8px !important;
}

.dynamic-notification {
    position: fixed !important;
    top: 20px !important;
    right: 20px !important;
    background-color: #28a745 !important;
    color: white !important;
    padding: 15px 20px !important;
    border-radius: 5px !important;
    box-shadow: 0 2px 10px rgba(0,0,0,0.2) !important;
    z-index: 10000 !important;
    font-size: 14px !important;
    font-weight: bold !important;
    opacity: 0 !important;
    transform: translateX(100%) !important;
    transition: all 0.3s ease !important;
}

.dynamic-notification.show {
    opacity: 1 !important;
    transform: translateX(0) !important;
}

.dynamic-baseline-button {
    background-color: #28a745 !important;
    border-color: #28a745 !important;
    color: white !important;
}

.flex-display {
    display: flex !important;
}

.border-bottom-black {
    border-bottom: 2px solid black !important;
}

.progress-bar {
    width: 0% !important;
}

/* ==== Mass baseline editing (runs page) ==== */
.filters.mass-editing-filters {
    display: flex !important;
    flex-wrap: wrap !important;
    align-items: center !important;
}

.filters.mass-editing-filters form {
    margin-right: auto !important; /* форма слева */
}

.mass-editing-controls {
    display: inline-flex !important;
    align-items: center !important;
    gap: 8px !important;
    margin-left: auto !important; /* кнопки справа */
}

/* hide helper: beats existing display:... !important */
.mass-editing-controls [hidden] {
    display: none !important;
}

/* кнопки в фильтрах: не переносить текст и не фиксировать узкую ширину */
.mass-editing-controls button.test-compare-button,
.mass-editing-controls button.test-fail-button,
.mass-editing-controls button.test-baseline-button {
    white-space: nowrap !important;
    width: auto !important;
    padding: 0 12px !important;
}

.mass-editing-controls button.test-compare-button {
    min-width: 140px !important;
}

.mass-editing-controls button.test-fail-button {
    min-width: 160px !important;
}

.mass-editing-controls button.test-baseline-button {
    min-width: 120px !important;
}

.lightbox-shortcuts-toggle {
    position: relative !important;
    display: inline-flex !important;
    align-items: center !important;
    gap: 4px !important;
    margin-right: 4px !important;
    padding: 4px 6px !important;
    border: 1px solid #cfd8dc !important;
    border-radius: 4px !important;
    background: #f5f7f8 !important;
    cursor: pointer !important;
    user-select: none !important;
    line-height: 1 !important;
}

.lightbox-shortcuts-toggle__icon {
    font-size: 32px !important;
    line-height: 1 !important;
    opacity: 0.85 !important;
}

.lightbox-shortcuts-toggle__input {
    margin: 0 !important;
    width: 14px !important;
    height: 14px !important;
    cursor: pointer !important;
}

.lightbox-shortcuts-toggle__tooltip {
    visibility: hidden !important;
    opacity: 0 !important;
    position: absolute !important;
    right: 0 !important;
    bottom: calc(100% + 8px) !important;
    width: 240px !important;
    padding: 8px 10px !important;
    border-radius: 6px !important;
    background: rgba(20, 28, 34, 0.96) !important;
    color: #fff !important;
    font-size: 12px !important;
    font-weight: 500 !important;
    line-height: 1.45 !important;
    text-align: left !important;
    white-space: normal !important;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25) !important;
    pointer-events: none !important;
    z-index: 10010 !important;
    transition: opacity 0.15s ease !important;
}

.lightbox-shortcuts-toggle:hover .lightbox-shortcuts-toggle__tooltip,
.lightbox-shortcuts-toggle:focus-within .lightbox-shortcuts-toggle__tooltip {
    visibility: visible !important;
    opacity: 1 !important;
}

.lightbox-shortcuts-toggle__tooltip strong {
    display: block !important;
    margin-bottom: 4px !important;
    font-size: 12px !important;
}

.mass-baseline-label {
    display: inline-flex !important;
    align-items: center !important;
    gap: 6px !important;
    margin-left: 10px !important;
    font-size: 13px !important;
    font-weight: 600 !important;
    cursor: pointer !important;
    user-select: none !important;
}

.mass-baseline-label input[type="checkbox"] {
    transform: scale(1.05);
}

.mass-editing-hud {
    position: fixed !important;
    left: 16px !important;
    bottom: 16px !important;
    padding: 8px 10px !important;
    border-radius: 6px !important;
    background: rgba(0, 0, 0, 0.78) !important;
    color: #fff !important;
    font-size: 14px !important;
    font-weight: 700 !important;
    z-index: 10005 !important;
    pointer-events: none !important;
}

.compare-nav-hud {
    position: fixed !important;
    left: 16px !important;
    top: 16px !important;
    padding: 8px 10px !important;
    border-radius: 6px !important;
    background: rgba(0, 0, 0, 0.78) !important;
    color: #fff !important;
    font-size: 14px !important;
    font-weight: 700 !important;
    z-index: 10005 !important;
    pointer-events: none !important;
    text-align: left !important;
    line-height: 1.35 !important;
    white-space: nowrap !important;
}

.compare-nav-hud[hidden] {
    display: none !important;
}

.auto-diff-indicator {
    position: fixed !important;
    right: 16px !important;
    top: 16px !important;
    padding: 4px 8px !important;
    border-radius: 4px !important;
    background: rgba(255, 34, 85, 0.92) !important;
    color: #fff !important;
    font-size: 11px !important;
    font-weight: 700 !important;
    letter-spacing: 0.04em !important;
    z-index: 10005 !important;
    pointer-events: none !important;
}

.auto-diff-indicator[hidden] {
    display: none !important;
}

.image-lightbox-hud {
    position: fixed !important;
    left: 16px !important;
    top: 16px !important;
    padding: 8px 10px !important;
    border-radius: 6px !important;
    background: rgba(0, 0, 0, 0.78) !important;
    color: #fff !important;
    font-size: 14px !important;
    font-weight: 700 !important;
    z-index: 10005 !important;
    pointer-events: none !important;
    text-align: left !important;
    line-height: 1.35 !important;
    white-space: nowrap !important;
}

.image-lightbox-hud[hidden] {
    display: none !important;
}

.modal--baseline-lightbox img.lightbox {
    max-width: 95%;
    max-height: 95%;
    height: 95%;
}

/* ==== WEBSITE: scrollable tall-image compare modal ==== */
.modal--website .modal-content {
    height: auto !important;
}

.modal--website .compare-viewport {
    display: flex;
    width: 100%;
    align-items: flex-start;
}

.modal--website .compare-indicator-gutter {
    flex: 0 0 14px;
    width: 14px;
    position: sticky;
    top: 0;
    height: 100vh;
    max-height: 100vh;
    box-sizing: border-box;
    z-index: 2;
}

.modal--website #image-compare {
    flex: 1 1 auto;
    min-width: 0;
    /* height set by JS after image loads (naturalWidth/Height ratio × container width) */
    min-height: 200px !important;
}

/* ==== Diff Highlight Circles (H key) ==== */
.diff-highlight-overlay circle {
    animation: diff-circle-appear 0.5s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes diff-circle-appear {
    0%   { r: 0; opacity: 0; stroke-width: 0; }
    55%  { opacity: 1; stroke-width: 3; }
    100% { opacity: 0.88; stroke-width: 2.5; }
}

/* ==== Diff Indicator Bar (vertical minimap, stays after H toggle) ==== */
.modal--compare #image-compare {
    position: relative;
}

.compare-indicator-gutter .diff-indicator-bar {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
}

.compare-indicator-gutter .diff-indicator-track {
    position: absolute;
    top: 1px;
    bottom: 1px;
    left: 4px;
    right: 4px;
    width: auto;
    background-color: #e8e8e8;
    border-radius: 3px;
    overflow: hidden;
}

.diff-indicator-inner {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
}

.diff-indicator-markers {
    position: absolute;
    inset: 0;
}

.diff-indicator-marker {
    position: absolute;
    left: 0;
    right: 0;
    background-color: #ff2255;
    min-height: 1px;
}
`);

    const totalTests = {
        //Updated 21.8.26
        '------XBS-----': 0,
        'monitoring chats list x-bees WEB': 7,
        'basic visual regression testing x-bees WEB': 549,
        'DMbasic visual regression testing x-bees WEB': 549,
        'pseudo localization basic visual regression testing x-bees WEB': 549,
        'basic visual regression testing x-bees iOS': 258,
        'DM basic visual regression testing x-bees iOS': 258,
        'basic visual regression testing simulator x-bees iOS': 243,
        'DM basic visual regression testing simulator x-bees iOS': 243,
        'big font size basic visual regression testing simulator x-bees iOS': 243,
        'pseudo localization basic visual regression testing simulator x-bees iOS': 243,
        'basic visual regression testing x-bees Android': 265,
        'DM basic visual regression testing x-bees Android': 265,
        'big font size basic visual regression testing x-bees Android': 265,
        'pseudo localization basic visual regression testing x-bees Android': 265,
        'storybook visual regression testing x-bees Android': 73,
        'Kite basic visual regression testing (chrome) x-bees KITE': 76,
        'Kite basic visual regression testing (firefox) x-bees KITE': 75,
        'Kite basic visual regression testing (safari) x-bees KITE': 75,
        'chrome Kite mobile basic visual regression testing x-bees mobile KITE': 44,
        'safari Kite mobile basic visual regression testing x-bees mobile KITE': 30,
        'locales test suite x-bees WEB': 110,
        'locales test suite x-bees Android': 77,
        'embedded visual regression testing x-bees EMBEDDED': 20,
        '------XHOPS------': 0,
        'monitoring chats list x-hoppers WEB': 6,
        'basic visual regression testing x-hoppers WEB': 526,
        'DMbasic visual regression testing x-hoppers WEB': 526,
        'calls test suite x-hoppers iOS': 20,
        'basic visual regression testing simulator x-hoppers iOS': 240,
        'basic visual regression testing x-hoppers Android': 272,
        'Kite basic visual regression testing (chrome) x-hoppers KITE': 75,
        'chrome Kite mobile basic visual regression testing x-hoppers mobile KITE': 44,
        'safari Kite mobile basic visual regression testing x-hoppers mobile KITE': 30,
        '------C7------': 0,
        'basic visual regression testing collaboration WEB': 415,
        'DMbasic visual regression testing collaboration WEB': 415,
        'calls test suite collaboration iOS': 20,
        'basic visual regression testing simulator collaboration iOS': 229,
        'basic visual regression testing collaboration Android': 259,
        'Kite basic visual regression testing (chrome) collaboration KITE': 63,
        'chrome Kite mobile basic visual regression testing collaboration mobile KITE': 40,
        'safari Kite mobile basic visual regression testing collaboration mobile KITE': 30,
        '------WEBSITE-----': 0,
        'widget: visual regression testing WEBSITE' : 24,
        'website: visual regression testing WEBSITE' : 66,
        'expand widget: visual regression testing WEBSITE': 11,
        'link-preview: visual regression testing WEBSITE': 15
    };

    const stagePlusProjects = [
        'DM basic',
        'DMbasic',
        'pseudo localization',
        'big font size',
        'Kite basic visual regression testing (firefox)',
        'Kite basic visual regression testing (safari)'
    ];

    // Global variables
    let text, score,
        lowDiffCount = 0;
    let lowDiffCountUniq = 0;
    let testLowDiffTitle = '';
    let testNamePrev = '';

    // Tab functionality
    function addProductTabs() {
        if (window.location.pathname === '/projects') {

            const tabContainer = document.createElement('div');
            tabContainer.id = 'product-tabs';

            const products = [
                { name: 'All', class: 'all-tab' },
                { name: 'x-bees', class: 'x-bees-tab' },
                { name: 'x-hoppers', class: 'x-hoppers-tab' },
                { name: 'collaboration', class: 'collaboration-tab' },
                { name: 'Website', class: 'website-tab' }
            ];

            products.forEach(product => {
                const tab = document.createElement('button');
                tab.innerText = product.name;
                tab.dataset.product = product.name.toLowerCase();
                tab.classList.add('product-tab', product.class);

                if (product.name === 'All') {
                    tab.classList.add('active-tab');
                }

                tab.addEventListener('click', function() {
                    const envTabs = document.getElementById('environment-tabs');
                    if (envTabs) {
                        envTabs.classList.add('flex-display');

                        const activeEnvTab = document.querySelector('.environment-tab.active-env-tab');
                        if (!activeEnvTab) {
                            const allEnvTab = document.querySelector('.environment-tab[data-env="all"]');
                            if (allEnvTab) allEnvTab.classList.add('active-env-tab');
                        }
                    }

                    filterProjectsByProduct(this.dataset.product);

                    document.querySelectorAll('.product-tab').forEach(t => {
                        t.classList.remove('active-tab');
                    });

                    this.classList.add('active-tab');
                });

                tabContainer.appendChild(tab);
            });

            const projectsHeader = document.querySelector('h1');
            if (projectsHeader) {
                projectsHeader.parentNode.insertBefore(tabContainer, projectsHeader.nextSibling);

                addEnvironmentTabs(projectsHeader.parentNode, tabContainer);
                addCategoryFilters(projectsHeader.parentNode);

                const envTabs = document.getElementById('environment-tabs');
                if (envTabs) {
                    envTabs.classList.add('flex-display');
                }
            }
        }
    }

    function addEnvironmentTabs(parentNode, tabContainer) {
        const envTabContainer = document.createElement('div');
        envTabContainer.id = 'environment-tabs';

        const environments = [
            { name: 'All Environments', value: 'all', class: '' },
            { name: '🏗️ Stage', value: 'stage', class: 'stage-tab' },
            { name: '🧬 Stage Plus', value: 'stage plus', class: 'stage-plus-tab' },
            { name: '🏭 Stable', value: 'stable', class: 'stable-tab' }
        ];

        environments.forEach(env => {
            const tab = document.createElement('button');
            tab.innerText = env.name;
            tab.dataset.env = env.value;
            tab.classList.add('environment-tab');
            if (env.class) tab.classList.add(env.class);

            if (env.name === 'All Environments') {
                tab.classList.add('active-env-tab');
            }

            tab.addEventListener('click', function() {
                filterProjectsByEnvironment(this.dataset.env);

                document.querySelectorAll('.environment-tab').forEach(t => {
                    t.classList.remove('active-env-tab');
                });

                this.classList.add('active-env-tab');
            });

            envTabContainer.appendChild(tab);
        });

        document.body.appendChild(envTabContainer);
    }

    function addCategoryFilters(parentNode) {
        const categoryContainer = document.createElement('div');
        categoryContainer.id = 'category-filters';

        const labelSpan = document.createElement('span');
        labelSpan.classList.add('category-label');
        labelSpan.innerText = 'Filter by platform:';
        categoryContainer.appendChild(labelSpan);

        const categories = [
            { name: 'All', class: '' },
            { name: 'WEB', class: 'category-web' },
            { name: 'KITE', class: 'category-kite' },
            { name: 'Android', class: 'category-android' },
            { name: 'iOS', class: 'category-ios' },
            { name: 'Mobile KITE', class: 'category-mobile-kite' }
        ];

        categories.forEach(category => {
            const button = document.createElement('button');
            button.innerText = category.name;
            button.dataset.category = category.name.toLowerCase();
            button.classList.add('category-button');
            if (category.class) button.classList.add(category.class);

            if (category.name === 'All') {
                button.classList.add('active-category');
            }

            button.addEventListener('click', function() {
                filterProjectsByCategory(this.dataset.category);

                document.querySelectorAll('.category-button').forEach(b => {
                    b.classList.remove('active-category');
                });

                this.classList.add('active-category');
            });

            categoryContainer.appendChild(button);
        });

        const reportButton = document.createElement('button');
        reportButton.innerText = 'Create Report';
        reportButton.classList.add('category-button', 'report-button');
        reportButton.addEventListener('click', function() {
            const visibleProjects = Array.from(document.querySelectorAll('tr.project:not(.hidden-project)'));
            const entries = [];

            visibleProjects.forEach(tr => {
                const platformEl = tr.querySelector('th span');
                const platform = platformEl ? platformEl.innerText.trim() : '';

                const suiteEl = tr.querySelector('td a span');
                const suite = suiteEl ? suiteEl.innerText.trim() : '';

                const dateEl = tr.querySelector('td p.date-time');
                const date = dateEl ? dateEl.innerText.trim() : '';

                const countEl = tr.querySelector('span.count-number');
                const countRaw = countEl ? countEl.innerText.trim() : '0';

                const totalTestsEl = tr.querySelector('a.total-tests');
                let suitKey = totalTestsEl ? (totalTestsEl.getAttribute('data-suite') || '') : '';
                suitKey = suitKey.replace('stable: ', '').replace('stage: ', '');
                const totalFromMap = totalTests[suitKey] || 0;

                const count = parseInt(countRaw, 10) || 0;
                const total = totalFromMap;
                const percent = total > 0 ? (count / total * 100).toFixed(1) : '0.0';

                const linkEl = tr.querySelector('a.label--pass');
                let link = '';
                if (linkEl) {
                    const href = linkEl.getAttribute('href') || '';
                    const cleanPath = href.split('?')[0];
                    link = window.location.origin + cleanPath;
                }

                let statusEmoji = '';
                if (total > 0) {
                    if (count < total) statusEmoji = '⚠️ ';
                    else if (count > total) statusEmoji = '⬆️ ';
                    else statusEmoji = '✅ ';
                }

                entries.push({ platform, suite, date, count: countRaw, total, percent, statusEmoji, link });
            });

            entries.sort((a, b) => b.platform.localeCompare(a.platform));

            const blocks = entries.map(e =>
                `${e.statusEmoji} ${e.platform} ${e.suite} 📊 ${e.count}/${e.total} (${e.percent}%)\n${e.date} 🔗 ${e.link}`
            );

            const platformGroups = { WEB: { count: 0, total: 0 }, KITE: { count: 0, total: 0 }, ANDROID: { count: 0, total: 0 }, IOS: { count: 0, total: 0 } };
            entries.forEach(e => {
                const p = e.platform.toUpperCase();
                let group = null;
                if (p.includes('WEB')) group = 'WEB';
                else if (p.includes('KITE')) group = 'KITE';
                else if (p.includes('ANDROID')) group = 'ANDROID';
                else if (p.includes('IOS') || p.includes('IOS')) group = 'IOS';
                if (group && e.total > 0) {
                    platformGroups[group].count += parseInt(e.count, 10) || 0;
                    platformGroups[group].total += e.total;
                }
            });

            const summaryLines = ['VRT Autotests pass rate:'];
            ['WEB', 'KITE', 'ANDROID', 'IOS'].forEach(g => {
                const { count, total } = platformGroups[g];
                const rate = total > 0 ? (count / total * 100).toFixed(1) + '%' : 'n/a';
                summaryLines.push(`- ${g}: ${rate}`);
            });

            const text = summaryLines.join('\n') + '\n____________________\n' + blocks.join('\n\n');
            navigator.clipboard.writeText(text).catch(() => {
                const ta = document.createElement('textarea');
                ta.value = text;
                document.body.appendChild(ta);
                ta.select();
                document.execCommand('copy');
                document.body.removeChild(ta);
            });

            reportButton.innerText = 'Copied!';
            setTimeout(() => { reportButton.innerText = 'Report'; }, 1500);
        });

        categoryContainer.appendChild(reportButton);
        document.body.appendChild(categoryContainer);
    }

    function filterProjectsByProduct(product) {
        const projects = document.querySelectorAll('tr.project');
        const activeEnvTab = document.querySelector('.environment-tab.active-env-tab');
        const activeCategoryTab = document.querySelector('.category-button.active-category');

        const envFilter = activeEnvTab ? activeEnvTab.dataset.env : 'all';
        const categoryFilter = activeCategoryTab ? activeCategoryTab.dataset.category : 'all';

        projects.forEach(project => {
            const projectNameElement = project.querySelector('th');
            if (!projectNameElement) return;

            const projectName = projectNameElement.innerText.toLowerCase();
            const projectEnv = project.dataset.project?.toLowerCase() || '';

            let showProject = true;

            if (product !== 'all' && !projectName.includes(product)) {
                showProject = false;
            }

            if (product !== 'all' && envFilter !== 'all') {
                if (!matchesEnvironmentFilter(projectEnv, envFilter)) {
                    showProject = false;
                }
            }

            if (categoryFilter !== 'all') {
                if (!projectName.includes(categoryFilter.toLowerCase())) {
                    showProject = false;
                }
            }

            if (showProject) {
                project.classList.remove('hidden-project');
            } else {
                project.classList.add('hidden-project');
            }
        });
    }

    function filterProjectsByEnvironment(environment) {
        const activeProductTab = document.querySelector('.product-tab.active-tab');
        if (!activeProductTab) return;

        const activeCategoryTab = document.querySelector('.category-button.active-category');
        const product = activeProductTab.dataset.product?.toLowerCase() || 'all';
        const categoryFilter = activeCategoryTab?.dataset.category?.toLowerCase() || 'all';
        const env = environment.toLowerCase();

        document.querySelectorAll('tr.project').forEach(project => {
            const projectNameElement = project.querySelector('th');
            if (!projectNameElement) return;

            const projectName = projectNameElement.innerText.toLowerCase();

            const projectEnv = project.dataset.project?.toLowerCase() || '';

            console.log(projectEnv);

            if (product !== 'all' && !projectName.includes(product)) {
                project.classList.add('hidden-project');
                return;
            }

            if (env !== 'all' && !matchesEnvironmentFilter(projectEnv, env)) {
                project.classList.add('hidden-project');
                return;
            }

            if (categoryFilter !== 'all') {
                const isMobileKite = categoryFilter === 'mobile kite';
                const categoryMatch = isMobileKite
                ? projectName.includes('mobile') && projectName.includes('kite')
                : projectName.includes(categoryFilter);

                if (!categoryMatch) {
                    project.classList.add('hidden-project');
                    return;
                }
            }

            project.classList.remove('hidden-project');
        });
    }

    function filterProjectsByCategory(category) {
        const activeProductTab = document.querySelector('.product-tab.active-tab');
        const activeEnvTab = document.querySelector('.environment-tab.active-env-tab');

        if (!activeProductTab) return;

        const product = activeProductTab.dataset.product;
        const environment = activeEnvTab ? activeEnvTab.dataset.env : 'all';

        const projects = document.querySelectorAll('tr.project');

        projects.forEach(project => {
            const projectNameElement = project.querySelector('th');
            if (!projectNameElement) return;

            const projectName = projectNameElement.innerText.toLowerCase();
            const projectEnv = project.dataset.project?.toLowerCase() || '';
            let showProject = true;

            console.log(projectName);

            if (product !== 'all' && !projectName.includes(product)) {
                showProject = false;
            }

            if (environment !== 'all' && !matchesEnvironmentFilter(projectEnv, environment)) {
                showProject = false;
            }

            if (category !== 'all') {
                if (category === 'mobile kite') {
                    if (!projectName.includes('mobile') || !projectName.includes('kite')) {
                        showProject = false;
                    }
                } else if (!projectName.includes(category)) {
                    showProject = false;
                }
            }

            if (showProject) {
                project.classList.remove('hidden-project');
            } else {
                project.classList.add('hidden-project');
            }
        });
    }

    function hasStagePlusEntry(projectEnv) {
        return stagePlusProjects.some(project => projectEnv.includes(project.toLowerCase()));
    }

    function matchesEnvironmentFilter(projectEnv, env) {
        if (env === 'all') return true;

        if (env === 'stage') {
            return projectEnv.includes('stage') && !hasStagePlusEntry(projectEnv);
        }

        if (env === 'stage plus') {
            return projectEnv.includes('stage') && hasStagePlusEntry(projectEnv);
        }

        if (env === 'stable') {
            return projectEnv.includes('stable');
        }

        return projectEnv.includes(env);
    }

    function combineFilterElements() {
        const productTabs = document.getElementById('product-tabs');
        const envTabs = document.getElementById('environment-tabs');
        const categoryFilters = document.getElementById('category-filters');

        if (productTabs && envTabs && categoryFilters) {
            const combinedContainer = document.createElement('div');
            combinedContainer.id = 'combined-filters';

            if (productTabs.parentNode) {
                productTabs.parentNode.insertBefore(combinedContainer, productTabs.nextSibling);
            }
            combinedContainer.appendChild(envTabs);
            combinedContainer.appendChild(categoryFilters);
        }
    }


    function addRowDividers() {
        const projectRows = document.querySelectorAll('tr.project');
        projectRows.forEach(row => {
            row.classList.add('border-bottom-black');
        });
    }

    function hideProjectsHeader() {
        const projectsHeader = document.querySelector('h1');
        if (projectsHeader && projectsHeader.textContent.includes('Projects')) {
            projectsHeader.classList.add('hidden-element');
        }
    }

    function adjustColumnWidths() {
        const projectsTable = document.getElementById('projects');
        if (!projectsTable) return;

        const projectRows = projectsTable.querySelectorAll('tr.project');
        if (!projectRows.length) return;

        const headerRow = projectsTable.querySelector('thead tr');
        if (headerRow && !headerRow.querySelector('.date-info-header')) {
            const lastRunHeader = headerRow.querySelector('th:nth-child(3)');
            if (lastRunHeader) {
                lastRunHeader.innerHTML = `
                    <div class="dynamic-header-content">
                        <div class="dynamic-header-date">Дата запуска</div>
                        <div class="dynamic-header-results">Результаты тестов</div>
                    </div>
                `;
                lastRunHeader.classList.add('date-info-header', 'dynamic-header-style');
            }
        }

        projectRows.forEach(row => {
            const lastRunCell = row.querySelector('td:nth-child(3)');
            if (lastRunCell && !lastRunCell.querySelector('.split-cell-container')) {
                const dateInfo = lastRunCell.querySelector('span.text-muted');
                const dateTimeElement = lastRunCell.querySelector('.date-time');
                const buttons = lastRunCell.querySelectorAll('.label--fail, .label--pass, .label--warning, a.total-tests, .low-diff-button');
                const splitContainer = document.createElement('div');
                splitContainer.classList.add('split-cell-container', 'dynamic-split-container');

                const dateSection = document.createElement('div');
                dateSection.classList.add('dynamic-date-section');

                if (dateInfo) {
                    dateSection.appendChild(dateInfo.cloneNode(true));
                }
                if (dateTimeElement) {
                    dateSection.appendChild(dateTimeElement.cloneNode(true));
                }

                const buttonsSection = document.createElement('div');
                buttonsSection.classList.add('dynamic-buttons-section');

                buttons.forEach(button => {
                    button.classList.add('label-minimal-padding');
                    buttonsSection.appendChild(button);
                });

                splitContainer.appendChild(dateSection);
                splitContainer.appendChild(buttonsSection);

                lastRunCell.innerHTML = '';
                lastRunCell.appendChild(splitContainer);
                lastRunCell.classList.add('dynamic-last-run-cell');
            }
        });

        const nameHeaders = projectsTable.querySelectorAll('th:first-child, td:first-child');
        nameHeaders.forEach(header => {
            header.classList.add('column-name-width');
        });

        const suiteHeaders = projectsTable.querySelectorAll('th:nth-child(2), td:nth-child(2)');
        suiteHeaders.forEach(header => {
            header.classList.add('column-suite-width');
        });
    }

    function highlightProjectAge() {
        const projectRows = document.querySelectorAll('tr.project');

        projectRows.forEach(row => {
            const dateTimeSpan = row.querySelector('td span.text-muted');
            if (!dateTimeSpan) return;

            const dateText = dateTimeSpan.innerText;

            if ((dateText.includes('days ago') && parseInt(dateText, 10) > 1) || dateText.includes('month ago') || dateText.includes('months ago') || dateText.includes('year ago') || dateText.includes('years ago')) {
                row.classList.add('old-project-row');
            }

            if (dateText.includes('days ago') && parseInt(dateText, 10) > 3) {
                row.classList.add('very-old-project-row');
            }
        });
    }



    function addLowDiffButtons() {
        // Работаем на странице /projects и на страницах с таблицами Latest runs
        if (window.location.pathname === '/projects' ||
            window.location.pathname.includes('/suites/') ||
            document.querySelector('table') ||
            document.querySelector('tr.project')) {

            // Ищем строки проектов в разных таблицах
            const projectRows = document.querySelectorAll('tr.project, tr[data-project], tbody tr');

            projectRows.forEach((row, index) => {
                // Пропускаем строки заголовков
                if (row.querySelector('th') && !row.querySelector('td')) {
                    return;
                }

                let buttonsSection = row.querySelector('.split-cell-container > div:last-child');
                if (!buttonsSection) {
                    // Ищем последнюю ячейку с кнопками
                    const cells = row.querySelectorAll('td');
                    if (cells.length > 0) {
                        buttonsSection = cells[cells.length - 1];
                    }
                }

                if (!buttonsSection || buttonsSection.querySelector('.low-diff-button')) {
                    return;
                }

                let allLinks = buttonsSection.querySelectorAll('a');
                let failedLink = null;
                for (let link of allLinks) {
                    const text = link.textContent.toLowerCase().trim();
                    const computedStyle = window.getComputedStyle(link);
                    const backgroundColor = computedStyle.backgroundColor;

                    if (text.includes('failed') ||
                        backgroundColor.includes('rgb(220, 53, 69)') ||
                        backgroundColor.includes('rgb(217, 83, 79)') ||
                        link.classList.contains('label--fail')) {
                        failedLink = link;
                        break;
                    }
                }

                if (!failedLink && allLinks.length > 0) {
                    failedLink = allLinks[allLinks.length - 1];
                }

                if (failedLink && failedLink.href) {
                    const url = new URL(failedLink.href);
                    url.searchParams.set('status', 'pass');
                    url.searchParams.set('diff', 'low-diff');

                    const lowDiffButton = document.createElement('a');
                    lowDiffButton.href = url.toString();
                    lowDiffButton.textContent = 'LD';
                    lowDiffButton.className = 'low-diff-button label-minimal-padding';
                    lowDiffButton.title = 'Показать тесты с низкими различиями (Low diff)';

                    buttonsSection.appendChild(lowDiffButton);
                }
            });
        }
    }



    function setupBaselineButtons() {
        function isMassEditingControl(el) {
            if (!el) return false;
            try {
                return el.hasAttribute('data-mass-editing-control') || !!el.closest('.mass-editing-controls');
            } catch (e) {
                return false;
            }
        }

        function handleBaselineClick(event) {
            // Не трогаем элементы управления массовым режимом
            if (isMassEditingControl(this)) return;
            this.classList.add('baseline-button-success', 'dynamic-baseline-button');
            showBaselineNotification();
            event.stopPropagation();
        }

        function findAndSetupBaselineButtons() {
            const selectors = [
                'button',
                '.btn',
                'input[type="button"]',
                'input[type="submit"]',
                'a[role="button"]',
                'a.btn',
                '[onclick*="baseline"]',
                '[onclick*="Baseline"]'
            ];

            selectors.forEach(selector => {
                const buttons = document.querySelectorAll(selector);
                buttons.forEach(button => {
                    if (isMassEditingControl(button)) return;
                    const text = (button.textContent || button.value || button.title || button.getAttribute('onclick') || '').toLowerCase();
                    if ((text.includes('baseline') || text.includes('set as baseline')) && !button.hasAttribute('data-baseline-listener')) {
                        button.addEventListener('click', handleBaselineClick);
                        button.setAttribute('data-baseline-listener', 'true');
                    }
                });
            });
        }

        findAndSetupBaselineButtons();

        const observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                mutation.addedNodes.forEach(function(node) {
                    if (node.nodeType === 1) {
                        if (isMassEditingControl(node)) return;
                        const text = (node.textContent || node.value || node.title || '').toLowerCase();
                        if ((node.tagName === 'BUTTON' || node.classList.contains('btn') || node.tagName === 'A') &&
                            (text.includes('baseline') || text.includes('set as baseline')) && !node.hasAttribute('data-baseline-listener')) {
                            node.addEventListener('click', handleBaselineClick);
                            node.setAttribute('data-baseline-listener', 'true');
                        }

                        if (node.querySelectorAll) {
                            findAndSetupBaselineButtons();
                        }
                    }
                });
            });
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        setInterval(findAndSetupBaselineButtons, 2000);
    }

    function showBaselineNotification() {
        const existingNotifications = document.querySelectorAll('.baseline-notification');
        existingNotifications.forEach(notif => notif.remove());

        const notification = document.createElement('div');
        notification.classList.add('baseline-notification', 'dynamic-notification');
        notification.innerHTML = '✅ Baseline успешно применен!';
        document.body.appendChild(notification);

        setTimeout(() => notification.classList.add('show'), 100);
        setTimeout(() => {
            notification.classList.remove('show');
            setTimeout(() => notification.remove(), 300);
        }, 3000);
    }

    // Selectors
    const differenceMarkElements = document.querySelectorAll('span.test__diff.text-muted');

    function addDifferencesMarks() {
        let testRow, testName, testEnv;
        const positive = '<img src="https://github.githubassets.com/images/icons/emoji/unicode/2714.png" width="32" height="32">';

        for (let elem of differenceMarkElements) {
            text = elem.innerHTML;
            testRow = elem.parentElement.parentElement;
            if (elem.innerHTML === 'No difference') {
                elem.innerHTML = positive + text;
                testRow.classList.add('pass');
            } else {
                score = parseFloat(elem.innerHTML);
                if (score <= 0.05) {
                    elem.innerHTML = `<img src="https://github.githubassets.com/images/icons/emoji/unicode/2754.png" class="diff-icon"><span class="diff-score-low">${score}%</span><br />${text}`;
                } else if (score > 0.05) {
                    elem.innerHTML = `<img src="https://github.githubassets.com/images/icons/emoji/unicode/2716.png" class="diff-icon"><span class="diff-score-high">${score}%</span><br />${text}`;
                }
                if (score < 0.10) {
                    lowDiffCount += 1;
                    const testNameElement = testRow.querySelector('.test__name');
                    const testEnvElement = testRow.querySelector('th p');

                    if (testNameElement && testEnvElement) {
                        testName = testNameElement.innerText;
                        testEnv = testEnvElement.innerText;

                        if (testName !== testNamePrev) {
                            testLowDiffTitle = `${testLowDiffTitle} ${testName} - ${testEnv}\n`;
                            testNamePrev = testName;
                            lowDiffCountUniq += 1;
                        }
                    }
                }
                testRow.classList.add('diffed');
            }
        }
    }

    function footerAndHeader() {
        if (window.location.pathname.indexOf('/runs/') !== -1) {
            const h1 = document.querySelector('div h1');
            if (h1) {
                const lowDiffP = document.createElement('p');
                lowDiffP.classList.add('low-difference-count');
                lowDiffP.innerText = `Low diff tests: ${lowDiffCountUniq} / Low diff screenshots: ${lowDiffCount}`;
                lowDiffP.title = testLowDiffTitle;
                insertAfter(lowDiffP, h1);

                addDownloadBlock();
                bindRunImagesDownload();
            }
        }
    }

    function sanitizeDownloadFilenamePart(value) {
        return String(value || '')
            .replace(/\s\s+/g, ' ')
            .replace(/,/g, '')
            .replace(/\s+/g, '-')
            .replace(/[\\/:*?"<>|]+/g, '-')
            .replace(/-+/g, '-')
            .replace(/^-|-$/g, '');
    }

    function getArchiveNameFromPage() {
        const containerHeader = $('.container').find('h1');
        const name = containerHeader.length ? containerHeader.text().trim() : '';
        return sanitizeDownloadFilenamePart(name) || 'spectre-export';
    }

    function generateImagesZip(zip, archiveName) {
        return zip.generateAsync({ type: 'blob' }, function updateCallback(metadata) {
            let msg = 'progression : ' + metadata.percent.toFixed(2) + ' %';
            if (metadata.currentFile) {
                msg += ', current file = ' + metadata.currentFile;
            }
            showMessage(msg);
            updatePercent(Math.floor(metadata.percent));
        }).then(function callback(blob) {
            saveAs(blob, archiveName + '.zip');
            showMessage('Done! Archive created successfully.');
        }, function (e) {
            showError(e);
        });
    }

    function bindRunImagesDownload() {
        const archiveName = getArchiveNameFromPage();
        const imageExtension = '.png';

        $('#download-images').off('click.spectreRunDownload').on('click.spectreRunDownload', function () {
            resetMessage();
            const zip = new JSZip();
            let fileCount = 0;

            $('tr.test').each(function () {
                const $this = $(this);
                const testImgLink = $this.find('td#image-test a.test__image');
                if (!testImgLink.length) return;

                const url = testImgLink.attr('data-href') || testImgLink.attr('href');
                const testNameElement = $this.find('span.test__name');
                const testInfoElement = $this.find('small.text-muted');

                if (!url || !testNameElement.length || !testInfoElement.length) return;

                const testName = sanitizeDownloadFilenamePart(testNameElement.text());
                const testInfo = sanitizeDownloadFilenamePart(testInfoElement.text());
                const filename = testName + testInfo;
                zip.file(filename + imageExtension, urlToPromise(url), { binary: true });
                fileCount += 1;
            });

            if (!fileCount) {
                showError('No images found to download.');
                return false;
            }

            generateImagesZip(zip, archiveName);
            return false;
        });
    }

    function getBaselineDownloadFilename(row, link, usedNames) {
        const href = link.getAttribute('data-href') || link.getAttribute('href') || '';
        let filename = '';

        try {
            const path = new URL(href, window.location.origin).pathname;
            filename = path.split('/').pop() || '';
        } catch (e) {
            filename = '';
        }

        if (!filename || filename.indexOf('.') === -1) {
            const name = sanitizeDownloadFilenamePart(getBaselineRowName(row));
            const cells = row ? row.querySelectorAll('td') : [];
            const browser = cells.length > 0 ? sanitizeDownloadFilenamePart(cells[0].textContent) : '';
            const size = cells.length > 1 ? sanitizeDownloadFilenamePart(cells[1].textContent) : '';
            filename = [name, browser, size].filter(Boolean).join('-') + '.png';
        }

        filename = sanitizeDownloadFilenamePart(filename.replace(/\.png$/i, '')) + '.png';

        let unique = filename;
        let n = 2;
        while (usedNames[unique]) {
            unique = filename.replace(/\.png$/i, '') + '-' + n + '.png';
            n += 1;
        }
        usedNames[unique] = true;
        return unique;
    }

    function setupBaselineImageDownload() {
        if (!isSuiteBaselinesPage()) return;
        if (document.getElementById('download-block')) return;

        addDownloadBlock({
            footerText: 'All baseline images from the current suite will be archived',
        });

        const archiveName = getArchiveNameFromPage();

        $('#download-images').off('click.spectreBaselineDownload').on('click.spectreBaselineDownload', function () {
            resetMessage();
            const zip = new JSZip();
            const usedNames = {};
            let fileCount = 0;

            document.querySelectorAll('tr.baseline a.baseline__image').forEach(function(link) {
                const url = link.getAttribute('data-href') || link.getAttribute('href');
                if (!url) return;

                const row = link.closest('tr');
                const filename = getBaselineDownloadFilename(row, link, usedNames);
                zip.file(filename, urlToPromise(url), { binary: true });
                fileCount += 1;
            });

            if (!fileCount) {
                showError('No baseline images found to download.');
                return false;
            }

            generateImagesZip(zip, archiveName);
            return false;
        });
    }

    function setupSimpleImageLightboxes() {
        const imgClass = getSimpleLightboxImgClass();
        const modal = getOrCreateSimpleLightboxModal(imgClass);

        ['image-baseline', 'image-test', 'image-diff'].forEach(function(columnId) {
            document.querySelectorAll('td[id="' + columnId + '"]').forEach(function(cell) {
                const link = findSimpleLightboxLink(cell);
                if (!prepareSimpleLightboxLink(link)) return;
                if (link.hasAttribute('data-simple-lightbox-bound')) return;
                link.setAttribute('data-simple-lightbox-bound', 'true');

                link.addEventListener('click', function() {
                    _imageLightboxModalClass = imgClass;
                    activateSimpleImageLightboxNav(link, columnId);
                    openSimpleLightboxModal(modal, link.getAttribute('data-href'));
                    bindSimpleLightboxCloseHandlers(modal);
                });
            });
        });
    }

    function addVisualComparisonButtons() {
        let pics, picReference, picCurrent;
        let failedTests = document.querySelectorAll('.diffed');

        failedTests.forEach(test => {
            if (!test) return;

            pics = test.querySelectorAll('a.test__image');
            if (!pics || pics.length < 2) return;

            pics.forEach(pic => {
                if (pic) pic.classList.add('diffBtn');
            });

            picReference = pics[0].href;
            picCurrent = pics[1].href;

            if (test.id && picReference && picCurrent) {
                addModalWindows(test.id, picReference, picCurrent, test);
            }
        });

        const failedButtons = document.querySelectorAll('.diffed .test__diff');
        failedButtons.forEach(button => {
            if (!button || !button.parentElement || !button.parentElement.parentElement) return;

            let parentId = button.parentElement.parentElement.id;
            if (parentId) {
                addElementButton(parentId, button);
            }
        });

        setListener();
        setViewers();
    }

    function improveDateTime() {
        let dateElements = document.querySelectorAll('td.text-muted span');
        dateElements.forEach(el => {
            if (!el) return;

            let dateTime = el.getAttribute('Title');
            if (dateTime) {
                addElementPTime(el, dateTime);
            }
        });

        dateElements = document.querySelectorAll('#test_count span.text-muted span');
        let parentCells = document.querySelectorAll('td#test_count');
        let parentRows = document.querySelectorAll('tr.project');

        dateElements.forEach(function(el, index) {
            if (!el || !parentCells[index]) return;

            let dateTime = el.getAttribute('Title');
            let dateText = el.innerText;
            let row = parentRows[index];

            if (dateText) {
                if (dateText.includes('month ago') || dateText.includes('months ago') || dateText.includes('year ago')) {
                    el.classList.add('date-old');
                    if (row) row.classList.add('project-old');
                } else if (dateText.includes('days ago')) {
                    const daysMatch = dateText.match(/(\d+) days ago/);
                    if (daysMatch && daysMatch[1]) {
                        const days = parseInt(daysMatch[1], 10);
                        if (days > 3) {
                            el.classList.add('date-old');
                            if (row) row.classList.add('project-very-old');
                        }
                    }
                }
            }

            if (dateTime) {
                let newP = document.createElement('p');
                newP.classList.add('date-time');
                newP.innerHTML = '🕒 ' + dateTime;
                parentCells[index].appendChild(newP);
            }
        });
    }

    function envStyle() {
        let nameElements = document.querySelectorAll('.project a');
        nameElements.forEach(el => {
            if (!el) return;

            let content = el.outerText ? el.outerText.toLowerCase() : '';

            if (content.includes('stage')) {
                el.innerHTML = '🏗️ <span class="env-stage">' + el.innerHTML + '</span>';
            } else if (content.includes('prod')) {
                el.innerHTML = '🏢 ' + el.innerHTML;
            } else if (content.includes('stable')) {
                el.innerHTML = '🏭 <span class="env-stable">' + el.innerHTML + '</span>';
            }
        });
    }

    function productStyle() {
        let nameElements = document.querySelectorAll('.project th');
        nameElements.forEach(el => {
            if (!el) return;

            let text = el.innerText ? el.innerText.toLowerCase() : '';

            if (text.includes('x-bees')) {
                el.innerHTML = '<span class="product-x-bees">' + el.innerHTML + '</span>';
            } else if (text.includes('x-hoppers')) {
                el.innerHTML = '<span class="product-x-hoppers">' + el.innerHTML + '</span>';
            } else if (text.includes('collaboration')) {
                el.innerHTML = '<span class="product-collaboration">' + el.innerHTML + '</span>';
            }
        });
    }

    function lowDiffFilter() {
        if ((window.location.pathname.indexOf('/suites/') !== -1) && (window.location.pathname.indexOf('/runs/') !== -1)) {
            let filtersForm = document.querySelector('div.filters form');
            if (!filtersForm) return;

            let selectDiff = document.createElement('select');
            selectDiff.name = 'diff';
            selectDiff.id = 'diff';
            selectDiff.classList.add('form-control');

            let optionAll = document.createElement('option');
            optionAll.value = 'All';
            optionAll.innerText = 'All';

            let optionLowDiff = document.createElement('option');
            optionLowDiff.value = 'low-diff';
            optionLowDiff.innerText = 'Low diff';

            selectDiff.appendChild(optionAll);
            selectDiff.appendChild(optionLowDiff);

            // Проверяем URL-параметры при загрузке страницы
            const urlParams = new URLSearchParams(window.location.search);
            const diffParam = urlParams.get('diff');

            if (diffParam === 'low-diff') {
                selectDiff.value = 'low-diff';
                // Автоматически применяем фильтр
                setTimeout(() => {
                    let tests = document.querySelectorAll('.pass, .test--fail');
                    tests.forEach(test => {
                        if (test) test.remove();
                    });
                }, 1000); // Небольшая задержка для загрузки элементов
            }

            selectDiff.addEventListener('change', function() {
                let tests = document.querySelectorAll('.pass, .test--fail');

                if (this.value === 'low-diff') {
                    tests.forEach(test => {
                        if (test) test.remove();
                    });
                    // Обновляем URL с параметром
                    const newUrl = new URL(window.location);
                    newUrl.searchParams.set('diff', 'low-diff');
                    window.history.pushState({}, '', newUrl);
                } else {
                    // Удаляем параметр из URL и перезагружаем
                    const newUrl = new URL(window.location);
                    newUrl.searchParams.delete('diff');
                    window.location.href = newUrl.toString();
                }
            });

            filtersForm.appendChild(selectDiff);
        }
    }

    function initMassBaselineEditing() {
        const isRunsInSuite =
            window.location.pathname.includes('/suites/') &&
            window.location.pathname.includes('/runs/');
        if (!isRunsInSuite) return;

        const STATE = {
            injected: false,
            mode: 'idle', // idle | scanned
            baselineInputs: [],
            checkboxRecords: [], // { checkbox, label, onChange }
            hudEl: null,
            filtersEl: null,
            controlsEl: null,
            btnMass: null,
            btnSet: null,
            btnCancel: null,
            onMassClick: null,
            onSetClick: null,
            onCancelClick: null,
        };

        function ensureInjected() {
            if (STATE.injected) return true;

            const filters = document.querySelector('div.filters');
            const form = document.querySelector('div.filters form');
            if (!filters || !form) return false;

            STATE.filtersEl = filters;
            filters.classList.add('mass-editing-filters');

            const controls = document.createElement('div');
            controls.className = 'mass-editing-controls';

            const btnMass = document.createElement('button');
            btnMass.type = 'button';
            btnMass.className = 'test-compare-button';
            btnMass.textContent = 'Mass editing';
            btnMass.setAttribute('data-mass-editing-control', 'true');

            const btnSet = document.createElement('button');
            btnSet.type = 'button';
            btnSet.className = 'test-fail-button';
            btnSet.textContent = 'Set baselines';
            btnSet.hidden = true;
            btnSet.setAttribute('data-mass-editing-control', 'true');

            const btnCancel = document.createElement('button');
            btnCancel.type = 'button';
            btnCancel.className = 'test-baseline-button';
            btnCancel.textContent = 'Cancel';
            btnCancel.hidden = true;
            btnCancel.setAttribute('data-mass-editing-control', 'true');

            const shortcutsToggle = document.createElement('label');
            shortcutsToggle.className = 'lightbox-shortcuts-toggle';
            shortcutsToggle.setAttribute('data-mass-editing-control', 'true');
            shortcutsToggle.title = '';

            const shortcutsIcon = document.createElement('span');
            shortcutsIcon.className = 'lightbox-shortcuts-toggle__icon';
            shortcutsIcon.setAttribute('aria-hidden', 'true');
            shortcutsIcon.textContent = '⌨';

            const shortcutsCheckbox = document.createElement('input');
            shortcutsCheckbox.type = 'checkbox';
            shortcutsCheckbox.checked = false;
            shortcutsCheckbox.className = 'lightbox-shortcuts-toggle__input';
            shortcutsCheckbox.setAttribute('data-lightbox-shortcuts-toggle', 'true');

            const shortcutsTooltip = document.createElement('span');
            shortcutsTooltip.className = 'lightbox-shortcuts-toggle__tooltip';
            shortcutsTooltip.innerHTML =
                '<strong>Shortcuts (only in compare mode)</strong>' +
                '↓ / → - Next<br>' +
                '↑ / ← - Previous<br>' +
                'A - Accept as baseline, next<br>' +
                'S - Skip, next<br>' +
                'Y - Auto diff highlights<br>';

            shortcutsToggle.appendChild(shortcutsCheckbox);
            shortcutsToggle.appendChild(shortcutsIcon);
            shortcutsToggle.appendChild(shortcutsTooltip);

            shortcutsCheckbox.addEventListener('change', function() {
                _lightboxShortcutsEnabled = shortcutsCheckbox.checked;
                if (!_lightboxShortcutsEnabled && _autoDiffHighlightsEnabled) {
                    setAutoDiffHighlightsEnabled(false);
                }
            });

            controls.appendChild(shortcutsToggle);
            controls.appendChild(btnMass);
            controls.appendChild(btnSet);
            controls.appendChild(btnCancel);

            form.insertAdjacentElement('afterend', controls);

            STATE.controlsEl = controls;
            STATE.btnMass = btnMass;
            STATE.btnSet = btnSet;
            STATE.btnCancel = btnCancel;

            STATE.onMassClick = () => startMassEditing();
            STATE.onSetClick = () => handleSetBaselines();
            STATE.onCancelClick = () => cleanupToIdle();

            btnMass.addEventListener('click', STATE.onMassClick);
            btnSet.addEventListener('click', STATE.onSetClick);
            btnCancel.addEventListener('click', STATE.onCancelClick);

            STATE.injected = true;
            return true;
        }

        function startMassEditing() {
            if (!ensureInjected()) return;
            if (STATE.mode !== 'idle') return;

            // Standard browser confirm: OK = "Go fast", Cancel = "Cancel"
            const ok = confirm("We can do this fast or slow, it's your call.\nMass editing can permanently change multiple screenshots.");
            if (!ok) return;

            STATE.btnMass.hidden = true;
            STATE.btnSet.hidden = false;
            STATE.btnCancel.hidden = false;

            // По требованию: сканируем сразу при нажатии Mass editing
            scanAndRender();
        }

        function createHudIfNeeded() {
            if (STATE.hudEl) return;
            const hud = document.createElement('div');
            hud.className = 'mass-editing-hud';
            hud.textContent = 'SELECTED DIFFS: 0/0';
            document.body.appendChild(hud);
            STATE.hudEl = hud;
        }

        function updateHud() {
            if (!STATE.hudEl) return;
            const found = STATE.baselineInputs.length;
            const selected = STATE.checkboxRecords.reduce((acc, r) => acc + (r.checkbox.checked ? 1 : 0), 0);
            STATE.hudEl.textContent = `SELECTED DIFFS: ${selected}/${found}`;
        }

        function scanAndRender() {
            // Очищаем возможные хвосты предыдущего скана, если что-то пошло не так
            removeCheckboxesAndHud();

            const inputs = Array.from(document.querySelectorAll('input.test__set-baseline'));
            STATE.baselineInputs = inputs;

            if (!inputs.length) {
                // Standard browser confirm: OK = "I know what I am doing", Cancel = "Cancel"
                confirm("Have you tried turning it off and on again?\nNo changes were detected.");
                cleanupToIdle();
                return false;
            }

            createHudIfNeeded();

            inputs.forEach((baselineInput, idx) => {
                if (!baselineInput || !baselineInput.parentElement) return;
                if (baselineInput.hasAttribute('data-mass-baseline-processed')) return;

                baselineInput.setAttribute('data-mass-baseline-processed', 'true');

                const label = document.createElement('label');
                label.className = 'mass-baseline-label';

                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkbox.checked = true;
                checkbox.setAttribute('data-mass-baseline-index', String(idx));

                const textNode = document.createTextNode('Set as a baseline');
                label.appendChild(checkbox);
                label.appendChild(textNode);

                baselineInput.insertAdjacentElement('afterend', label);

                const onChange = () => updateHud();
                checkbox.addEventListener('change', onChange);

                STATE.checkboxRecords.push({ checkbox, label, onChange });
            });

            updateHud();
            STATE.mode = 'scanned';
            return true;
        }

        async function applySelectedBaselines() {
            const selectedIndices = STATE.checkboxRecords
                .filter(r => r.checkbox.checked)
                .map(r => parseInt(r.checkbox.getAttribute('data-mass-baseline-index') || '', 10))
                .filter(n => Number.isFinite(n));

            const selectedInputs = selectedIndices
                .map(i => STATE.baselineInputs[i])
                .filter(Boolean);

            const selectedCount = selectedInputs.length;

            // Standard browser confirm: OK/Cancel
            const ok = confirm("WARNING: That's one way to get your attention…\nProceed only if you’re confident.");
            if (!ok) return;

            // Standard browser input (prompt): require safety phrase
            const phrase = prompt('Type "THEBEAST" for confirmation:', '');
            if (phrase !== 'THEBEAST') {
                alert('Aborted.');
                return;
            }

            // Блокируем кнопки на время выполнения
            STATE.btnSet.disabled = true;
            STATE.btnCancel.disabled = true;

            for (let i = 0; i < selectedInputs.length; i++) {
                try {
                    selectedInputs[i].click();
                } catch (e) {
                    // игнорируем единичные ошибки клика
                }
                await new Promise(r => setTimeout(r, 250));
            }

            cleanupToIdle();

            // Standard browser confirm: OK = refresh, Cancel = stay
            const refresh = confirm(`UPDATED ${selectedCount} BASELINES\n\nREFRESH THE PAGE?`);
            if (refresh) {
                window.location.reload();
            }
        }

        function handleSetBaselines() {
            if (!ensureInjected()) return;

            if (STATE.mode !== 'scanned') {
                const ok = scanAndRender();
                if (!ok) return;
            }

            applySelectedBaselines();
        }

        function removeCheckboxesAndHud() {
            STATE.checkboxRecords.forEach(r => {
                try {
                    r.checkbox.removeEventListener('change', r.onChange);
                } catch (e) {}
                try {
                    if (r.label) r.label.remove();
                } catch (e) {}
            });
            STATE.checkboxRecords = [];

            // Снимаем метки обработанности, чтобы повторный вход работал корректно
            try {
                document.querySelectorAll('input.test__set-baseline[data-mass-baseline-processed="true"]').forEach(el => {
                    el.removeAttribute('data-mass-baseline-processed');
                });
            } catch (e) {}

            if (STATE.hudEl) {
                try { STATE.hudEl.remove(); } catch (e) {}
                STATE.hudEl = null;
            }

            STATE.baselineInputs = [];
        }

        function cleanupToIdle() {
            if (!ensureInjected()) return;

            removeCheckboxesAndHud();

            STATE.mode = 'idle';
            STATE.btnSet.disabled = false;
            STATE.btnCancel.disabled = false;

            // На всякий случай убираем "успешные" классы, если кто-то их навесил
            STATE.btnMass.classList.remove('baseline-button-success', 'dynamic-baseline-button');
            STATE.btnSet.classList.remove('baseline-button-success', 'dynamic-baseline-button');
            STATE.btnCancel.classList.remove('baseline-button-success', 'dynamic-baseline-button');

            STATE.btnMass.hidden = false;
            STATE.btnSet.hidden = true;
            STATE.btnCancel.hidden = true;
        }

        // Пытаемся сразу, и на случай поздней отрисовки фильтров — наблюдатель
        if (!ensureInjected()) {
            const obs = new MutationObserver(() => {
                if (ensureInjected()) obs.disconnect();
            });
            obs.observe(document.body, { childList: true, subtree: true });
        }
    }

    function totalTestCount() {
        let executedTestsElements = document.querySelectorAll('a.total-tests');

        if (executedTestsElements && executedTestsElements.length > 0) {
            executedTestsElements.forEach(el => {
                if (!el) return;

                let newCount;
                let count = parseInt(el.textContent, 10);
                let suitName = el.getAttribute('data-suite');

                if (!suitName) return;

                suitName = suitName.replace('stable: ', '').replace('stage: ', '');

                if (totalTests[suitName]) {
                    if (count === totalTests[suitName]) {
                        newCount = `<span class="count-number">${count}</span><sup class="count-sup">${totalTests[suitName]}</sup>`;
                    } else if (count < totalTests[suitName]) {
                        newCount = `<span class="count-warning count-number">${count}</span><sup class="count-sup">${totalTests[suitName]}</sup>`;
                    } else {
                        newCount = `<span class="count-number">${count}</span><sup class="count-sup"><span class="count-excess count-number">${totalTests[suitName]}</span></sup>`;
                    }

                    el.innerHTML = newCount;

                    const iconSpan = document.createElement('span');
                    iconSpan.classList.add('icon-span');

                    if (count < totalTests[suitName]) {
                        iconSpan.textContent = '⚠️';
                    } else if (count > totalTests[suitName]) {
                        iconSpan.textContent = '⬆️';
                    }

                    if (iconSpan.textContent) el.appendChild(iconSpan);

                    if (count < totalTests[suitName]) {
                        let percentMark = document.createElement('a');
                        percentMark.classList.add('label', 'label--warning', 'percent-mark');
                        percentMark.title = 'Test Pass Rate';
                        percentMark.innerText = `${((count / totalTests[suitName]) * 100).toFixed(1)}%`;
                        insertAfter(percentMark, el);
                    }
                }
            });
        }
    }

    function sortingProjects() {
        let projectsTable = document.querySelector('#projects');

        if (!projectsTable) return;

        let projects = projectsTable.querySelectorAll('.project');

        if (!projects || projects.length === 0) return;

        let sortedProjectsArr = [];
        let projectName, projectNameEnv, projectNameNormalized;

        projects.forEach(project => {
            if (!project) return;

            projectName = project.getAttribute('data-project');

            if (!projectName) return;

            projectNameEnv = projectName.split(':')[0];

            if (projectName.includes('monitoring chats list')) {
                projectNameNormalized = projectNameEnv + '9';
            } else if (projectName.includes('widget:') || projectName.includes('website:')) {
                projectNameNormalized = '1website';
            } else {
                projectNameNormalized = projectNameEnv;
            }

            sortedProjectsArr.push({ name: projectNameNormalized, val: project });
        });

        if (sortedProjectsArr.length > 0) {
            sortedProjectsArr.sort((a, b) => b.name.localeCompare(a.name));

            projectsTable.innerHTML = '';

            sortedProjectsArr.forEach(project => {
                projectsTable.appendChild(project.val);
            });
        }
    }

    function sortingTests() {
        if (window.location.pathname.indexOf('projects/website/suites/website-visual-regression-testing/runs') !== -1) {
            let testsBlockArr = document.querySelectorAll('tr.test');

            if (!testsBlockArr || testsBlockArr.length === 0) return;

            let parentTests = testsBlockArr[0].parentElement;

            if (!parentTests) return;

            let sortedTestsBlockArr = [];

            testsBlockArr.forEach(testsBlock => {
                if (!testsBlock) return;

                const test = testsBlock.querySelector('th a');

                if (!test) return;

                const testName = test.innerHTML.replace(/\s+/g, '-').toLowerCase();
                sortedTestsBlockArr.push({ name: testName, val: testsBlock });
            });

            if (sortedTestsBlockArr.length > 0) {
                sortedTestsBlockArr.sort((a, b) => a.name.localeCompare(b.name));

                parentTests.innerHTML = '';

                sortedTestsBlockArr.forEach(testsBlock => {
                    parentTests.appendChild(testsBlock.val);
                });
            }
        }
    }

    // Baseline highlight
    if ((window.location.pathname.includes('/projects/')) && (window.location.pathname.includes('/suites/')) && (window.location.pathname.indexOf('/runs/') === -1)) {
        let newBaselines = document.querySelectorAll('tr.new-baseline');
        let oldBaselines = document.querySelectorAll('tr.old-baseline');

        if (newBaselines && newBaselines.length > 0) {
            let breadcrumb = document.querySelector('ul.breadcrumb');
            if (breadcrumb) {
                let newButton = document.createElement('button');
                newButton.id = 'show-new-baselines';
                newButton.classList.add('label--all', 'label');
                newButton.innerText = `New baselines: ${newBaselines.length}`;
                breadcrumb.appendChild(newButton);

                newBaselines.forEach(item => {
                    const link = item.querySelector('th > a');
                    if (link) link.classList.add('new-baseline-link');
                });

                newButton.addEventListener('click', function() {
                    oldBaselines.forEach(item => {
                        if (item) item.remove();
                    });

                    const filters = document.querySelector('div.filters');
                    if (filters) {
                        filters.scrollIntoView({ behavior: 'instant', block: 'start', inline: 'start' });
                    }
                });
            }
        }
    }

    // Helper functions
    function addElementButton(parentId, test) {
        if (!parentId || !test) return;

        let newButton = document.createElement('button');
        newButton.id = parentId;
        newButton.classList.add('test-compare-button', 'diffBtn');
        newButton.innerText = 'Compare';
        insertAfter(newButton, test);
    }

    function addModalWindows(parentId, reference, current) {
        if (!parentId || !reference || !current) return;

        let modalWindow = document.createElement('div');
        modalWindow.id = parentId;
        modalWindow.classList.add('modal', 'modal--compare');

        if (window.location.pathname.indexOf('projects/website') !== -1) {
            modalWindow.classList.add('modal--website');
        }

        modalWindow.innerHTML = '<div class="modal-content"><span class="close">&times;</span><div class="compare-viewport"><div class="compare-indicator-gutter" aria-hidden="true"></div><div id="image-compare"><img src="' + reference + '" alt="reference" /><img src="' + current + '" alt="current" /></div></div></div>';
        document.body.appendChild(modalWindow);
    }

    function addElementPTime(parent, text) {
        if (!parent || !text) return;

        const time = text.split(' ');

        if (time.length < 4) return;

        const timeParts = time[3].split(':');

        if (timeParts.length < 2) return;

        let newP = document.createElement('p');
        newP.classList.add('date-time');
        newP.innerHTML = '🕒 ' + text;
        insertAfter(newP, parent);
    }

    const _icvOptions = {
        showLabels: true,
        labelOptions: {
            before: 'Baseline',
            after: 'Comparison',
            onHover: false
        },
        smoothing: false,
        startingPoint: 50,
        fluidMode: true,
        controlColor: '#FF0000',
        controlShadow: false,
        addCircle: false,
        addCircleBlur: false,
    };

    function mountIcvOnElement(element) {
        new ImageCompare(element, _icvOptions).mount();

        const observer = new MutationObserver(function() {
            updateHorizontalLines();
        });
        observer.observe(element, { attributes: true, childList: true, subtree: true });
        element.addEventListener('mousemove', updateHorizontalLines);
        element.addEventListener('click', updateHorizontalLines);
    }

    function setViewers() {
        const viewers = document.querySelectorAll('#image-compare');
        viewers.forEach(element => {
            // Website modals are mounted on-open after images load (see mountWebsiteViewer)
            if (element.closest('.modal--website')) return;
            mountIcvOnElement(element);
        });
    }

    function mountWebsiteViewer(modal) {
        const container = modal.querySelector('#image-compare');
        if (!container || container.dataset.icvMounted) return;
        container.dataset.icvMounted = '1';

        const firstImg = container.querySelector('img');
        if (!firstImg) return;

        function doMount() {
            if (!firstImg.naturalWidth) return;
            const w = container.clientWidth;
            const h = Math.round(w * firstImg.naturalHeight / firstImg.naturalWidth);
            container.style.height = h + 'px';
            mountIcvOnElement(container);
        }

        if (firstImg.complete && firstImg.naturalWidth) {
            doMount();
        } else {
            firstImg.addEventListener('load', doMount, { once: true });
        }
    }

    function updateHorizontalLines() {
        const control = document.querySelector('.icv__control');
        const container = document.querySelector('#image-compare');
        const beforeLabel = document.querySelector('.icv__label-before');
        const afterLabel = document.querySelector('.icv__label-after');

        if (!control || !container || !beforeLabel || !afterLabel) return;

        const controlRect = control.getBoundingClientRect();
        const containerRect = container.getBoundingClientRect();
        const beforeLabelRect = beforeLabel.getBoundingClientRect();
        const afterLabelRect = afterLabel.getBoundingClientRect();

        const controlCenterX = controlRect.left + (controlRect.width / 2);
        const beforeLineWidth = controlCenterX - (beforeLabelRect.right);
        const afterLineWidth = (afterLabelRect.left) - controlCenterX;

        document.documentElement.style.setProperty('--before-line-width', `${Math.max(0, beforeLineWidth)}px`);
        document.documentElement.style.setProperty('--after-line-width', `${Math.max(0, afterLineWidth)}px`);
    }

    let _lightboxNavEnabled = false;
    let _lightboxNavIndex = -1;
    let _lightboxShortcutsEnabled = false;
    let _compareNavHudEl = null;
    let _imageLightboxNavEnabled = false;
    let _imageLightboxNavIndex = -1;
    let _imageLightboxColumnId = null;
    let _imageLightboxModalClass = null;
    let _imageLightboxHudEl = null;

    function getSimpleLightboxImgClass() {
        return window.location.pathname.indexOf('projects/website/suites') !== -1
            ? 'imgModal2'
            : 'imgModal1';
    }

    function getOrCreateSimpleLightboxModal(imgClass) {
        let modal = document.querySelector('div.modal.' + imgClass + ':not(.modal--compare)');
        if (modal) return modal;

        modal = document.createElement('div');
        modal.classList.add('modal', imgClass);
        modal.innerHTML = '<div class="modal-content"><span class="close">&times;</span><img class="lightbox" src=""/></div>';
        document.body.appendChild(modal);
        return modal;
    }

    function getOpenSimpleLightboxModal() {
        return document.querySelector('.modal.imgModal1.modal-show:not(.modal--baseline-lightbox), .modal.imgModal2.modal-show:not(.modal--baseline-lightbox)');
    }

    function findSimpleLightboxLink(cell) {
        if (!cell) return null;
        return cell.querySelector('a.baseline__image, a.test__image, a.diff__image, a[data-href], a[href]');
    }

    function prepareSimpleLightboxLink(link) {
        if (!link) return false;

        const href = link.getAttribute('data-href') || link.getAttribute('href');
        if (!href) return false;

        if (!link.getAttribute('data-href')) {
            link.setAttribute('data-href', href);
        }
        if (link.hasAttribute('href')) {
            link.removeAttribute('href');
        }

        return true;
    }

    function collectSimpleLightboxItems(columnId) {
        const items = [];

        document.querySelectorAll('td[id="' + columnId + '"]').forEach(function(cell) {
            const link = findSimpleLightboxLink(cell);
            if (!prepareSimpleLightboxLink(link)) return;

            items.push({
                link: link,
                row: cell.closest('tr'),
                columnId: columnId,
                href: link.getAttribute('data-href'),
            });
        });

        return items;
    }

    function getCurrentSimpleLightboxItems() {
        if (!_imageLightboxColumnId) return [];
        return collectSimpleLightboxItems(_imageLightboxColumnId);
    }

    function getTestRowName(row) {
        if (!row) return 'Unknown test';
        const nameEl = row.querySelector('.test__name');
        return nameEl ? nameEl.textContent.replace(/\s+/g, ' ').trim() : 'Unknown test';
    }

    function ensureImageLightboxHud() {
        if (_imageLightboxHudEl) return _imageLightboxHudEl;

        const hud = document.createElement('div');
        hud.className = 'image-lightbox-hud';
        hud.hidden = true;
        document.body.appendChild(hud);
        _imageLightboxHudEl = hud;
        return hud;
    }

    function hideImageLightboxHud() {
        if (!_imageLightboxHudEl) return;
        _imageLightboxHudEl.hidden = true;
    }

    function updateImageLightboxHud() {
        const openModal = getOpenSimpleLightboxModal();
        if (!openModal || !_imageLightboxNavEnabled || _imageLightboxNavIndex < 0) {
            hideImageLightboxHud();
            return;
        }

        const items = getCurrentSimpleLightboxItems();
        const item = items[_imageLightboxNavIndex];
        if (!item) {
            hideImageLightboxHud();
            return;
        }

        hideCompareNavHud();

        const hud = ensureImageLightboxHud();
        hud.textContent = (_imageLightboxNavIndex + 1) + '/' + items.length + ' ' + getTestRowName(item.row);
        hud.hidden = false;
    }

    function resetImageLightboxNav() {
        _imageLightboxNavEnabled = false;
        _imageLightboxNavIndex = -1;
        _imageLightboxColumnId = null;
        hideImageLightboxHud();
    }

    function openSimpleLightboxModal(modal, href) {
        if (!modal || !href) return;

        modal.classList.add('modal-show');
        modal.classList.remove('modal-hide');

        const modalImg = modal.querySelector('img.lightbox');
        if (modalImg) {
            modalImg.src = href;
        }
    }

    function bindSimpleLightboxCloseHandlers(modal) {
        const close = modal.querySelector('span.close');
        if (close) {
            close.onclick = function() {
                closeSimpleLightboxModal(modal);
            };
        }

        window.onclick = function(event) {
            if (event.target === modal) {
                closeSimpleLightboxModal(modal);
            }
        };
    }

    function activateSimpleImageLightboxNav(link, columnId) {
        const items = collectSimpleLightboxItems(columnId);
        const idx = items.findIndex(function(item) { return item.link === link; });
        if (idx === -1) return;

        _imageLightboxNavEnabled = true;
        _imageLightboxNavIndex = idx;
        _imageLightboxColumnId = columnId;
        updateImageLightboxHud();
    }

    function goToSimpleLightboxIndex(index) {
        const items = getCurrentSimpleLightboxItems();
        if (!items.length) {
            resetImageLightboxNav();
            return;
        }

        if (index < 0 || index >= items.length) return;

        _imageLightboxNavIndex = index;
        const modal = getOrCreateSimpleLightboxModal(_imageLightboxModalClass || getSimpleLightboxImgClass());
        openSimpleLightboxModal(modal, items[index].href);

        if (items[index].row) {
            items[index].row.scrollIntoView({ behavior: 'instant', block: 'center' });
        }

        updateImageLightboxHud();
    }

    function goSimpleLightboxNext() {
        goToSimpleLightboxIndex(_imageLightboxNavIndex + 1);
    }

    function goSimpleLightboxPrev() {
        goToSimpleLightboxIndex(_imageLightboxNavIndex - 1);
    }

    function closeSimpleLightboxModal(modal) {
        if (!modal) return;
        modal.classList.add('modal-hide');
        modal.classList.remove('modal-show');
        resetImageLightboxNav();
    }

    function closeOpenLightbox(reason) {
        const compareModal = document.querySelector('.modal.modal--compare.modal-show');
        if (compareModal) {
            closeCompareModal(compareModal, reason || 'Escape');
            resetLightboxNav(reason || 'Escape');
            return true;
        }

        const simpleModal = getOpenSimpleLightboxModal();
        if (simpleModal) {
            closeSimpleLightboxModal(simpleModal);
            return true;
        }

        const baselineModal = getOpenBaselineLightboxModal();
        if (baselineModal) {
            closeBaselineLightboxModal(baselineModal);
            return true;
        }

        return false;
    }

    function setupLightboxEscapeClose() {
        document.addEventListener('keydown', function(e) {
            if (e.key !== 'Escape') return;

            const compareOpen = document.querySelector('.modal.modal--compare.modal-show');
            const simpleOpen = getOpenSimpleLightboxModal();
            const baselineOpen = getOpenBaselineLightboxModal();
            if (!compareOpen && !simpleOpen && !baselineOpen) return;

            e.preventDefault();
            closeOpenLightbox('Escape');
        });
    }

    function setupSimpleImageLightboxNav() {
        document.addEventListener('keydown', function(e) {
            const isNextKey = e.key === 'ArrowDown' || e.key === 'ArrowRight';
            const isPrevKey = e.key === 'ArrowUp' || e.key === 'ArrowLeft';
            if (!isNextKey && !isPrevKey) return;
            if (!_imageLightboxNavEnabled) return;

            if (!getOpenSimpleLightboxModal()) {
                resetImageLightboxNav();
                return;
            }

            if (document.querySelector('.modal.modal--compare.modal-show')) return;
            if (_lightboxShortcutsEnabled && _lightboxNavEnabled) return;

            if (e.target.matches('input, textarea, select, [contenteditable="true"]')) return;
            if (e.metaKey || e.ctrlKey || e.altKey) return;

            e.preventDefault();

            if (isNextKey) {
                goSimpleLightboxNext();
            } else {
                goSimpleLightboxPrev();
            }
        });
    }

    // ── Baseline suite lightbox (suite list page only; isolated from run lightboxes) ──
    let _baselineLightboxNavEnabled = false;
    let _baselineLightboxNavIndex = -1;
    let _baselineLightboxHudEl = null;
    let _baselineLightboxCloseBound = false;

    function isSuiteBaselinesPage() {
        const path = window.location.pathname;
        return path.indexOf('/projects/') !== -1
            && path.indexOf('/suites/') !== -1
            && path.indexOf('/runs/') === -1;
    }

    function getOrCreateBaselineLightboxModal() {
        let modal = document.querySelector('div.modal.modal--baseline-lightbox');
        if (modal) return modal;

        modal = document.createElement('div');
        modal.classList.add('modal', 'modal--baseline-lightbox');
        modal.innerHTML = '<div class="modal-content"><span class="close">&times;</span><img class="lightbox" src=""/></div>';
        document.body.appendChild(modal);
        return modal;
    }

    function getOpenBaselineLightboxModal() {
        return document.querySelector('.modal.modal--baseline-lightbox.modal-show');
    }

    function collectBaselineLightboxItems() {
        const items = [];

        document.querySelectorAll('tr.baseline a.baseline__image').forEach(function(link) {
            const href = link.getAttribute('data-href') || link.getAttribute('href');
            if (!href) return;

            if (!link.getAttribute('data-href')) {
                link.setAttribute('data-href', href);
            }
            if (link.hasAttribute('href')) {
                link.removeAttribute('href');
            }

            items.push({
                link: link,
                row: link.closest('tr'),
                href: link.getAttribute('data-href'),
            });
        });

        return items;
    }

    function getBaselineRowName(row) {
        if (!row) return 'Unknown baseline';
        const nameEl = row.querySelector('.baseline__name');
        return nameEl ? nameEl.textContent.replace(/\s+/g, ' ').trim() : 'Unknown baseline';
    }

    function ensureBaselineLightboxHud() {
        if (_baselineLightboxHudEl) return _baselineLightboxHudEl;

        const hud = document.createElement('div');
        hud.className = 'image-lightbox-hud';
        hud.hidden = true;
        document.body.appendChild(hud);
        _baselineLightboxHudEl = hud;
        return hud;
    }

    function hideBaselineLightboxHud() {
        if (!_baselineLightboxHudEl) return;
        _baselineLightboxHudEl.hidden = true;
    }

    function updateBaselineLightboxHud() {
        if (!getOpenBaselineLightboxModal() || !_baselineLightboxNavEnabled || _baselineLightboxNavIndex < 0) {
            hideBaselineLightboxHud();
            return;
        }

        const items = collectBaselineLightboxItems();
        const item = items[_baselineLightboxNavIndex];
        if (!item) {
            hideBaselineLightboxHud();
            return;
        }

        hideCompareNavHud();
        hideImageLightboxHud();

        const hud = ensureBaselineLightboxHud();
        hud.textContent = (_baselineLightboxNavIndex + 1) + '/' + items.length + ' ' + getBaselineRowName(item.row);
        hud.hidden = false;
    }

    function resetBaselineLightboxNav() {
        _baselineLightboxNavEnabled = false;
        _baselineLightboxNavIndex = -1;
        hideBaselineLightboxHud();
    }

    function openBaselineLightboxModal(modal, href) {
        if (!modal || !href) return;

        modal.classList.add('modal-show');
        modal.classList.remove('modal-hide');

        const modalImg = modal.querySelector('img.lightbox');
        if (modalImg) {
            modalImg.src = href;
        }
    }

    function closeBaselineLightboxModal(modal) {
        if (!modal) return;
        modal.classList.add('modal-hide');
        modal.classList.remove('modal-show');
        resetBaselineLightboxNav();
    }

    function bindBaselineLightboxCloseHandlers(modal) {
        if (!modal || _baselineLightboxCloseBound) return;
        _baselineLightboxCloseBound = true;

        const close = modal.querySelector('span.close');
        if (close) {
            close.addEventListener('click', function() {
                closeBaselineLightboxModal(modal);
            });
        }

        modal.addEventListener('click', function(event) {
            if (event.target === modal) {
                closeBaselineLightboxModal(modal);
            }
        });
    }

    function activateBaselineLightboxNav(link) {
        const items = collectBaselineLightboxItems();
        const idx = items.findIndex(function(item) { return item.link === link; });
        if (idx === -1) return;

        _baselineLightboxNavEnabled = true;
        _baselineLightboxNavIndex = idx;
        updateBaselineLightboxHud();
    }

    function goToBaselineLightboxIndex(index) {
        const items = collectBaselineLightboxItems();
        if (!items.length) {
            resetBaselineLightboxNav();
            return;
        }

        if (index < 0 || index >= items.length) return;

        _baselineLightboxNavIndex = index;
        const modal = getOrCreateBaselineLightboxModal();
        openBaselineLightboxModal(modal, items[index].href);

        if (items[index].row) {
            items[index].row.scrollIntoView({ behavior: 'instant', block: 'center' });
        }

        updateBaselineLightboxHud();
    }

    function goBaselineLightboxNext() {
        goToBaselineLightboxIndex(_baselineLightboxNavIndex + 1);
    }

    function goBaselineLightboxPrev() {
        goToBaselineLightboxIndex(_baselineLightboxNavIndex - 1);
    }

    function setupBaselineImageLightbox() {
        if (!isSuiteBaselinesPage()) return;

        const modal = getOrCreateBaselineLightboxModal();
        bindBaselineLightboxCloseHandlers(modal);

        document.querySelectorAll('tr.baseline a.baseline__image').forEach(function(link) {
            if (link.hasAttribute('data-baseline-lightbox-bound')) return;

            const href = link.getAttribute('data-href') || link.getAttribute('href');
            if (!href) return;

            if (!link.getAttribute('data-href')) {
                link.setAttribute('data-href', href);
            }
            if (link.hasAttribute('href')) {
                link.removeAttribute('href');
            }

            link.setAttribute('data-baseline-lightbox-bound', 'true');
            link.addEventListener('click', function(e) {
                e.preventDefault();
                e.stopPropagation();
                activateBaselineLightboxNav(link);
                openBaselineLightboxModal(modal, link.getAttribute('data-href'));
            });
        });
    }

    function setupBaselineImageLightboxNav() {
        document.addEventListener('keydown', function(e) {
            const isNextKey = e.key === 'ArrowDown' || e.key === 'ArrowRight';
            const isPrevKey = e.key === 'ArrowUp' || e.key === 'ArrowLeft';
            if (!isNextKey && !isPrevKey) return;
            if (!_baselineLightboxNavEnabled) return;

            if (!getOpenBaselineLightboxModal()) {
                resetBaselineLightboxNav();
                return;
            }

            if (document.querySelector('.modal.modal--compare.modal-show')) return;
            if (getOpenSimpleLightboxModal()) return;

            if (e.target.matches('input, textarea, select, [contenteditable="true"]')) return;
            if (e.metaKey || e.ctrlKey || e.altKey) return;

            e.preventDefault();

            if (isNextKey) {
                goBaselineLightboxNext();
            } else {
                goBaselineLightboxPrev();
            }
        });
    }

    function collectNavigableCompareRows() {
        const diffedRows = Array.from(document.querySelectorAll('tr.diffed'));
        return diffedRows.filter(function(row) {
            return row.id && getCompareModalByTestId(row.id);
        });
    }

    function ensureCompareNavHud() {
        if (_compareNavHudEl) return _compareNavHudEl;

        const hud = document.createElement('div');
        hud.className = 'compare-nav-hud';
        hud.hidden = true;
        document.body.appendChild(hud);
        _compareNavHudEl = hud;
        return hud;
    }

    function hideCompareNavHud() {
        if (!_compareNavHudEl) return;
        _compareNavHudEl.hidden = true;
    }

    function updateCompareNavHud() {
        const openModal = document.querySelector('.modal.modal--compare.modal-show');
        if (!openModal || !_lightboxNavEnabled || _lightboxNavIndex < 0) {
            hideCompareNavHud();
            return;
        }

        hideImageLightboxHud();

        const rows = collectNavigableCompareRows();
        if (!rows[_lightboxNavIndex]) {
            hideCompareNavHud();
            return;
        }

        const row = rows[_lightboxNavIndex];
        const hud = ensureCompareNavHud();
        hud.textContent = (_lightboxNavIndex + 1) + '/' + rows.length + ' ' + getTestRowName(row);
        hud.hidden = false;
    }

    function lbLog(step, data) {
        if (data !== undefined) {
            console.log('[Spectre5000][LightboxNav] ' + step, data);
        } else {
            console.log('[Spectre5000][LightboxNav] ' + step);
        }
    }

    function getCompareModalByTestId(testId) {
        if (!testId) return null;
        return document.querySelector('div.modal.modal--compare#' + CSS.escape(String(testId)));
    }

    function describeCompareRow(row) {
        if (!row) return null;
        const modal = row.id ? getCompareModalByTestId(row.id) : null;
        return {
            rowId: row.id || null,
            hasModal: !!modal,
            modalIsCompare: !!modal,
            hasBaselineBtn: !!row.querySelector('input.test__set-baseline'),
            testName: (row.querySelector('.test__name') || {}).textContent || null,
        };
    }

    function getNavigableCompareRows() {
        const diffedRows = Array.from(document.querySelectorAll('tr.diffed'));
        const rows = collectNavigableCompareRows();

        lbLog('getNavigableCompareRows', {
            diffedCount: diffedRows.length,
            navigableCount: rows.length,
            diffedWithoutModal: diffedRows.filter(function(row) {
                return !row.id || !getCompareModalByTestId(row.id);
            }).length,
            diffedWithNonCompareModal: 0,
            rows: rows.map(describeCompareRow),
        });

        return rows;
    }

    function resetLightboxNav(reason) {
        lbLog('resetLightboxNav', {
            reason: reason || 'unknown',
            wasEnabled: _lightboxNavEnabled,
            wasIndex: _lightboxNavIndex,
        });
        _lightboxNavEnabled = false;
        _lightboxNavIndex = -1;
        hideCompareNavHud();
    }

    function closeCompareModal(modal, reason) {
        if (!modal) {
            lbLog('closeCompareModal skipped — no modal', { reason: reason || 'unknown' });
            return;
        }
        lbLog('closeCompareModal', {
            reason: reason || 'unknown',
            modalId: modal.id || null,
            hadModalShow: modal.classList.contains('modal-show'),
        });
        modal.classList.add('modal-hide');
        modal.classList.remove('modal-show');
    }

    function bindCompareModalCloseHandlers(modal) {
        const close = modal.querySelector('span.close');
        if (close) {
            close.onclick = function() {
                closeCompareModal(modal, 'close button click');
                resetLightboxNav('close button click');
            };
        } else {
            lbLog('bindCompareModalCloseHandlers — close button not found', {
                modalId: modal.id || null,
            });
        }

        window.onclick = function(event) {
            if (event.target === modal) {
                closeCompareModal(modal, 'backdrop click');
                resetLightboxNav('backdrop click');
            }
        };
    }

    function openCompareModal(modal, reason) {
        if (!modal) {
            lbLog('openCompareModal skipped — no modal', { reason: reason || 'unknown' });
            return;
        }

        lbLog('openCompareModal', {
            reason: reason || 'unknown',
            modalId: modal.id || null,
            isWebsite: modal.classList.contains('modal--website'),
        });

        document.querySelectorAll('.modal.modal--compare.modal-show').forEach(function(m) {
            closeCompareModal(m, 'switching to another compare modal');
        });

        modal.classList.add('modal-show');
        modal.classList.remove('modal-hide');

        if (modal.classList.contains('modal--website')) {
            mountWebsiteViewer(modal);
        }

        bindCompareModalCloseHandlers(modal);
        maybeAutoApplyDiffHighlights(modal);
    }

    function activateLightboxNav(testId, source) {
        const rows = getNavigableCompareRows();
        const idx = rows.findIndex(function(row) { return row.id === testId; });
        lbLog('activateLightboxNav', {
            source: source || 'unknown',
            testId: testId,
            idx: idx,
            enabled: idx !== -1,
            row: idx !== -1 ? describeCompareRow(rows[idx]) : null,
        });
        if (idx === -1) return;
        _lightboxNavEnabled = true;
        _lightboxNavIndex = idx;
        updateCompareNavHud();
    }

    function setListener() {
        const btn = document.querySelectorAll('button.diffBtn');
        lbLog('setListener init', {
            diffBtnCount: btn.length,
            buttons: Array.from(btn).map(function(element) {
                return {
                    id: element.id || null,
                    text: (element.textContent || '').trim(),
                    className: element.className,
                };
            }),
        });

        btn.forEach(element => {
            element.addEventListener('click', function(event) {
                const triggerId = event.currentTarget.id || event.target.id || null;
                const modal = getCompareModalByTestId(triggerId);

                lbLog('Compare button click', {
                    triggerId: triggerId,
                    targetTag: event.target && event.target.tagName,
                    targetId: event.target && event.target.id,
                    currentTargetId: event.currentTarget && event.currentTarget.id,
                    modalFound: !!modal,
                    modalIsCompare: !!modal,
                    modalClasses: modal ? modal.className : null,
                    wrongElementByGetElementById: triggerId
                        ? (document.getElementById(triggerId) || {}).tagName || null
                        : null,
                });

                if (!modal) return;

                openCompareModal(modal, 'Compare button click');
                activateLightboxNav(triggerId, 'Compare button click');
            });
        });
    }

    function setupLightboxKeyboardNav() {
        lbLog('setupLightboxKeyboardNav init', {
            pathname: window.location.pathname,
            compareModalCount: document.querySelectorAll('.modal.modal--compare').length,
            openCompareModalCount: document.querySelectorAll('.modal.modal--compare.modal-show').length,
        });

        function goToIndex(index, source) {
            const rows = getNavigableCompareRows();
            lbLog('goToIndex', {
                source: source || 'unknown',
                requestedIndex: index,
                currentIndex: _lightboxNavIndex,
                rowCount: rows.length,
            });

            if (!rows.length) {
                closeCompareModal(document.querySelector('.modal.modal--compare.modal-show'), 'goToIndex — no rows');
                resetLightboxNav('goToIndex — no rows');
                return;
            }

            if (index >= rows.length) {
                closeCompareModal(document.querySelector('.modal.modal--compare.modal-show'), 'goToIndex — past last');
                resetLightboxNav('goToIndex — past last');
                return;
            }

            if (index < 0) {
                index = 0;
            }

            _lightboxNavIndex = index;
            const targetRow = rows[index];
            const targetModal = getCompareModalByTestId(targetRow.id);
            lbLog('goToIndex opening', {
                source: source || 'unknown',
                index: index,
                row: describeCompareRow(targetRow),
                modalFound: !!targetModal,
            });
            openCompareModal(targetModal, source || 'goToIndex');
            targetRow.scrollIntoView({ behavior: 'instant', block: 'center' });
            updateCompareNavHud();
        }

        function goNext(source) {
            goToIndex(_lightboxNavIndex + 1, source || 'goNext');
        }

        function goPrev(source) {
            lbLog('goPrev', {
                source: source || 'unknown',
                currentIndex: _lightboxNavIndex,
            });
            if (_lightboxNavIndex > 0) {
                goToIndex(_lightboxNavIndex - 1, source || 'goPrev');
            } else {
                lbLog('goPrev skipped — already at first item');
            }
        }

        function acceptBaselineAndNext(source) {
            const rows = getNavigableCompareRows();
            const row = rows[_lightboxNavIndex];
            const baselineBtn = row ? row.querySelector('input.test__set-baseline') : null;
            lbLog('acceptBaselineAndNext', {
                source: source || 'unknown',
                currentIndex: _lightboxNavIndex,
                row: describeCompareRow(row),
                baselineBtnFound: !!baselineBtn,
                baselineBtnDisabled: baselineBtn ? baselineBtn.disabled : null,
            });
            if (baselineBtn) {
                baselineBtn.click();
            }
            goNext(source || 'acceptBaselineAndNext');
        }

        document.addEventListener('keydown', function(e) {
            if (e.key === 'y' || e.key === 'Y') {
                if (!_lightboxShortcutsEnabled) return;
                if (e.target.matches('input, textarea, select, [contenteditable="true"]')) return;
                if (e.metaKey || e.ctrlKey || e.altKey) return;
                e.preventDefault();
                toggleAutoDiffHighlights();
                return;
            }

            const openModal = document.querySelector('.modal.modal--compare.modal-show');
            const isNavKey = ['ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight', 'a', 'A', 's', 'S'].indexOf(e.key) !== -1;

            if (!isNavKey) return;

            if (!_lightboxShortcutsEnabled) {
                lbLog('keydown ignored — shortcuts toggle off', {
                    key: e.key,
                    openCompareModal: !!openModal,
                });
                return;
            }

            if (!_lightboxNavEnabled) {
                lbLog('keydown ignored — nav not enabled', {
                    key: e.key,
                    openCompareModal: !!openModal,
                    openModalId: openModal ? openModal.id : null,
                });
                return;
            }

            if (!openModal) {
                lbLog('keydown ignored — no open compare modal, resetting nav', { key: e.key });
                resetLightboxNav('keydown — no open compare modal');
                return;
            }

            if (e.target.matches('input, textarea, select, [contenteditable="true"]')) {
                lbLog('keydown ignored — focus in editable field', {
                    key: e.key,
                    targetTag: e.target.tagName,
                    targetType: e.target.type || null,
                });
                return;
            }

            if (e.metaKey || e.ctrlKey || e.altKey) {
                lbLog('keydown ignored — modifier pressed', {
                    key: e.key,
                    metaKey: e.metaKey,
                    ctrlKey: e.ctrlKey,
                    altKey: e.altKey,
                });
                return;
            }

            lbLog('keydown accepted', {
                key: e.key,
                currentIndex: _lightboxNavIndex,
                openModalId: openModal.id,
            });

            switch (e.key) {
                case 'ArrowDown':
                case 'ArrowRight':
                    e.preventDefault();
                    goNext(e.key);
                    break;
                case 'ArrowUp':
                case 'ArrowLeft':
                    e.preventDefault();
                    goPrev(e.key);
                    break;
                case 'a':
                case 'A':
                    e.preventDefault();
                    acceptBaselineAndNext('A');
                    break;
                case 's':
                case 'S':
                    e.preventDefault();
                    goNext('S');
                    break;
            }
        });
    }

    function insertAfter(newNode, existingNode) {
        if (!newNode || !existingNode || !existingNode.parentNode) return;
        existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);
    }

    // ── Diff Highlight: press H while Compare lightbox is open ──────────────

    const _diffCache   = new Map();   // testId -> { circleRects, indicatorRects, imgW, imgH }
    const _diffLoading = new Set();   // testIds currently being fetched
    let _autoDiffHighlightsEnabled = false;
    let _autoDiffIndicatorEl = null;

    // Pixel-analysis worker (runs off main thread so the slider stays responsive)
    const _diffWorkerUrl = URL.createObjectURL(new Blob([`
        function computeRects(data, width, height, blockSize) {
            var cols = Math.ceil(width / blockSize);
            var rows = Math.ceil(height / blockSize);
            var grid = new Uint8Array(cols * rows);

            for (var y = 0; y < height; y++) {
                for (var x = 0; x < width; x++) {
                    var i = (y * width + x) * 4;
                    var r = data[i], g = data[i+1], b = data[i+2], a = data[i+3];
                    if (a < 128) continue;
                    var maxC = r > g ? (r > b ? r : b) : (g > b ? g : b);
                    var minC = r < g ? (r < b ? r : b) : (g < b ? g : b);
                    if (maxC > 40 && (maxC - minC) / maxC > 0.25) {
                        grid[Math.floor(y / blockSize) * cols + Math.floor(x / blockSize)] = 1;
                    }
                }
            }

            var visited = new Uint8Array(cols * rows);
            var rects = [];
            for (var i = 0; i < grid.length; i++) {
                if (!grid[i] || visited[i]) continue;
                var queue = [i];
                visited[i] = 1;
                var minBx = Infinity, maxBx = -Infinity, minBy = Infinity, maxBy = -Infinity;
                while (queue.length) {
                    var idx = queue.shift();
                    var bx = idx % cols;
                    var by = Math.floor(idx / cols);
                    if (bx < minBx) minBx = bx;
                    if (bx > maxBx) maxBx = bx;
                    if (by < minBy) minBy = by;
                    if (by > maxBy) maxBy = by;
                    for (var dy = -1; dy <= 1; dy++) {
                        for (var dx = -1; dx <= 1; dx++) {
                            if (dx === 0 && dy === 0) continue;
                            var nx = bx + dx, ny = by + dy;
                            if (nx < 0 || nx >= cols || ny < 0 || ny >= rows) continue;
                            var ni = ny * cols + nx;
                            if (!grid[ni] || visited[ni]) continue;
                            visited[ni] = 1;
                            queue.push(ni);
                        }
                    }
                }
                rects.push({
                    x: minBx * blockSize, y: minBy * blockSize,
                    width: (maxBx - minBx + 1) * blockSize,
                    height: (maxBy - minBy + 1) * blockSize,
                });
            }
            return rects;
        }

        self.onmessage = function(e) {
            var buffer = e.data.buffer, width = e.data.width, height = e.data.height;
            var data = new Uint8ClampedArray(buffer);
            self.postMessage({
                circleRects: computeRects(data, width, height, 24),
                indicatorRects: computeRects(data, width, height, 5),
            });
        };
    `], { type: 'application/javascript' }));

    function isWebsiteCompareModal(modal) {
        return modal.classList.contains('modal--website');
    }

    function getImageCompareLayout(container, imgW, imgH, modal) {
        const cRect = container.getBoundingClientRect();
        if (modal && isWebsiteCompareModal(modal)) {
            const scale = cRect.width / imgW;
            return {
                scale: scale,
                offsetX: 0,
                offsetY: 0,
                containerWidth: cRect.width,
                containerHeight: cRect.height,
            };
        }
        const scale = Math.min(cRect.width / imgW, cRect.height / imgH);
        return {
            scale: scale,
            offsetX: (cRect.width - imgW * scale) / 2,
            offsetY: (cRect.height - imgH * scale) / 2,
            containerWidth: cRect.width,
            containerHeight: cRect.height,
        };
    }

    function getWebsiteIndicatorScrollOffset(modal, container, fullHeight, trackHeight) {
        const modalRect = modal.getBoundingClientRect();
        const containerRect = container.getBoundingClientRect();
        const offset = Math.max(0, modalRect.top - containerRect.top);
        const maxOffset = Math.max(0, fullHeight - trackHeight);
        return Math.min(offset, maxOffset);
    }

    function ensureCompareContainerPosition(container) {
        if (container.style.position !== 'relative') {
            container.style.position = 'relative';
        }
    }

    function removeDiffCircles(modal) {
        const existing = modal.querySelector('.diff-highlight-overlay');
        if (existing) {
            existing.remove();
        }
    }

    function getCompareIndicatorGutter(modal) {
        return modal.querySelector('.compare-indicator-gutter');
    }

    function removeDiffIndicator(modal) {
        const gutter = getCompareIndicatorGutter(modal);
        if (!gutter) return;
        const bar = gutter.querySelector('.diff-indicator-bar');
        if (!bar) return;
        if (bar._resizeObserver) {
            bar._resizeObserver.disconnect();
        }
        if (bar._scrollRoot && bar._scrollListener) {
            bar._scrollRoot.removeEventListener('scroll', bar._scrollListener);
            window.removeEventListener('scroll', bar._scrollListener);
        }
        bar.remove();
    }

    function renderDiffIndicator(modal, rects, imgW, imgH) {
        const container = modal.querySelector('#image-compare');
        const gutter = getCompareIndicatorGutter(modal);
        if (!container || !gutter) return;

        let bar = gutter.querySelector('.diff-indicator-bar');
        if (!bar) {
            bar = document.createElement('div');
            bar.classList.add('diff-indicator-bar');

            const track = document.createElement('div');
            track.classList.add('diff-indicator-track');

            const inner = document.createElement('div');
            inner.classList.add('diff-indicator-inner');

            const markers = document.createElement('div');
            markers.classList.add('diff-indicator-markers');

            inner.appendChild(markers);
            track.appendChild(inner);
            bar.appendChild(track);
            gutter.appendChild(bar);

            bar._markersEl = markers;
            bar._innerEl = inner;
            bar._trackEl = track;

            const updateLayout = function() {
                const layout = getImageCompareLayout(container, imgW, imgH, modal);
                const fullHeight = imgH * layout.scale;
                bar._innerEl.style.height = fullHeight + 'px';

                if (isWebsiteCompareModal(modal)) {
                    const trackHeight = bar._trackEl.clientHeight || gutter.clientHeight;
                    const scrollOffset = getWebsiteIndicatorScrollOffset(
                        modal, container, fullHeight, trackHeight
                    );
                    bar._innerEl.style.transform = 'translateY(' + (-scrollOffset) + 'px)';
                } else {
                    bar._innerEl.style.transform = 'translateY(' + layout.offsetY + 'px)';
                }

                bar._markersEl.innerHTML = '';
                rects.forEach(function(rect) {
                    const marker = document.createElement('div');
                    marker.classList.add('diff-indicator-marker');
                    marker.style.top = (rect.y * layout.scale) + 'px';
                    marker.style.height = Math.max(rect.height * layout.scale, 1) + 'px';
                    bar._markersEl.appendChild(marker);
                });
            };

            updateLayout();
            bar._resizeObserver = new ResizeObserver(updateLayout);
            bar._resizeObserver.observe(container);

            if (isWebsiteCompareModal(modal)) {
                bar._scrollRoot = modal;
                bar._scrollListener = updateLayout;
                modal.addEventListener('scroll', updateLayout, { passive: true });
                window.addEventListener('scroll', updateLayout, { passive: true });
            }
        }
    }

    function showDiffHighlights(modal, cached) {
        renderDiffIndicator(modal, cached.indicatorRects, cached.imgW, cached.imgH);
        renderDiffCircles(modal, cached.circleRects, cached.imgW, cached.imgH);
    }

    function getDiffUrlForCompareModal(modal) {
        const testId = modal && modal.id;
        if (!testId) return null;

        const testRow = document.querySelector('tr[id="' + testId + '"]');
        if (!testRow) return null;

        const diffTd = testRow.querySelector('[id="image-diff"]');
        if (!diffTd) return null;

        const diffLink = diffTd.querySelector('a');
        if (!diffLink) return null;

        return diffLink.getAttribute('data-href') || diffLink.href || null;
    }

    function requestDiffHighlightsForModal(modal) {
        if (!modal || !modal.classList.contains('modal--compare')) return;

        const testId = modal.id;
        if (!testId) return;

        if (_diffCache.has(testId)) {
            showDiffHighlights(modal, _diffCache.get(testId));
            return;
        }

        if (_diffLoading.has(testId)) return;

        const diffUrl = getDiffUrlForCompareModal(modal);
        if (!diffUrl) return;

        _diffLoading.add(testId);
        loadAndAnalyzeDiffImage(diffUrl, function(circleRects, indicatorRects, imgW, imgH) {
            _diffLoading.delete(testId);

            const cached = {
                circleRects: circleRects,
                indicatorRects: indicatorRects,
                imgW: imgW,
                imgH: imgH,
            };
            _diffCache.set(testId, cached);
            watchModalClose(modal, testId);

            if (modal.classList.contains('modal-show')) {
                showDiffHighlights(modal, cached);
            }
        });
    }

    function clearDiffHighlightsFromModal(modal) {
        if (!modal) return;
        removeDiffCircles(modal);
        removeDiffIndicator(modal);
    }

    function ensureAutoDiffIndicator() {
        if (_autoDiffIndicatorEl) return _autoDiffIndicatorEl;

        const indicator = document.createElement('div');
        indicator.className = 'auto-diff-indicator';
        indicator.textContent = 'Y · DIFF';
        indicator.hidden = true;
        document.body.appendChild(indicator);
        _autoDiffIndicatorEl = indicator;
        return indicator;
    }

    function updateAutoDiffIndicator() {
        const indicator = ensureAutoDiffIndicator();
        indicator.hidden = !_autoDiffHighlightsEnabled;
    }

    function setAutoDiffHighlightsEnabled(enabled) {
        _autoDiffHighlightsEnabled = enabled;
        updateAutoDiffIndicator();

        const modal = document.querySelector('.modal.modal--compare.modal-show');
        if (enabled && modal) {
            maybeAutoApplyDiffHighlights(modal);
        } else if (!enabled && modal) {
            clearDiffHighlightsFromModal(modal);
        }
    }

    function toggleAutoDiffHighlights() {
        setAutoDiffHighlightsEnabled(!_autoDiffHighlightsEnabled);
    }

    function maybeAutoApplyDiffHighlights(modal) {
        if (!_autoDiffHighlightsEnabled || !modal) return;

        if (modal.classList.contains('modal--website')) {
            setTimeout(function() {
                if (modal.classList.contains('modal-show')) {
                    requestDiffHighlightsForModal(modal);
                }
            }, 200);
            return;
        }

        requestDiffHighlightsForModal(modal);
    }

    function setupDiffHighlighter() {
        document.addEventListener('keydown', function(e) {
            if (e.key !== 'h' && e.key !== 'H') return;

            const modal = document.querySelector('.modal.modal--compare.modal-show');
            if (!modal) return;

            if (modal.querySelector('.diff-highlight-overlay')) {
                removeDiffCircles(modal);
                return;
            }

            requestDiffHighlightsForModal(modal);
        });
    }

    function watchModalClose(modal, testId) {
        const observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                if (mutation.attributeName === 'class' && !modal.classList.contains('modal-show')) {
                    _diffCache.delete(testId);
                    removeDiffCircles(modal);
                    removeDiffIndicator(modal);
                    observer.disconnect();
                    console.log('[Spectre5000] Cache cleared for ' + testId);
                }
            });
        });
        observer.observe(modal, { attributes: true });
    }

    function loadAndAnalyzeDiffImage(url, callback) {
        const img = new Image();
        img.crossOrigin = 'anonymous';
        img.onload = function() {
            const canvas = document.createElement('canvas');
            canvas.width = img.naturalWidth;
            canvas.height = img.naturalHeight;
            const ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0);

            let imageData;
            try {
                imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            } catch (ex) {
                console.warn('[Spectre5000] Cannot read diff pixels (CORS):', ex);
                return;
            }

            const worker = new Worker(_diffWorkerUrl);
            const buffer = imageData.data.buffer;
            worker.postMessage(
                { buffer: buffer, width: canvas.width, height: canvas.height },
                [buffer]
            );
            worker.onmessage = function(e) {
                worker.terminate();
                callback(
                    e.data.circleRects,
                    e.data.indicatorRects,
                    canvas.width,
                    canvas.height
                );
            };
            worker.onerror = function(err) {
                worker.terminate();
                console.warn('[Spectre5000] Worker error:', err);
            };
        };
        img.onerror = function() {
            console.warn('[Spectre5000] Could not load diff image:', url);
        };
        img.src = url;
    }

    function renderDiffCircles(modal, rects, imgW, imgH) {
        const container = modal.querySelector('#image-compare');
        if (!container) return;

        removeDiffCircles(modal);
        ensureCompareContainerPosition(container);

        const layout = getImageCompareLayout(container, imgW, imgH, modal);
        const scale = layout.scale;
        const offsetX = layout.offsetX;
        const offsetY = layout.offsetY;
        const cRect = container.getBoundingClientRect();

        const svgNS = 'http://www.w3.org/2000/svg';
        const svg = document.createElementNS(svgNS, 'svg');
        svg.classList.add('diff-highlight-overlay');
        svg.setAttribute('width', cRect.width);
        svg.setAttribute('height', cRect.height);
        svg.style.cssText = 'position:absolute;top:0;left:0;pointer-events:none;z-index:9999;overflow:visible;';

        const minRadius = 30;
        const finalCircleScale = 0.90;

        rects.forEach(function(rect) {
            const cx = offsetX + (rect.x + rect.width / 2) * scale;
            const cy = offsetY + (rect.y + rect.height / 2) * scale;
            const r = Math.max(Math.max(rect.width, rect.height) / 2 * scale, minRadius) * finalCircleScale;

            const circle = document.createElementNS(svgNS, 'circle');
            circle.setAttribute('cx', cx);
            circle.setAttribute('cy', cy);
            circle.setAttribute('r', r);
            circle.setAttribute('fill', 'none');
            circle.setAttribute('stroke', '#ff2255');
            circle.setAttribute('stroke-width', '2.5');
            svg.appendChild(circle);
        });

        container.appendChild(svg);
    }

    // ────────────────────────────────────────────────────────────────────────


    function addDownloadBlock(options) {
        options = options || {};

        let downloadBlock = document.createElement('div');
        downloadBlock.id = 'download-block';
        downloadBlock.classList.add('container');

        let downloadButton = document.createElement('button');
        downloadButton.id = 'download-images';
        downloadButton.classList.add('download-button');
        downloadButton.innerHTML = 'Download images';
        downloadBlock.appendChild(downloadButton);

        let progressBlock = document.createElement('div');
        progressBlock.id = 'progress_bar';
        progressBlock.classList.add('progress', 'hide');
        progressBlock.innerHTML = '<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>';
        downloadBlock.appendChild(progressBlock);

        let progressStatus = document.createElement('p');
        progressStatus.id = 'result';
        progressStatus.classList.add('hide');
        progressStatus.innerHTML = '';
        downloadBlock.appendChild(progressStatus);

        let footer = document.createElement('p');
        footer.innerHTML = options.footerText || 'All images from the current run will be archived';
        downloadBlock.appendChild(footer);

        let versionInfo = document.createElement('p');
        versionInfo.classList.add('version');
        versionInfo.innerHTML = 'Spectre 5000    v.17.050';
        downloadBlock.appendChild(versionInfo);

        document.body.appendChild(downloadBlock);
    }

    function resetMessage() {
        $('#result')
            .removeClass()
            .text('');
    }

    function showMessage(text) {
        resetMessage();
        $('#result')
            .addClass('alert alert-success')
            .text(text);
    }

    function showError(text) {
        resetMessage();
        $('#result')
            .addClass('alert alert-danger')
            .text(text);
    }

    function updatePercent(percent) {
        $('#progress_bar').removeClass('hide')
            .find('.progress-bar')
            .attr('aria-valuenow', percent)
            .css({
            width: percent + '%'
        });
    }

    const Promise = window.Promise || JSZip.external.Promise;

    function urlToPromise(url) {
        return new Promise(function(resolve, reject) {
            JSZipUtils.getBinaryContent(url, function(err, data) {
                if (err) {
                    reject(err);
                } else {
                    resolve(data);
                }
            });
        });
    }


    // Initialize all functions
    addDifferencesMarks();
    footerAndHeader();
    addVisualComparisonButtons();
    improveDateTime();
    lowDiffFilter();
    totalTestCount();
    sortingProjects();
    sortingTests();
    envStyle();
    productStyle();
    setupSimpleImageLightboxes();
    setupBaselineImageLightbox();
    setupBaselineImageDownload();
    addProductTabs();
    highlightProjectAge();
    addRowDividers();
    adjustColumnWidths();
    hideProjectsHeader();
    combineFilterElements();
    setupBaselineButtons();

    addLowDiffButtons();
    initMassBaselineEditing();
    setupDiffHighlighter();
    setupLightboxKeyboardNav();
    setupSimpleImageLightboxNav();
    setupBaselineImageLightboxNav();
    setupLightboxEscapeClose();

    setTimeout(() => {
        addLowDiffButtons();
    }, 2000);

})()