@zeesoft/i18n-verify 3.4.1 → 3.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/executor.mjs +1535 -1144
  2. package/package.json +1 -1
package/dist/executor.mjs CHANGED
@@ -459,1088 +459,1369 @@ class BaseReport {
459
459
  }
460
460
  }
461
461
  function getBodyData() {
462
- return `<header><div class="logo">zAutomate.AI</div><div class="report-timestamp"><span class="info"></span></div></header>
463
- <main>
464
- <div class="sidebar">
465
- <ul class="menu" id="menu">
466
- <li class="menu-item" data-page="overview">
467
- <a href="#">Overview</a>
468
- </li>
469
- <li class="menu-item" data-page="log">
470
- <a href="#">View Log</a>
471
- </li>
472
- <li class="menu-item has-submenu" data-page="insights">
473
- <a href="#" data-page="insights">Insights</a>
474
- <ul class="submenu"></ul>
475
- </li>
476
- </ul>
477
- <div class="footer"></div>
478
- </div>
479
- <div class="content-wrapper">
480
- <div class="container">
481
- <div id="overview" class="content">
482
- <div class="common-info card">
483
- <span class="title"></span>
484
- <p class="info"></p>
485
- <div class="section"></div>
486
- </div>
487
- <div class="overall-quality card">
488
- <span class="title">Overall I18n Coverage</span>
489
- <div class="section">
490
- <div class="block">
491
- <article>
492
- <p class="desc">
493
- zI18n-Verify report provides a comprehensive information
494
- about the I18n and L10n quailty of your application.
495
- </p>
496
- <ul class="items">
497
- <li>
498
- <h4>Reviewed:</h4>
499
- <p class="detail">
500
- Total strings which are captured and processed by
501
- zI18n-Verify.
502
- </p>
503
- </li>
504
- <li>
505
- <h4>Internationlized:</h4>
506
- <p class="detail">
507
- Different types of value like string, number, date-time
508
- which are properly Internationalized.
509
- </p>
510
- </li>
511
- <li>
512
- <h4>Not Internationalized:</h4>
513
- <p class="detail">
514
- Values which are not Internationalized. Also includes
515
- Partially Localized strings and Encoding Issues.
516
- </p>
517
- </li>
518
- <li>
519
- <h4>Skipped:</h4>
520
- <p class="detail">
521
- Values which are skipped from processing because they
522
- are listed in DNT / Ignored lists or contains Auto
523
- Ignored pattern / User input pattern.
524
- </p>
525
- </li>
526
- </ul>
527
- </article>
528
- </div>
529
- <div class="block">
530
- <div class="graph"></div>
531
- </div>
532
- </div>
533
- </div>
534
- <div class="string-quality card">
535
- <span class="title">String Coverage</span>
536
- <div class="graph"></div>
537
- </div>
538
- <div class="skipped-items card">
539
- <span class="title">Skipped Items</span>
540
- <div class="graph"></div>
541
- </div>
542
- <div class="number-quality card">
543
- <span class="title">Number Coverage</span>
544
- <div class="graph"></div>
545
- </div>
546
- <div class="datetime-quality card">
547
- <span class="title">DateTime Coverage</span>
548
- <div class="graph"></div>
549
- </div>
550
- </div>
551
- <div id="page" class="content">
552
- <span class="title">Pages</span>
553
- <div class="section">
554
- <div class="desc"></div>
555
- </div>
556
- </div>
557
- <div id="log" class="content">
558
- <span class="title">Runtime log</span>
559
- <div class="log-content"><pre></pre></div>
560
- </div>
561
- <div id="insights" class="content">
562
- <div class="cards">
563
- <span class="title">Locale Quality</span>
564
- <div class="holder"></div>
565
- </div>
566
- </div>
567
- <div id="locale" class="content">
568
- <span class="title">Locale Quality</span>
569
- <div class="coverage-info">
570
- <table class="row-border hover order-column stripe"></table>
571
- </div>
572
- <div id="imageViewer" class="image-viewer">
573
- <span class="close-button" onclick="closeImageViewer()" title="close"
574
- >&times;</span
575
- >
576
- <div class="image-container">
577
- <img id="imageView" src="" alt="Image" />
578
- </div>
579
- </div>
580
- </div>
581
- </div>
582
- </div>
583
- </main>`;
462
+ return '<header class="report-header">\n <div class="header-left">\n <div class="brand-badge">\n <span class="brand-text">zAutomate<span class="brand-ai">.AI</span></span>\n </div>\n <div class="header-divider"></div>\n <div class="product-badge" id="productBadge" title="Product Name">\n <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m7.5 4.27 9 5.15"/><path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"/><path d="m3.3 7 8.7 5 8.7-5"/><path d="M12 22V12"/></svg>\n <span class="product-name" id="productName">Product</span>\n </div>\n <div class="mode-pill mode-sanity" id="modePill">\n <span class="mode-dot"></span>\n <span class="mode-label" id="modeLabel">Quick Sanity</span>\n </div>\n <div class="status-pill status-passed" id="statusPill">\n <span class="status-icon"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span>\n <span class="status-label" id="statusLabel">Passed</span>\n </div>\n <div class="timestamp-badge">\n <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>\n <span class="info" id="reportTimestamp">--</span>\n </div>\n </div>\n <div class="nav-tabs-wrapper">\n <nav class="tabs-list" id="menu">\n <button type="button" class="tab-item selected" data-page="overview">\n <svg class="tab-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect width="7" height="9" x="3" y="3" rx="1"/><rect width="7" height="5" x="14" y="3" rx="1"/><rect width="7" height="9" x="14" y="12" rx="1"/><rect width="7" height="5" x="3" y="16" rx="1"/></svg>\n <span>Overview</span>\n </button>\n <button type="button" class="tab-item" data-page="log">\n <svg class="tab-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="4 17 10 11 4 5"/><line x1="12" x2="20" y1="19" y2="19"/></svg>\n <span>View Log</span>\n </button>\n <div class="tab-dropdown" id="insightsTabDropdown">\n <button type="button" class="tab-item has-submenu" data-page="insights">\n <svg class="tab-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m22 7-8.5 8.5-5-5L2 17"/><polyline points="16 7 22 7 22 13"/></svg>\n <span>Insights</span>\n <svg class="tab-chevron" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m6 9 6 6 6-6"/></svg>\n </button>\n <ul class="submenu"></ul>\n </div>\n </nav>\n </div>\n </header>\n <main class="report-main">\n <div class="content-wrapper">\n <div class="container">\n <div id="overview" class="content active">\n <div class="common-info card">\n <span class="title"></span>\n <p class="info"></p>\n <div class="section"></div>\n </div>\n <div class="overall-quality card">\n <span class="title">Overall I18n Coverage</span>\n <div class="section">\n <div class="block">\n <article>\n <p class="desc">\n zI18n-Verify report provides a comprehensive information\n about the I18n and L10n quality of your application.\n </p>\n <ul class="items">\n <li>\n <h4>Reviewed:</h4>\n <p class="detail">Total strings which are captured and processed by zI18n-Verify.</p>\n </li>\n <li>\n <h4>Internationalized:</h4>\n <p class="detail">Different types of value like string, number, date-time which are properly Internationalized.</p>\n </li>\n <li>\n <h4>Not Internationalized:</h4>\n <p class="detail">Values which are not Internationalized. Also includes Partially Localized strings and Encoding Issues.</p>\n </li>\n <li>\n <h4>Skipped:</h4>\n <p class="detail">Values which are skipped from processing because they are listed in DNT / Ignored lists or contains Auto Ignored pattern / User input pattern.</p>\n </li>\n </ul>\n </article>\n </div>\n <div class="block">\n <div class="graph"></div>\n </div>\n </div>\n </div>\n <div class="string-quality card">\n <span class="title">String Coverage</span>\n <div class="graph"></div>\n </div>\n <div class="skipped-items card">\n <span class="title">Skipped Items</span>\n <div class="graph"></div>\n </div>\n <div class="number-quality card">\n <span class="title">Number Coverage</span>\n <div class="graph"></div>\n </div>\n <div class="datetime-quality card">\n <span class="title">DateTime Coverage</span>\n <div class="graph"></div>\n </div>\n </div>\n <div id="page" class="content">\n <span class="title">Pages</span>\n <div class="section">\n <div class="desc"></div>\n </div>\n </div>\n <div id="log" class="content">\n <div class="terminal-container">\n <div class="terminal-header">\n <div class="terminal-dots">\n <span class="terminal-dot dot-close"></span>\n <span class="terminal-dot dot-min"></span>\n <span class="terminal-dot dot-max"></span>\n </div>\n <div class="terminal-title">\n <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="4 17 10 11 4 5"/><line x1="12" x2="20" y1="19" y2="19"/></svg>\n <span>Runtime Automation Execution Log</span>\n </div>\n <div class="terminal-actions">\n <input type="text" id="logSearchInput" class="terminal-search" placeholder="Filter logs..." />\n <button class="terminal-copy-btn" id="copyLogBtn" type="button" title="Copy Log">\n <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>\n <span>Copy</span>\n </button>\n </div>\n </div>\n <div class="log-content"><pre id="logPre"></pre></div>\n </div>\n </div>\n <div id="insights" class="content">\n <div class="cards">\n <span class="title">Locale Quality</span>\n <div class="holder"></div>\n </div>\n </div>\n <div id="locale" class="content">\n <div class="locale-header-bar">\n <button class="back-to-insights-btn" id="backToInsightsBtn" type="button">\n <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg>\n <span>Back to Insights</span>\n </button>\n <span class="title">Locale Quality Details</span>\n </div>\n <div class="coverage-info">\n <table class="row-border hover order-column stripe"></table>\n </div>\n </div>\n </div>\n </div>\n <div id="imageViewer" class="image-viewer">\n <div class="image-viewer-backdrop" onclick="closeImageViewer()"></div>\n <div class="image-container">\n <div class="image-viewer-header">\n <span class="image-viewer-title">Layout Screenshot Preview</span>\n <button class="close-button" onclick="closeImageViewer()" title="Close (Esc)">&times;</button>\n </div>\n <div class="image-viewer-body">\n <img id="imageView" src="" alt="Screenshot Preview" />\n </div>\n </div>\n </div>\n </main>';
584
463
  }
585
464
  function getCssData() {
586
- return `html {
587
- width: 100vw;
588
- height: 100vh;
589
- }
465
+ return `:root {
466
+ --bg-body: #f8fafc;
467
+ --bg-card: #ffffff;
468
+ --border: #e2e8f0;
469
+ --foreground: #0f172a;
470
+ --text-muted: #64748b;
471
+ --accent: #ea580c;
472
+ --accent-light: #fff7ed;
473
+ --muted-bg: #f1f5f9;
474
+ --success: #10b981;
475
+ --danger: #ef4444;
476
+ --warning: #f59e0b;
477
+ --info: #0284c7;
478
+ --purple: #8b5cf6;
479
+ --radius: 8px;
480
+ }
590
481
 
591
- * {
592
- user-select: none;
593
- box-sizing: border-box;
594
- scrollbar-width: thin;
595
- scroll-behavior: smooth;
596
- }
482
+ [data-theme="dark"] {
483
+ --bg-body: #09090b;
484
+ --bg-card: #18181b;
485
+ --border: #27272a;
486
+ --foreground: #f8fafc;
487
+ --text-muted: #a1a1aa;
488
+ --accent: #f97316;
489
+ --accent-light: rgba(249, 115, 22, 0.15);
490
+ --muted-bg: #27272a;
491
+ --success: #10b981;
492
+ --danger: #ef4444;
493
+ --warning: #f59e0b;
494
+ --info: #38bdf8;
495
+ --purple: #a855f7;
496
+ }
597
497
 
598
- body {
599
- width: 100%;
600
- height: 100%;
601
- margin: 0;
602
- display: flex;
603
- flex-direction: column;
604
- font-family: Arial, sans-serif;
605
- font-family: 'Helvetica Neue', Arial, sans-serif;
606
- -webkit-font-smoothing: antialiased; /* Webkit-based browsers */
607
- -moz-osx-font-smoothing: grayscale; /* Firefox on OS X */
608
- font-smooth: always; /* Non-standard, some browsers */
609
- }
498
+ * {
499
+ box-sizing: border-box;
500
+ scrollbar-width: thin;
501
+ scrollbar-color: var(--border) transparent;
502
+ }
610
503
 
611
- header {
612
- background-color: #333;
613
- height: 8%;
614
- display: flex;
615
- }
504
+ html, body {
505
+ margin: 0;
506
+ padding: 0;
507
+ width: 100%;
508
+ height: 100%;
509
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
510
+ background-color: var(--bg-body);
511
+ color: var(--foreground);
512
+ font-size: 14px;
513
+ line-height: 1.5;
514
+ -webkit-font-smoothing: antialiased;
515
+ }
616
516
 
617
- main {
618
- display: flex;
619
- flex-direction: row;
620
- width: 100%;
621
- height: 92%
622
- }
517
+ /* Header */
518
+ .report-header {
519
+ height: 52px;
520
+ background-color: var(--bg-card);
521
+ border-bottom: 1px solid var(--border);
522
+ display: flex;
523
+ align-items: center;
524
+ justify-content: space-between;
525
+ padding: 0 20px;
526
+ position: sticky;
527
+ top: 0;
528
+ z-index: 100;
529
+ }
623
530
 
624
- .sidebar {
625
- width: 16%;
626
- height: 100%;
627
- background-color: #333;
628
- color: #fff;
629
- padding: 20px;
630
- box-sizing: border-box;
631
- float: left;
632
- }
531
+ .header-left {
532
+ display: flex;
533
+ align-items: center;
534
+ gap: 12px;
535
+ }
633
536
 
634
- .logo {
635
- flex-grow: 1;
636
- align-content: center;
637
- margin-left: 2%;
638
- color: #14cf96;
639
- font-weight: bold;
640
- font-size: 1.4em;
641
- }
537
+ .brand-badge {
538
+ font-family: 'Outfit', sans-serif;
539
+ font-weight: 700;
540
+ font-size: 15px;
541
+ letter-spacing: -0.3px;
542
+ color: var(--foreground);
543
+ }
642
544
 
643
- .report-timestamp {
644
- flex-grow: 1;
645
- height: 100%;
646
- align-content: center;
647
- margin-right: 2%;
648
- }
545
+ .brand-text .brand-ai {
546
+ color: var(--accent);
547
+ }
649
548
 
650
- .report-timestamp .info {
651
- float: right;
652
- font-size: 0.9em;
653
- color: #90a3a9;
654
- }
549
+ .header-divider {
550
+ width: 1px;
551
+ height: 16px;
552
+ background-color: var(--border);
553
+ }
655
554
 
656
- .menu {
657
- list-style-type: none;
658
- padding: 0;
659
- margin: 0;
660
- }
555
+ .product-badge {
556
+ display: inline-flex;
557
+ align-items: center;
558
+ gap: 5px;
559
+ background-color: var(--muted-bg);
560
+ color: var(--foreground);
561
+ border: 1px solid var(--border);
562
+ border-radius: 6px;
563
+ padding: 2px 8px;
564
+ font-size: 12px;
565
+ font-weight: 500;
566
+ }
661
567
 
662
- .menu-item {
663
- margin-bottom: 10px;
664
- }
568
+ .mode-pill {
569
+ display: inline-flex;
570
+ align-items: center;
571
+ gap: 5px;
572
+ border-radius: 6px;
573
+ padding: 2px 8px;
574
+ font-size: 12px;
575
+ font-weight: 500;
576
+ }
665
577
 
666
- .menu-item a {
667
- color: #fff;
668
- text-decoration: none;
669
- display: block;
670
- padding: 10px;
671
- border-radius: 5px;
672
- font-size: 1.05rem;
673
- }
578
+ .mode-pill .mode-dot {
579
+ width: 6px;
580
+ height: 6px;
581
+ border-radius: 50%;
582
+ }
674
583
 
675
- .menu-item a:hover {
676
- background-color: #555;
677
- }
584
+ .mode-pill.mode-sanity {
585
+ background-color: rgba(16, 185, 129, 0.1);
586
+ color: #059669;
587
+ border: 1px solid rgba(16, 185, 129, 0.2);
588
+ }
589
+ .mode-pill.mode-sanity .mode-dot { background-color: #10b981; }
678
590
 
679
- .submenu {
680
- display: none;
681
- list-style-type: none;
682
- padding-left: 20px;
683
- }
591
+ .mode-pill.mode-context {
592
+ background-color: rgba(59, 130, 246, 0.1);
593
+ color: #2563eb;
594
+ border: 1px solid rgba(59, 130, 246, 0.2);
595
+ }
596
+ .mode-pill.mode-context .mode-dot { background-color: #3b82f6; }
684
597
 
685
- .menu-item.has-submenu > a::after {
686
- content: '⯆';
687
- float: right;
688
- margin-left: 5px;
689
- }
598
+ .mode-pill.mode-i18n {
599
+ background-color: rgba(234, 88, 12, 0.1);
600
+ color: #ea580c;
601
+ border: 1px solid rgba(234, 88, 12, 0.2);
602
+ }
603
+ .mode-pill.mode-i18n .mode-dot { background-color: #ea580c; }
604
+
605
+ .status-pill {
606
+ display: inline-flex;
607
+ align-items: center;
608
+ gap: 4px;
609
+ border-radius: 6px;
610
+ padding: 2px 8px;
611
+ font-size: 12px;
612
+ font-weight: 600;
613
+ }
690
614
 
691
- .menu-item.has-submenu.selected > a::after {
692
- content: '⯅';
693
- float: right;
694
- margin-left: 5px;
695
- }
615
+ .status-pill.status-passed {
616
+ background-color: rgba(16, 185, 129, 0.1);
617
+ color: #059669;
618
+ border: 1px solid rgba(16, 185, 129, 0.2);
619
+ }
696
620
 
697
- .menu-item.selected > a {
698
- background-color: #555;
699
- }
621
+ .status-pill.status-failed {
622
+ background-color: rgba(239, 68, 68, 0.1);
623
+ color: #dc2626;
624
+ border: 1px solid rgba(239, 68, 68, 0.2);
625
+ }
700
626
 
701
- .submenu .sub-menu-item {
702
- margin: 3px auto;
703
- }
627
+ .timestamp-badge {
628
+ display: inline-flex;
629
+ align-items: center;
630
+ gap: 5px;
631
+ color: var(--text-muted);
632
+ font-size: 12px;
633
+ }
704
634
 
705
- .submenu .sub-menu-item a:hover {
706
- background-color: #777;
707
- }
635
+ /* Navigation Tabs (Minimalist client_v2 style) */
636
+ .nav-tabs-wrapper {
637
+ display: flex;
638
+ align-items: center;
639
+ }
708
640
 
709
- .submenu .sub-menu-item.selected a {
710
- background-color: #555 !important;
711
- }
641
+ .tabs-list {
642
+ background-color: var(--muted-bg);
643
+ border-radius: 8px;
644
+ padding: 3px;
645
+ display: inline-flex;
646
+ align-items: center;
647
+ gap: 2px;
648
+ list-style: none;
649
+ margin: 0;
650
+ }
712
651
 
713
- .submenu.active {
714
- display: block !important;
715
- }
652
+ .tab-item {
653
+ border: none;
654
+ background: transparent;
655
+ color: var(--text-muted);
656
+ font-size: 13px;
657
+ font-weight: 500;
658
+ padding: 5px 12px;
659
+ border-radius: 6px;
660
+ cursor: pointer;
661
+ transition: all 0.15s ease;
662
+ display: inline-flex;
663
+ align-items: center;
664
+ gap: 6px;
665
+ font-family: inherit;
666
+ outline: none;
667
+ }
716
668
 
717
- .view-screenshot-image {
718
- width: 100px;
719
- height: 30px;
720
- content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBVcGxvYWRlZCB0bzogU1ZHIFJlcG8sIHd3dy5zdmdyZXBvLmNvbSwgR2VuZXJhdG9yOiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4NCjxzdmcgZmlsbD0iIzAwMDAwMCIgaGVpZ2h0PSI4MDBweCIgd2lkdGg9IjgwMHB4IiB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIA0KCSB2aWV3Qm94PSIwIDAgNDkwIDQ5MCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8Zz4NCgk8cGF0aCBkPSJNMjQ1LjIwNCwxMDEuMjY3QzY3LjE3MSwxMDEuMjY3LDAsMjQ1LDAsMjQ1czY2Ljc2MywxNDMuNzMzLDI0NC43OTYsMTQzLjczM0M0MjIuODI5LDM4OC43MzMsNDkwLDI0NSw0OTAsMjQ1DQoJCVM0MjMuMjM4LDEwMS4yNjcsMjQ1LjIwNCwxMDEuMjY3eiBNMjQ0Ljc5NiwzNzMuNDIxYy0xNDYuMzkzLDAtMjEyLjM2Ny0xMDEuMDUzLTIyNy41MDYtMTI4LjMzMw0KCQljMTUuMjQ5LTI2Ljc5Niw4Mi43MzMtMTI4LjUwOCwyMjcuOTE0LTEyOC41MDhjMTQ2LjUxNCwwLDIxMi40NzUsMTAxLjIyLDIyNy41NDMsMTI4LjQNCgkJQzQ1Ny41NzgsMjcyLjIwMywzOTEuMzEzLDM3My40MjEsMjQ0Ljc5NiwzNzMuNDIxeiIvPg0KCTxwYXRoIGQ9Ik0yNDUuMDAzLDE0Ni4xMjRjLTU0LjUyMSwwLTk4Ljg4MSw0NC4zNTItOTguODgxLDk4Ljg3M2MwLDU0LjUyMSw0NC4zNiw5OC44ODEsOTguODgxLDk4Ljg4MXM5OC44NzMtNDQuMzYsOTguODczLTk4Ljg4MQ0KCQlDMzQzLjg3NiwxOTAuNDc3LDI5OS41MjQsMTQ2LjEyNCwyNDUuMDAzLDE0Ni4xMjR6IE0yNDUuMDAzLDMyOC41NjZjLTQ2LjA4LDAtODMuNTY4LTM3LjQ4OS04My41NjgtODMuNTY4DQoJCWMwLTQ2LjA3MiwzNy40ODktODMuNTYxLDgzLjU2OC04My41NjFjNDYuMDcyLDAsODMuNTYxLDM3LjQ4OSw4My41NjEsODMuNTYxQzMyOC41NjQsMjkxLjA3NywyOTEuMDc1LDMyOC41NjYsMjQ1LjAwMywzMjguNTY2eiIvPg0KCTxwYXRoIGQ9Ik0yNDUuMDAzLDE3NS41ODNjLTM4LjI4MSwwLTY5LjQyMiwzMS4xNDEtNjkuNDIyLDY5LjQxNWMwLDM4LjI3NCwzMS4xNDEsNjkuNDE1LDY5LjQyMiw2OS40MTUNCgkJYzM4LjI3NCwwLDY5LjQxNS0zMS4xNDEsNjkuNDE1LTY5LjQxNUMzMTQuNDE3LDIwNi43MjQsMjgzLjI3NywxNzUuNTgzLDI0NS4wMDMsMTc1LjU4M3ogTTI0NS4wMDMsMjk5LjENCgkJYy0yOS44MzMsMC01NC4xMS0yNC4yNy01NC4xMS01NC4xMDJjMC0yOS44MzIsMjQuMjc3LTU0LjEwMiw1NC4xMS01NC4xMDJzNTQuMTAyLDI0LjI3LDU0LjEwMiw1NC4xMDINCgkJQzI5OS4xMDUsMjc0LjgzLDI3NC44MzUsMjk5LjEsMjQ1LjAwMywyOTkuMXoiLz4NCgk8cGF0aCBkPSJNMjQ1LjAwMywyMDYuNjc5Yy0yMS4xMywwLTM4LjMyNiwxNy4xODktMzguMzI2LDM4LjMxOWMwLDIxLjEyOSwxNy4xOTcsMzguMzI2LDM4LjMyNiwzOC4zMjZzMzguMzE5LTE3LjE5NywzOC4zMTktMzguMzI2DQoJCUMyODMuMzIxLDIyMy44NjgsMjY2LjEzMiwyMDYuNjc5LDI0NS4wMDMsMjA2LjY3OXogTTI0NS4wMDMsMjY4LjAxMWMtMTIuNjg4LDAtMjMuMDE0LTEwLjMyNi0yMy4wMTQtMjMuMDE0DQoJCWMwLTEyLjY4OCwxMC4zMjUtMjMuMDA2LDIzLjAxNC0yMy4wMDZjMTIuNjg4LDAsMjMuMDA2LDEwLjMxOCwyMy4wMDYsMjMuMDA2QzI2OC4wMDksMjU3LjY4NiwyNTcuNjkxLDI2OC4wMTEsMjQ1LjAwMywyNjguMDExeiIvPg0KPC9nPg0KPC9zdmc+);
721
- }
669
+ .tab-item:hover {
670
+ color: var(--foreground);
671
+ }
722
672
 
723
- .content-wrapper {
724
- padding: 1%;
725
- float: left;
726
- width: 84%;
727
- background-color: #f4f4f4;
728
- overflow: hidden;
729
- height: 100%;
730
- }
673
+ .tab-item.selected {
674
+ background-color: var(--bg-card);
675
+ color: var(--foreground);
676
+ font-weight: 600;
677
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
678
+ }
731
679
 
732
- .content {
733
- display: none !important;
734
- height: 100%;
735
- }
680
+ .tab-dropdown {
681
+ position: relative;
682
+ }
736
683
 
737
- .content .title {
738
- font-size: 1rem;
739
- color: #080404e2;
740
- font-weight: 600;
741
- }
684
+ .tab-chevron {
685
+ transition: transform 0.15s ease;
686
+ }
742
687
 
743
- .content .title::after {
744
- content: ':';
745
- }
688
+ .submenu.active + .tab-item .tab-chevron,
689
+ .tab-dropdown:focus-within .tab-chevron {
690
+ transform: rotate(180deg);
691
+ }
746
692
 
747
- .content.active {
748
- display: flex !important;
749
- flex-direction: column;
750
- gap: 0.9rem;
751
- flex-wrap: wrap;
752
- transition: all 2s ease-in-out;
753
- }
693
+ .tabs-list .submenu {
694
+ position: absolute;
695
+ top: calc(100% + 4px);
696
+ right: 0;
697
+ background-color: var(--bg-card);
698
+ border: 1px solid var(--border);
699
+ border-radius: 8px;
700
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
701
+ min-width: 140px;
702
+ padding: 4px;
703
+ display: none;
704
+ z-index: 1000;
705
+ list-style: none;
706
+ margin: 0;
707
+ }
754
708
 
755
- .container {
756
- height: 99%;
757
- overflow: hidden;
758
- overflow-y: auto;
759
- }
709
+ .tabs-list .submenu.active {
710
+ display: block;
711
+ }
760
712
 
761
- .sidebar .footer {
762
- bottom: 1.5%;
763
- position: absolute;
764
- font-size: 0.75rem;
765
- color: #14cf96;
766
- font-family: system-ui;
767
- width: inherit;
768
- }
713
+ .sub-menu-item {
714
+ margin: 0;
715
+ padding: 0;
716
+ }
769
717
 
770
- #overview {
771
- flex-direction: row;
772
- justify-content: space-between;
773
- }
718
+ .sub-menu-item a {
719
+ display: block;
720
+ padding: 6px 12px;
721
+ font-size: 13px;
722
+ color: var(--foreground);
723
+ text-decoration: none;
724
+ border-radius: 5px;
725
+ font-family: inherit;
726
+ transition: background 0.15s;
727
+ }
774
728
 
775
- #overview .card {
776
- display: flex;
777
- flex-direction: column;
778
- width: 25rem;
779
- border: 1px solid #ddd;
780
- box-shadow: 0 22px 35px -16px rgba(0, 0, 0, 0.3);
781
- border-radius: 5px;
782
- background: white;
783
- padding: 1rem;
784
- }
729
+ .sub-menu-item a:hover {
730
+ background-color: var(--muted-bg);
731
+ }
785
732
 
786
- #overview .overall-quality {
787
- flex-basis: 100%;
788
- line-height: 14px;
789
- }
733
+ /* Main Content Layout (Full Width) */
734
+ .report-main {
735
+ width: 100%;
736
+ height: calc(100% - 52px);
737
+ overflow-y: auto;
738
+ }
790
739
 
791
- #overview .overall-quality .section {
792
- display: flex;
793
- flex-direction: row;
794
- }
740
+ .content-wrapper {
741
+ width: 100%;
742
+ min-height: 100%;
743
+ padding: 20px;
744
+ }
795
745
 
796
- #overview .overall-quality .section .block {
797
- width: 50%;
798
- }
746
+ .container {
747
+ max-width: 1360px;
748
+ margin: 0 auto;
749
+ }
799
750
 
800
- #overview .overall-quality .section .block article p.desc {
801
- font-size: 0.85em;
802
- }
751
+ .content {
752
+ display: none;
753
+ }
803
754
 
804
- #overview .overall-quality .section .block article .items li {
805
- font-size: 0.8em;
806
- }
755
+ .content.active {
756
+ display: block;
757
+ }
807
758
 
808
- #overview .overall-quality .section .block article .items li .detail {
809
- margin-top: -2%;
810
- }
759
+ /* Cards */
760
+ .card {
761
+ background-color: var(--bg-card);
762
+ border: 1px solid var(--border);
763
+ border-radius: var(--radius);
764
+ padding: 20px;
765
+ margin-bottom: 20px;
766
+ }
811
767
 
812
- #overview .overall-quality .section .block .graph {
813
- margin-top: 1.5em;
814
- }
768
+ .card > .title {
769
+ font-size: 15px;
770
+ font-weight: 600;
771
+ color: var(--foreground);
772
+ margin-bottom: 14px;
773
+ display: block;
774
+ }
815
775
 
816
- #overview .string-quality,
817
- #overview .number-quality,
818
- #overview .datetime-quality,
819
- #overview .skipped-items {
820
- flex-basis: 48.5%;
821
- }
776
+ /* Common Info / Sanity Details Card */
777
+ .common-info.card {
778
+ border-left: 3px solid var(--accent);
779
+ }
822
780
 
823
- #overview .string-quality .graph,
824
- #overview .number-quality .graph,
825
- #overview .datetime-quality .graph,
826
- #overview .skipped-items .graph {
827
- align-self: center;
828
- }
781
+ .common-info .title {
782
+ font-size: 15px;
783
+ font-weight: 600;
784
+ color: var(--foreground);
785
+ margin-bottom: 8px;
786
+ display: block;
787
+ }
829
788
 
830
- #overview .string-quality .graph {
831
- margin-left: 4rem;
832
- }
789
+ .common-info .info {
790
+ font-size: 13.5px;
791
+ color: var(--text-muted);
792
+ line-height: 1.6;
793
+ margin: 0;
794
+ }
833
795
 
834
- #overview .number-quality .graph,
835
- #overview .datetime-quality .graph {
836
- margin-top: -0.9rem;
837
- margin-left: 4.5rem;
838
- }
796
+ .btn-view-log {
797
+ margin-top: 14px;
798
+ background-color: var(--accent);
799
+ color: #ffffff;
800
+ border: none;
801
+ padding: 6px 14px;
802
+ border-radius: 6px;
803
+ font-size: 13px;
804
+ font-weight: 500;
805
+ cursor: pointer;
806
+ display: inline-flex;
807
+ align-items: center;
808
+ gap: 6px;
809
+ font-family: inherit;
810
+ transition: opacity 0.15s;
811
+ }
839
812
 
840
- #overview .common-info {
841
- width: 100%;
842
- height: 100%;
843
- }
813
+ .btn-view-log:hover {
814
+ opacity: 0.9;
815
+ }
844
816
 
845
- #overview .common-info .info {
846
- font-size: 0.9em;
847
- margin-top: 0.8%;
848
- }
817
+ /* Overall Quality Section */
818
+ .overall-quality .section {
819
+ display: flex;
820
+ gap: 24px;
821
+ align-items: flex-start;
822
+ }
849
823
 
850
- #overview .common-info .title {
851
- font-size: 1.1em;
852
- }
824
+ .overall-quality .block:first-child {
825
+ flex: 1;
826
+ }
853
827
 
854
- #overview .common-info .section {
855
- width: 100%;
856
- height: 100%;
857
- overflow: hidden;
858
- padding-top: 3%;
859
- }
828
+ .overall-quality .block:last-child {
829
+ width: 520px;
830
+ min-width: 480px;
831
+ }
860
832
 
861
- #overview .common-info .section .page-tiles .title-section .locale-filter-wrapper {
862
- margin-right: 1%;
863
- font-size: 0.8em;
864
- font-weight: 600;
865
- }
833
+ .overall-quality .desc {
834
+ font-size: 13.5px;
835
+ color: var(--text-muted);
836
+ line-height: 1.6;
837
+ margin: 0 0 16px 0;
838
+ }
866
839
 
867
- #overview .common-info .section .page-tiles .title-section .locale-filter-wrapper #locale-filter {
868
- font-size: 0.9em;
869
- height: 1.7em;
870
- border-radius: 3px
871
- }
840
+ .overall-quality .items {
841
+ list-style: none;
842
+ padding: 0;
843
+ margin: 0;
844
+ display: grid;
845
+ grid-template-columns: 1fr 1fr;
846
+ gap: 12px;
847
+ }
872
848
 
873
- #overview .common-info .section .page-tiles .title-section {
874
- display: flex;
875
- align-items: center;
876
- }
849
+ .overall-quality .items li {
850
+ background-color: var(--muted-bg);
851
+ padding: 12px;
852
+ border-radius: 6px;
853
+ border: 1px solid var(--border);
854
+ }
877
855
 
878
- #overview .common-info .section .page-tiles .title-section .title-wrapper {
879
- flex: 1;
880
- }
856
+ .overall-quality .items li h4 {
857
+ margin: 0 0 4px 0;
858
+ font-size: 13px;
859
+ font-weight: 600;
860
+ color: var(--foreground);
861
+ }
881
862
 
882
- #overview .common-info .section .page-tiles .title-section .search-field-wrapper {
883
- flex: 0.7;
884
- font-size: 0.8em;
885
- font-weight: 600;
886
- }
863
+ .overall-quality .items li p.detail {
864
+ margin: 0;
865
+ font-size: 12px;
866
+ color: var(--text-muted);
867
+ line-height: 1.4;
868
+ }
887
869
 
888
- #overview .common-info .section .page-tiles {
889
- display: flex;
890
- flex-direction: column;
891
- gap: 1%;
892
- width: 100%;
893
- height: 92%;
894
- }
870
+ /* Graphs grid */
871
+ .string-quality, .skipped-items, .number-quality, .datetime-quality {
872
+ margin-bottom: 20px;
873
+ }
895
874
 
896
- #overview .common-info .section .page-tiles .title {
897
- flex: 1;
898
- }
875
+ /* Status Bars */
876
+ .status-bar {
877
+ margin-bottom: 16px;
878
+ }
899
879
 
900
- #overview .common-info .section .page-tiles .tiles-list-wrapper {
901
- width: 100%;
902
- height: 100%;
903
- border: 0.5px solid #00000008;
904
- border-radius: 5px;
905
- padding: 0;
906
- margin: 0;
907
- }
880
+ .bar-container {
881
+ margin-bottom: 10px;
882
+ }
908
883
 
909
- #overview .common-info .section .page-tiles .tiles-list {
910
- width: 100%;
911
- height: 100%;
912
- overflow: hidden;
913
- overflow-y: auto;
914
- padding: 10px;
915
- display: flex;
916
- flex-wrap: wrap;
917
- gap: 2.2%;
918
- justify-content: start;
919
- }
884
+ .bar-container .name {
885
+ font-size: 12px;
886
+ font-weight: 500;
887
+ color: var(--text-muted);
888
+ margin-bottom: 4px;
889
+ }
920
890
 
921
- #overview .common-info .section .page-tiles .tiles-list .empty-context {
922
- background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAA7AAAAOwBeShxvQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAALnSURBVFiFxddNiFZlFAfw3zjvSGUfWjRCgdmiTV8IGjlFhBJotQmjdraqqBbZtAjBFoYVBH0tGiQUFCJKDQqpNpW0sJosIvowyEW1s4a+7UOsuS3OubzPvL133hmbefvD5d7nPOd5zsfzP+feS2AEb+MYqnm+jqWtkbTtKvzVB8Od1wmslt5UeAKLzD8W4am0+S7ttPfDeI3T0+bxVmH4hj46UGPhQHryv6FVPO/rs+1boMzAQJ8dqGBBn43+C60G+TW4B4NzZOdvjOFgt8m6MZR40dw3nhe62W3KQH00T2K8d4DTYjXu15DNJgdqjPvv1fEh1uH1k3FgLvAVLm2anC8HlmE5luA7fIZfO3ROzMSBUdkwuuAQHi/GLdyOu3F5h+5xvIlH8F7KbpPk71YFO/Rm9Q+F/nJ8XMx9L96yr+B9EW09N4ahemFTJ1yMtabvA5/jcBofx1IcwWbsF98YNc7GvXgAp6ZjN2OyKQMzRUs78jdwZg/9VZhI/QdpzsAVmmv3MLbm813YLiJfhV9m4PRawYc/cBHdM/Co5rP/XfsMP0nZhmLtQXyA4RyvE5wYLXT25LotTVXwsGD5UJe5LwSpluEyQcb9xfwpWIm3cp/dKSv32o1bcSMnz4E1ue5Ah/xc7cxM5v1ZU494OOXfNmWgiQMVdgrCnZGyzgYzgW0izQP4CQ+ZGuTPeT+r3nQ2HHguda7M8aGOtesFwep+UIlOOFzoXJjyr2n/E5TRnoabRBcsrw2ipomS+1Pw4ZxibW30GdEbPs3x9kLnjpS9LL2rcL3Z49Vcu7WQjYqGU5/5cBq/OseDhc2NA9iEp0W/PiD+E6ZDhecF80fwjsjEtaL8emGbaEJHcAnx8fGY2f2evVZsOJayCdFkmjCYxifFsa1hamlcgBVY2COCSjSbozkewl7BmQovYRc+wo84H9fhPlycgd6ZOnOGBSKtv5k+c1/KyOcL52GLeOcfFbz6RrB9oy6d9R/3ey953ywo7QAAAABJRU5ErkJggg==);
923
- width: 100%;
924
- background-repeat: no-repeat;
925
- height: 100%;
926
- background-size: 2.5em;
927
- background-position-x: 50%;
928
- background-position-y: 43%;
929
- display: flex;
930
- justify-content: center;
931
- align-content: center;
932
- flex-wrap: wrap;
933
- }
891
+ .bar-holder {
892
+ background-color: var(--muted-bg);
893
+ height: 8px;
894
+ border-radius: 4px;
895
+ overflow: hidden;
896
+ position: relative;
897
+ }
934
898
 
935
- #overview .common-info .section .page-tiles .tiles-list .tile-container {
936
- width: 23%;
937
- height: 35%;
938
- text-align: center;
939
- display: flex;
940
- flex-direction: column;
941
- border: 1px solid #80808030;
942
- border-radius: 5px;
943
- }
899
+ .bar {
900
+ height: 100%;
901
+ border-radius: 4px;
902
+ text-indent: -9999px;
903
+ transition: width 0.3s ease;
904
+ }
944
905
 
945
- #overview .common-info .section .page-tiles .tiles-list .tile-container:hover {
946
- transform: scale(1.03);
947
- box-shadow: 0 22px 35px -16px #00000033;
948
- cursor: pointer;
949
- transition: all 0.2s ease-in-out;
950
- }
906
+ .bar.--green { background-color: var(--success); }
907
+ .bar.--blue { background-color: #3b82f6; }
908
+ .bar.--yellow { background-color: var(--warning); }
909
+ .bar.--red { background-color: var(--danger); }
910
+
911
+ /* Stat Summary Table */
912
+ .stat .name {
913
+ font-size: 13px;
914
+ font-weight: 600;
915
+ color: var(--foreground);
916
+ margin: 14px 0 8px 0;
917
+ }
951
918
 
952
- #overview .common-info .section .page-tiles .tiles-list .tile-container .image {
953
- width: 100%;
954
- height: 85%;
955
- object-fit: contain;
956
- }
919
+ .stat table {
920
+ width: 100%;
921
+ border-collapse: collapse;
922
+ }
957
923
 
958
- #overview .common-info .section .page-tiles .tiles-list .tile-container .name span {
959
- width: 75%;
960
- display: inline-block;
961
- white-space: nowrap;
962
- overflow: hidden;
963
- text-overflow: ellipsis;
964
- }
924
+ .stat tr {
925
+ border-bottom: 1px solid var(--border);
926
+ }
965
927
 
966
- #overview .common-info .section .page-tiles .tiles-list .tile-container .name {
967
- width: 100%;
968
- display: block;
969
- height: 15%;
970
- align-content: center;
971
- background-color: rgb(0 0 0 / 7%);
972
- border-top: 1px solid #80808030;
973
- color: #2cb2c1e6;
974
- -webkit-font-smoothing: antialiased;
975
- font-variant: all-small-caps;
976
- font-weight: 600;
977
- font-size: 0.87em;
978
- }
928
+ .stat td {
929
+ padding: 6px 0;
930
+ font-size: 12.5px;
931
+ }
979
932
 
980
- #insights .cards {
981
- display: flex;
982
- flex-direction: column;
983
- gap: 1.5rem;
984
- }
933
+ .stat td.name {
934
+ color: var(--text-muted);
935
+ }
985
936
 
986
- #insights .cards .holder {
987
- display: flex;
988
- flex-direction: row;
989
- gap: 1.5rem;
990
- flex-wrap: wrap;
991
- }
937
+ .stat td.value {
938
+ color: var(--foreground);
939
+ font-weight: 600;
940
+ text-align: right;
941
+ font-variant-numeric: tabular-nums;
942
+ }
992
943
 
993
- #insights .cards .card {
994
- display: flex;
995
- flex-direction: column;
996
- width: 20rem;
997
- min-height: 10rem;
998
- border: 1px solid #ddd;
999
- box-shadow: 0 22px 35px -16px rgba(0, 0, 0, 0.3);
1000
- border-radius: 5px;
1001
- background: white;
1002
- }
944
+ /* Insights Cards Holder */
945
+ #insights .cards .holder {
946
+ display: grid;
947
+ grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
948
+ gap: 20px;
949
+ }
1003
950
 
1004
- #insights .cards .card:hover {
1005
- transform: scale(1.05);
1006
- box-shadow: 0 22px 35px -16px #07ff7d33;
1007
- cursor: pointer;
1008
- transition: all 0.2s ease-in-out;
1009
- }
951
+ #insights .card[data-locale] {
952
+ cursor: pointer;
953
+ transition: border-color 0.15s, box-shadow 0.15s;
954
+ }
1010
955
 
1011
- #insights .cards .card .title {
1012
- height: 2.5rem;
1013
- font-size: 1rem;
1014
- padding-top: 1rem;
1015
- font-weight: 500;
1016
- background: #0c5ad9d6;
1017
- border-top-left-radius: 5px;
1018
- border-top-right-radius: 5px;
1019
- padding-left: 1rem;
1020
- color: white;
1021
- }
956
+ #insights .card[data-locale]:hover {
957
+ border-color: var(--accent);
958
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
959
+ }
1022
960
 
1023
- #insights .cards .card .title::after {
1024
- content: '';
1025
- }
961
+ /* Locale Table Header */
962
+ .locale-header-bar {
963
+ display: flex;
964
+ align-items: center;
965
+ gap: 12px;
966
+ margin-bottom: 16px;
967
+ }
1026
968
 
1027
- #insights .cards .card .card-content {
1028
- display: flex;
1029
- flex-direction: column;
1030
- gap: 1rem;
1031
- padding: 1rem;
1032
- }
969
+ .back-to-insights-btn {
970
+ background-color: var(--muted-bg);
971
+ border: 1px solid var(--border);
972
+ color: var(--foreground);
973
+ border-radius: 6px;
974
+ padding: 5px 12px;
975
+ font-size: 12.5px;
976
+ font-weight: 500;
977
+ cursor: pointer;
978
+ display: inline-flex;
979
+ align-items: center;
980
+ gap: 6px;
981
+ font-family: inherit;
982
+ transition: background 0.15s;
983
+ }
1033
984
 
1034
- #insights .cards .card .status-bar {
1035
- display: flex;
1036
- flex-direction: column;
1037
- gap: 0.8rem;
1038
- }
985
+ .back-to-insights-btn:hover {
986
+ background-color: var(--border);
987
+ }
1039
988
 
1040
- #insights .cards .card .status-bar .bar-container .name {
1041
- font-size: 0.78rem;
1042
- -webkit-font-smoothing: antialiased;
1043
- -moz-osx-font-smoothing: grayscale;
1044
- }
989
+ .locale-header-bar .title {
990
+ font-size: 16px;
991
+ font-weight: 600;
992
+ color: var(--foreground);
993
+ }
1045
994
 
1046
- #insights .cards .card .status-bar .bar-container .name::after {
1047
- content: ':';
1048
- }
995
+ /* DataTables Styling */
996
+ .coverage-info {
997
+ background-color: var(--bg-card);
998
+ border: 1px solid var(--border);
999
+ border-radius: var(--radius);
1000
+ padding: 16px;
1001
+ }
1049
1002
 
1050
- #insights .cards .card .status-bar .bar-container .bar-holder {
1051
- width: 100%;
1052
- height: 10px;
1053
- border: 1px solid #00000038;
1054
- border-radius: 2px;
1055
- }
1003
+ table.dataTable {
1004
+ border-collapse: separate !important;
1005
+ border-spacing: 0;
1006
+ width: 100% !important;
1007
+ border: 1px solid var(--border) !important;
1008
+ border-radius: 6px;
1009
+ overflow: hidden;
1010
+ background-color: var(--bg-card);
1011
+ }
1056
1012
 
1057
- #insights .cards .card .status-bar .bar-container .bar-holder .bar {
1058
- height: 100%;
1059
- font-size: 0.63rem;
1060
- text-align: right;
1061
- color: rgb(0, 0, 0);
1062
- }
1013
+ table.dataTable thead th {
1014
+ background-color: var(--muted-bg) !important;
1015
+ color: var(--foreground) !important;
1016
+ font-size: 12.5px !important;
1017
+ font-weight: 600 !important;
1018
+ border-bottom: 1px solid var(--border) !important;
1019
+ padding: 10px 12px !important;
1020
+ text-align: left;
1021
+ }
1063
1022
 
1064
- .bar.--green {
1065
- background-color: #1dedaf;
1066
- }
1023
+ table.dataTable tbody td {
1024
+ padding: 10px 12px !important;
1025
+ font-size: 13px !important;
1026
+ color: var(--foreground) !important;
1027
+ border-bottom: 1px solid var(--border) !important;
1028
+ }
1067
1029
 
1068
- .bar.--red {
1069
- background-color: #fe3e3e;
1070
- }
1030
+ table.dataTable tbody tr:last-child td {
1031
+ border-bottom: none !important;
1032
+ }
1071
1033
 
1072
- .bar.--yellow {
1073
- background-color: #faef1f;
1074
- }
1034
+ table.dataTable tbody tr:hover td {
1035
+ background-color: var(--muted-bg) !important;
1036
+ }
1075
1037
 
1076
- .bar.--blue {
1077
- background-color: #77c2ff;
1078
- }
1038
+ select.filter.dt-input {
1039
+ display: block;
1040
+ width: 100%;
1041
+ margin-top: 5px;
1042
+ padding: 3px 6px;
1043
+ font-size: 11.5px;
1044
+ border: 1px solid var(--border);
1045
+ border-radius: 4px;
1046
+ background-color: var(--bg-card);
1047
+ color: var(--foreground);
1048
+ font-family: inherit;
1049
+ outline: none;
1050
+ }
1079
1051
 
1080
- #insights .cards .card .stat {
1081
- display: flex;
1082
- flex-direction: column;
1083
- gap: 0.3rem;
1084
- border: 0.5px solid #00000012;
1085
- border-radius: 6px;
1086
- }
1052
+ .reset-filters-btn {
1053
+ background-color: var(--muted-bg);
1054
+ border: 1px solid var(--border);
1055
+ color: var(--foreground);
1056
+ border-radius: 6px;
1057
+ padding: 4px 10px;
1058
+ font-size: 12px;
1059
+ font-weight: 500;
1060
+ cursor: pointer;
1061
+ font-family: inherit;
1062
+ transition: background 0.15s;
1063
+ margin-left: 12px;
1064
+ }
1087
1065
 
1088
- #insights .cards .card .stat table td {
1089
- font-size: 0.78rem;
1090
- -webkit-font-smoothing: antialiased;
1091
- -moz-osx-font-smoothing: grayscale;
1092
- }
1066
+ .reset-filters-btn:hover {
1067
+ background-color: var(--border);
1068
+ }
1093
1069
 
1094
- #insights .cards .card .stat table td.name {
1095
- width: 70%;
1096
- }
1070
+ .view-screenshot-btn {
1071
+ background-color: var(--muted-bg);
1072
+ border: 1px solid var(--border);
1073
+ color: var(--foreground);
1074
+ border-radius: 6px;
1075
+ padding: 4px 10px;
1076
+ font-size: 12px;
1077
+ font-weight: 500;
1078
+ cursor: pointer;
1079
+ text-decoration: none;
1080
+ display: inline-flex;
1081
+ align-items: center;
1082
+ justify-content: center;
1083
+ gap: 6px;
1084
+ font-family: inherit;
1085
+ transition: all 0.15s ease;
1086
+ line-height: 1;
1087
+ }
1097
1088
 
1098
- #insights .cards .card .stat table td.value::before {
1099
- content: ': ';
1100
- }
1089
+ .view-screenshot-btn:hover {
1090
+ background-color: var(--accent);
1091
+ color: #ffffff;
1092
+ border-color: var(--accent);
1093
+ }
1101
1094
 
1102
- #locale {
1103
- display: flex;
1104
- gap: 0.2em;
1105
- background: white;
1106
- padding: 1em;
1107
- border-radius: 5px;
1108
- flex-wrap: nowrap;
1109
- }
1095
+ .view-screenshot-btn svg {
1096
+ flex-shrink: 0;
1097
+ }
1110
1098
 
1111
- #locale .title {
1112
- content: ':';
1113
- }
1099
+ /* Terminal Log */
1100
+ .terminal-container {
1101
+ background-color: #0f172a;
1102
+ color: #f8fafc;
1103
+ border-radius: var(--radius);
1104
+ border: 1px solid #1e293b;
1105
+ overflow: hidden;
1106
+ }
1114
1107
 
1115
- #locale .coverage-info {
1116
- width: 100%;
1117
- }
1108
+ .terminal-header {
1109
+ display: flex;
1110
+ align-items: center;
1111
+ justify-content: space-between;
1112
+ padding: 10px 14px;
1113
+ background-color: #1e293b;
1114
+ border-bottom: 1px solid #334155;
1115
+ }
1118
1116
 
1119
- #locale table thead th select.filter {
1120
- margin-left: 1rem;
1121
- max-width: 8rem;
1122
- text-overflow: ellipsis;
1123
- }
1117
+ .terminal-dots {
1118
+ display: flex;
1119
+ gap: 6px;
1120
+ }
1124
1121
 
1125
- #locale .image-viewer {
1126
- display: none;
1127
- position: fixed;
1128
- z-index: 9998;
1129
- top: 0;
1130
- left: 0;
1131
- width: 100%;
1132
- height: 100%;
1133
- background-color: rgba(0, 0, 0, 0.8);
1134
- text-align: center;
1135
- }
1122
+ .terminal-dot {
1123
+ width: 10px;
1124
+ height: 10px;
1125
+ border-radius: 50%;
1126
+ }
1136
1127
 
1137
- #locale .image-container {
1138
- position: relative;
1139
- top: 50%;
1140
- transform: translateY(-50%);
1141
- display: inline-block;
1142
- width: 98vw;
1143
- height: 94vh;
1144
- overflow: hidden;
1145
- overflow-y: auto;
1146
- }
1128
+ .dot-close { background-color: #ef4444; }
1129
+ .dot-min { background-color: #f59e0b; }
1130
+ .dot-max { background-color: #10b981; }
1131
+
1132
+ .terminal-title {
1133
+ display: flex;
1134
+ align-items: center;
1135
+ gap: 6px;
1136
+ font-size: 12px;
1137
+ font-weight: 500;
1138
+ color: #94a3b8;
1139
+ }
1147
1140
 
1148
- #locale .image-viewer img {
1149
- width: 100%;
1150
- }
1141
+ .terminal-actions {
1142
+ display: flex;
1143
+ align-items: center;
1144
+ gap: 8px;
1145
+ }
1151
1146
 
1152
- #locale .close-button {
1153
- position: absolute;
1154
- top: -0.6rem;
1155
- right: 0.1rem;
1156
- color: #ffffffbf;
1157
- font-size: 2.4rem;
1158
- cursor: pointer;
1159
- z-index: 9999;
1160
- }
1147
+ .terminal-search {
1148
+ background-color: #0f172a;
1149
+ border: 1px solid #334155;
1150
+ color: #f8fafc;
1151
+ border-radius: 4px;
1152
+ padding: 4px 8px;
1153
+ font-size: 12px;
1154
+ outline: none;
1155
+ }
1161
1156
 
1162
- #locale .close-button:hover {
1163
- color: white;
1164
- }
1157
+ .terminal-copy-btn {
1158
+ background-color: #334155;
1159
+ border: none;
1160
+ color: #f8fafc;
1161
+ border-radius: 4px;
1162
+ padding: 4px 10px;
1163
+ font-size: 12px;
1164
+ cursor: pointer;
1165
+ display: inline-flex;
1166
+ align-items: center;
1167
+ gap: 4px;
1168
+ font-family: inherit;
1169
+ transition: background 0.15s;
1170
+ }
1165
1171
 
1166
- #locale table tbody td {
1167
- font-size: 0.9em;
1168
- }
1172
+ .terminal-copy-btn:hover {
1173
+ background-color: #475569;
1174
+ }
1169
1175
 
1170
- #locale table td .view-screenshot-btn {
1171
- color: blue;
1172
- }
1176
+ .log-content pre {
1177
+ padding: 16px;
1178
+ margin: 0;
1179
+ font-family: 'JetBrains Mono', monospace;
1180
+ font-size: 12.5px;
1181
+ line-height: 1.6;
1182
+ max-height: 600px;
1183
+ overflow-y: auto;
1184
+ color: #38bdf8;
1185
+ white-space: pre-wrap;
1186
+ }
1173
1187
 
1174
- @media (max-width: 768px) {
1175
- .sidebar {
1176
- width: 16rem;
1177
- padding: 10px;
1178
- }
1179
- }
1188
+ .log-badge-info { color: #38bdf8; font-weight: 600; }
1189
+ .log-badge-warn { color: #f59e0b; font-weight: 600; }
1190
+ .log-badge-error { color: #ef4444; font-weight: 600; }
1191
+
1192
+ /* Image Viewer Modal */
1193
+ .image-viewer {
1194
+ display: none;
1195
+ position: fixed;
1196
+ top: 0;
1197
+ left: 0;
1198
+ width: 100vw;
1199
+ height: 100vh;
1200
+ z-index: 99999;
1201
+ }
1180
1202
 
1181
- .--hidden {
1182
- display: none !important;
1183
- visibility: hidden !important;
1184
- }
1203
+ .image-viewer-backdrop {
1204
+ position: absolute;
1205
+ top: 0;
1206
+ left: 0;
1207
+ width: 100%;
1208
+ height: 100%;
1209
+ background: rgba(0, 0, 0, 0.75);
1210
+ backdrop-filter: blur(4px);
1211
+ cursor: pointer;
1212
+ }
1185
1213
 
1186
- #log {
1187
- display: flex;
1188
- }
1214
+ .image-container {
1215
+ position: absolute;
1216
+ top: 50%;
1217
+ left: 50%;
1218
+ transform: translate(-50%, -50%);
1219
+ background-color: var(--bg-card);
1220
+ border: 1px solid var(--border);
1221
+ border-radius: 10px;
1222
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
1223
+ width: 95vw;
1224
+ height: 92vh;
1225
+ max-width: 96vw;
1226
+ max-height: 94vh;
1227
+ overflow: hidden;
1228
+ display: flex;
1229
+ flex-direction: column;
1230
+ z-index: 100000;
1231
+ }
1189
1232
 
1190
- #log .title {
1191
- display: block;
1192
- flex: 1;
1193
- }
1233
+ .image-viewer-header {
1234
+ display: flex;
1235
+ justify-content: space-between;
1236
+ align-items: center;
1237
+ padding: 8px 16px;
1238
+ border-bottom: 1px solid var(--border);
1239
+ background-color: var(--bg-card);
1240
+ flex-shrink: 0;
1241
+ }
1194
1242
 
1195
- #log .log-content {
1196
- flex: 99;
1197
- background: white;
1198
- border-radius: 3px;
1199
- overflow: hidden;
1200
- padding: 1em;
1201
- }
1243
+ .image-viewer-title {
1244
+ font-size: 14px;
1245
+ font-weight: 600;
1246
+ color: var(--foreground);
1247
+ }
1202
1248
 
1203
- #log .log-content pre {
1204
- height: 100%;
1205
- white-space: pre-line;
1206
- word-break: break-all;
1207
- padding: 0;
1208
- margin: 0;
1209
- width: 100%;
1210
- overflow: hidden;
1211
- overflow-y: auto;
1212
- user-select: all;
1213
- }
1249
+ .close-button {
1250
+ background: var(--muted-bg);
1251
+ border: 1px solid var(--border);
1252
+ border-radius: 6px;
1253
+ width: 30px;
1254
+ height: 30px;
1255
+ display: inline-flex;
1256
+ align-items: center;
1257
+ justify-content: center;
1258
+ font-size: 20px;
1259
+ cursor: pointer;
1260
+ color: var(--foreground);
1261
+ line-height: 1;
1262
+ transition: all 0.15s ease;
1263
+ }
1214
1264
 
1215
- body .context-image-viewer {
1216
- z-index: 9999;
1217
- width: 100vw;
1218
- height: 100vh;
1219
- display: flex;
1220
- flex-direction: column;
1221
- position: fixed;
1222
- top: 0;
1223
- left: 0;
1224
- background: #0000009c;
1225
- }
1265
+ .close-button:hover {
1266
+ background-color: #ef4444;
1267
+ color: #ffffff;
1268
+ border-color: #ef4444;
1269
+ }
1226
1270
 
1227
- body .context-image-viewer .close-btn {
1228
- position: absolute;
1229
- right: 1.2%;
1230
- top: 0.65%;
1231
- color: #a7a5a5;
1232
- font-size: 2.8em;
1233
- cursor: pointer;
1234
- z-index: 1;
1235
- }
1271
+ .image-viewer-body {
1272
+ flex: 1;
1273
+ padding: 10px;
1274
+ overflow: auto;
1275
+ background-color: #0b0f19;
1276
+ display: flex;
1277
+ justify-content: center;
1278
+ align-items: flex-start;
1279
+ }
1236
1280
 
1237
- body .context-image-viewer .close-btn:hover {
1238
- color: #000000a6;
1239
- transform: scale(1.04);
1240
- transition: all 0.15s ease-in-out;
1241
- }
1281
+ .image-viewer-body img {
1282
+ max-width: 100%;
1283
+ height: auto;
1284
+ object-fit: contain;
1285
+ border-radius: 4px;
1286
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
1287
+ }
1242
1288
 
1243
- body .context-image-viewer .loader {
1244
- width: 100vw;
1245
- height: 100vh;
1246
- z-index: 9999;
1247
- top: 0;
1248
- left: 0;
1249
- position: absolute;
1250
- background: #0000009c;
1251
- color: white;
1252
- text-align: center;
1253
- padding-top: 50vh;
1254
- }
1289
+ /* Context Pages & Modal Viewer Styles (Theme-compatible) */
1290
+ #overview .common-info {
1291
+ background-color: var(--bg-card);
1292
+ border: 1px solid var(--border);
1293
+ border-radius: 8px;
1294
+ padding: 20px;
1295
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
1296
+ margin-bottom: 20px;
1297
+ display: flex;
1298
+ flex-direction: column;
1299
+ }
1255
1300
 
1256
- body .context-image-viewer .viewer {
1257
- width: 98%;
1258
- height: 96%;
1259
- background-color: white;
1260
- margin: auto;
1261
- position: relative;
1262
- }
1301
+ #overview .common-info .title {
1302
+ font-size: 16px;
1303
+ font-weight: 700;
1304
+ color: var(--foreground);
1305
+ margin-bottom: 6px;
1306
+ display: block;
1307
+ }
1263
1308
 
1264
- body .context-image-viewer .viewer .zoom-in-btn,
1265
- body .context-image-viewer .viewer .zoom-out-btn {
1266
- position: absolute;
1267
- bottom: 10%;
1268
- width: 35px;
1269
- height: 35px;
1270
- border-radius: 50%;
1271
- text-align: center;
1272
- background: #0000001a;
1273
- cursor: pointer;
1274
- }
1309
+ #overview .common-info .info {
1310
+ font-size: 13.5px;
1311
+ color: var(--text-muted);
1312
+ line-height: 1.6;
1313
+ margin: 0 0 16px 0;
1314
+ }
1275
1315
 
1276
- body .context-image-viewer .viewer .zoom-in-btn {
1277
- left: 51%;
1278
- }
1316
+ #overview .common-info .info strong {
1317
+ color: var(--foreground);
1318
+ }
1279
1319
 
1280
- body .context-image-viewer .viewer .zoom-out-btn {
1281
- left: 47%;
1282
- }
1320
+ #overview .common-info .section {
1321
+ flex: 1;
1322
+ width: 100%;
1323
+ }
1283
1324
 
1284
- body .context-image-viewer .viewer .next-btn,
1285
- body .context-image-viewer .viewer .prev-btn {
1286
- width: 35px;
1287
- height: 35px;
1288
- border-radius: 50%;
1289
- text-align: center;
1290
- background: #0000001a;
1291
- cursor: pointer;
1292
- position: absolute;
1293
- top: 50%;
1294
- }
1325
+ .page-tiles {
1326
+ display: flex;
1327
+ flex-direction: column;
1328
+ width: 100%;
1329
+ padding-top: 14px;
1330
+ border-top: 1px solid var(--border);
1331
+ }
1295
1332
 
1296
- body .context-image-viewer .viewer .zoom-in-btn:hover,
1297
- body .context-image-viewer .viewer .zoom-out-btn:hover {
1298
- transform: scale(1.04);
1299
- transition: all 0.15s ease-in-out;
1300
- }
1333
+ .page-tiles .title-section {
1334
+ display: flex;
1335
+ flex-direction: row;
1336
+ align-items: center;
1337
+ justify-content: space-between;
1338
+ flex-wrap: wrap;
1339
+ gap: 14px;
1340
+ margin-bottom: 18px;
1341
+ }
1301
1342
 
1302
- body .context-image-viewer .viewer .zoom-in-btn span,
1303
- body .context-image-viewer .viewer .zoom-out-btn span {
1304
- display: inline-block;
1305
- margin-top: 12%;
1306
- font-size: 1.5em;
1307
- }
1343
+ .page-tiles .title-section .title-wrapper {
1344
+ flex: 1;
1345
+ min-width: 140px;
1346
+ }
1308
1347
 
1309
- body .context-image-viewer .viewer .next-btn:hover,
1310
- body .context-image-viewer .viewer .prev-btn:hover {
1311
- transform: scale(1.04);
1312
- transition: all 0.15s ease-in-out;
1313
- }
1348
+ .page-tiles .title-section .title-wrapper .title {
1349
+ font-size: 15px;
1350
+ font-weight: 700;
1351
+ color: var(--foreground);
1352
+ }
1314
1353
 
1315
- body .context-image-viewer .viewer .next-btn span,
1316
- body .context-image-viewer .viewer .prev-btn span {
1317
- display: inline-block;
1318
- margin-top: 15%;
1319
- font-size: 1.5em;
1320
- }
1354
+ .page-tiles .title-section .search-field-wrapper {
1355
+ display: flex;
1356
+ align-items: center;
1357
+ gap: 8px;
1358
+ font-size: 13px;
1359
+ color: var(--text-muted);
1360
+ }
1321
1361
 
1322
- body .context-image-viewer .viewer .prev-btn {
1323
- left: 1%;
1324
- }
1362
+ .page-tiles .title-section .search-field-wrapper label {
1363
+ font-weight: 500;
1364
+ color: var(--text-muted);
1365
+ white-space: nowrap;
1366
+ }
1325
1367
 
1326
- body .context-image-viewer .viewer .next-btn {
1327
- right: 1%;
1328
- }
1368
+ .page-tiles .title-section .search-field-wrapper #operator-filter {
1369
+ padding: 5px 10px;
1370
+ border: 1px solid var(--border);
1371
+ border-radius: 6px;
1372
+ background-color: var(--bg-card);
1373
+ color: var(--foreground);
1374
+ font-size: 13px;
1375
+ outline: none;
1376
+ cursor: pointer;
1377
+ }
1329
1378
 
1330
- body .context-image-viewer .viewer .wrapper {
1331
- display: flex;
1332
- flex-direction: column;
1333
- width: 100%;
1334
- height: 100%;
1335
- padding: 1.8%;
1336
- }
1379
+ .page-tiles .title-section .search-field-wrapper #search-input {
1380
+ padding: 5px 10px;
1381
+ border: 1px solid var(--border);
1382
+ border-radius: 6px;
1383
+ background-color: var(--bg-card);
1384
+ color: var(--foreground);
1385
+ font-size: 13px;
1386
+ width: 220px;
1387
+ outline: none;
1388
+ }
1337
1389
 
1338
- body .context-image-viewer .viewer .wrapper .toolbar .page-title-wrapper .page-title {
1339
- font-weight: 600;
1340
- max-width: 75%;
1341
- white-space: nowrap;
1342
- overflow: hidden;
1343
- text-overflow: ellipsis;
1344
- }
1390
+ .page-tiles .title-section .search-field-wrapper #search-input:focus,
1391
+ .page-tiles .title-section .search-field-wrapper #operator-filter:focus,
1392
+ .page-tiles .title-section .locale-filter-wrapper #locale-filter:focus {
1393
+ border-color: var(--accent);
1394
+ }
1345
1395
 
1346
- body .context-image-viewer .viewer .wrapper .toolbar .page-title-wrapper .page-count {
1347
- font-size: 0.7em;
1348
- }
1396
+ .page-tiles .title-section .locale-filter-wrapper {
1397
+ display: flex;
1398
+ align-items: center;
1399
+ gap: 8px;
1400
+ font-size: 13px;
1401
+ color: var(--text-muted);
1402
+ }
1349
1403
 
1350
- body #overview .section .page-tiles .search-field-wrapper #search-input {
1351
- width: 55%;
1352
- height: 1.5em;
1353
- margin-left: 0.5%;
1354
- white-space: nowrap;
1355
- text-overflow: ellipsis;
1356
- border-radius: 3px;
1357
- border: 0.1px solid;
1358
- }
1404
+ .page-tiles .title-section .locale-filter-wrapper label {
1405
+ font-weight: 500;
1406
+ color: var(--text-muted);
1407
+ white-space: nowrap;
1408
+ }
1359
1409
 
1360
- body #overview .section .page-tiles .search-field-wrapper #operator-filter {
1361
- width: fit-content;
1362
- height: 1.5em;
1363
- border-radius: 3px;
1364
- }
1410
+ .page-tiles .title-section .locale-filter-wrapper #locale-filter {
1411
+ padding: 5px 10px;
1412
+ border: 1px solid var(--border);
1413
+ border-radius: 6px;
1414
+ background-color: var(--bg-card);
1415
+ color: var(--foreground);
1416
+ font-size: 13px;
1417
+ outline: none;
1418
+ cursor: pointer;
1419
+ }
1365
1420
 
1366
- body #overview .section .page-tiles .search-field-wrapper {
1367
- flex: 33;
1368
- display: flex;
1369
- align-items: center;
1370
- gap: 1%;
1371
- }
1421
+ .page-tiles .tiles-list-wrapper {
1422
+ width: 100%;
1423
+ overflow-y: auto;
1424
+ padding: 4px 0 20px 0;
1425
+ }
1372
1426
 
1373
- body .context-image-viewer .viewer .wrapper .toolbar .smart-compare-wrapper .switch-wrapper .switch-knob {
1374
- position: absolute;
1375
- width: 40%;
1376
- height: 86%;
1377
- border-radius: 50%;
1378
- background-color: white;
1379
- top: 50%;
1380
- left: 3%;
1381
- transform: translateY(-50%);
1382
- transition: left 0.3s;
1383
- }
1427
+ .page-tiles .tiles-list {
1428
+ display: grid;
1429
+ grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
1430
+ gap: 16px;
1431
+ width: 100%;
1432
+ }
1384
1433
 
1385
- body .context-image-viewer .viewer .wrapper .toolbar .smart-compare-wrapper .switch-wrapper {
1386
- position: relative;
1387
- width: 2.5em;
1388
- height: 1.3em;
1389
- border-radius: 2em;
1390
- background-color: gray;
1391
- cursor: pointer;
1392
- }
1434
+ .page-tiles .tiles-list .empty-context {
1435
+ grid-column: 1 / -1;
1436
+ text-align: center;
1437
+ padding: 40px 20px;
1438
+ color: var(--text-muted);
1439
+ font-size: 14px;
1440
+ font-weight: 500;
1441
+ }
1393
1442
 
1394
- body .context-image-viewer .viewer .wrapper .toolbar .smart-compare-wrapper {
1395
- display: flex;
1396
- align-items: center;
1397
- gap: 1%;
1398
- flex: 33;
1399
- justify-content: end;
1400
- }
1443
+ .page-tiles .tiles-list .tile-container {
1444
+ display: flex;
1445
+ flex-direction: column;
1446
+ background-color: var(--bg-card);
1447
+ border: 1px solid var(--border);
1448
+ border-radius: 8px;
1449
+ overflow: hidden;
1450
+ cursor: pointer;
1451
+ transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
1452
+ height: 190px;
1453
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
1454
+ }
1401
1455
 
1402
- body .context-image-viewer .viewer .wrapper .toolbar .page-title-wrapper {
1403
- display: flex;
1404
- flex-direction: column;
1405
- overflow: hidden;
1406
- flex: 33;
1407
- }
1456
+ .page-tiles .tiles-list .tile-container:hover {
1457
+ border-color: var(--accent);
1458
+ transform: translateY(-2px);
1459
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
1460
+ }
1408
1461
 
1409
- body .context-image-viewer .viewer .wrapper .image-section .split-view .source-image-wrapper .locale-name-bar span,
1410
- body .context-image-viewer .viewer .wrapper .image-section .split-view .target-image-wrapper .locale-name-bar span {
1411
- opacity: 0.6;
1412
- }
1462
+ .page-tiles .tiles-list .tile-container .image {
1463
+ width: 100%;
1464
+ height: 148px;
1465
+ object-fit: cover;
1466
+ background-color: rgba(100, 116, 139, 0.08);
1467
+ display: block;
1468
+ }
1413
1469
 
1414
- body .context-image-viewer .viewer .wrapper .image-section .split-view .source-image-wrapper .locale-name-bar,
1415
- body .context-image-viewer .viewer .wrapper .image-section .split-view .target-image-wrapper .locale-name-bar {
1416
- position: absolute;
1417
- background-color: #8080801f;
1418
- width: 9%;
1419
- height: 3.5%;
1420
- text-align: center;
1421
- margin: auto;
1422
- overflow: hidden;
1423
- text-overflow: ellipsis;
1424
- white-space: nowrap;
1425
- padding: 0.5em;
1426
- bottom: 2.1rem;
1427
- left: 2rem;
1428
- border-radius: 3em;
1429
- color: #00000099;
1430
- font: status-bar;
1431
- font-weight: 500;
1432
- }
1470
+ .page-tiles .tiles-list .tile-container .name {
1471
+ display: flex;
1472
+ height: 42px;
1473
+ border-top: 1px solid var(--border);
1474
+ align-items: center;
1475
+ padding: 0 10px;
1476
+ background-color: var(--bg-card);
1477
+ box-sizing: border-box;
1478
+ }
1433
1479
 
1434
- body .context-image-viewer .viewer .wrapper .image-section .split-view .source-image-wrapper,
1435
- body .context-image-viewer .viewer .wrapper .image-section .split-view .target-image-wrapper {
1436
- width: 100%;
1437
- height: 100%;
1438
- overflow: hidden;
1439
- flex: 1;
1440
- display: flex;
1441
- justify-content: center;
1442
- align-items: center;
1443
- border: 0.1px solid #00000021;
1444
- border-radius: 5px;
1445
- }
1480
+ .page-tiles .tiles-list .tile-container .name span {
1481
+ white-space: nowrap;
1482
+ overflow: hidden;
1483
+ text-overflow: ellipsis;
1484
+ font-size: 12px;
1485
+ font-weight: 600;
1486
+ color: var(--foreground);
1487
+ letter-spacing: 0.2px;
1488
+ }
1446
1489
 
1447
- body .context-image-viewer .viewer .wrapper .image-section .split-view .source-image-wrapper img,
1448
- body .context-image-viewer .viewer .wrapper .image-section .split-view .target-image-wrapper img {
1449
- max-width: 100%;
1450
- max-height: 100%;
1451
- object-fit: contain;
1452
- transform: translate(0, 0) scale(1);
1453
- transition: transform 0.1s ease-out;
1454
- pointer-events: none;
1455
- }
1490
+ /* Modal Context Image Viewer */
1491
+ body .context-image-viewer {
1492
+ z-index: 99999;
1493
+ width: 100vw;
1494
+ height: 100vh;
1495
+ display: flex;
1496
+ flex-direction: column;
1497
+ top: 0;
1498
+ left: 0;
1499
+ background: rgba(0, 0, 0, 0.82);
1500
+ position: fixed;
1501
+ backdrop-filter: blur(4px);
1502
+ box-sizing: border-box;
1503
+ }
1456
1504
 
1457
- body .context-image-viewer .viewer .wrapper .image-section .split-view {
1458
- width: 100%;
1459
- height: 100%;
1460
- display: flex;
1461
- gap: 0.5%;
1462
- }
1505
+ body .context-image-viewer .close-btn {
1506
+ position: absolute;
1507
+ right: 20px;
1508
+ top: 14px;
1509
+ color: #cbd5e1;
1510
+ font-size: 34px;
1511
+ line-height: 1;
1512
+ cursor: pointer;
1513
+ z-index: 100000;
1514
+ transition: all 0.15s ease;
1515
+ }
1463
1516
 
1464
- body .context-image-viewer .viewer .wrapper .image-section {
1465
- display: flex;
1466
- flex: 95;
1467
- overflow: hidden;
1468
- width: 100%;
1469
- height: 100%;
1470
- }
1517
+ body .context-image-viewer .close-btn:hover {
1518
+ color: #ffffff;
1519
+ transform: scale(1.1);
1520
+ }
1471
1521
 
1472
- body .context-image-viewer .viewer .wrapper .toolbar {
1473
- border: 0.1px solid #00000021;
1474
- border-bottom: 0;
1475
- height: 7%;
1476
- border-radius: 5px;
1477
- padding: 0.5%;
1478
- padding-left: 1%;
1479
- padding-right: 1%;
1480
- display: flex;
1481
- flex-direction: row;
1482
- align-items: center;
1483
- justify-content: stretch;
1484
- flex: 4;
1485
- }
1522
+ body .context-image-viewer .loader {
1523
+ width: 100vw;
1524
+ height: 100vh;
1525
+ position: absolute;
1526
+ z-index: 100001;
1527
+ top: 0;
1528
+ left: 0;
1529
+ color: #ffffff;
1530
+ text-align: center;
1531
+ display: flex;
1532
+ align-items: center;
1533
+ justify-content: center;
1534
+ font-size: 16px;
1535
+ font-weight: 600;
1536
+ background: rgba(0, 0, 0, 0.5);
1537
+ }
1486
1538
 
1487
- body .dt-layout-row:first-of-type .dt-layout-cell {
1488
- display: table-cell;
1489
- width: 33.33%;
1490
- vertical-align: middle;
1491
- text-align: center;
1492
- padding: 8px;
1493
- }
1494
-
1495
- body .dt-layout-row:first-of-type .dt-layout-cell.dt-middle {
1496
- text-align: right;
1497
- }
1498
-
1499
- body .dt-layout-row:first-of-type .reset-filters-btn {
1500
- background-color: #555;
1501
- color: white;
1502
- border: none;
1503
- padding: 8px 16px;
1504
- font-size: 14px;
1505
- cursor: pointer;
1506
- border-radius: 4px;
1507
- transition: background-color 0.3s ease;
1508
- }
1539
+ body .context-image-viewer .viewer {
1540
+ width: 96%;
1541
+ height: 94%;
1542
+ background-color: var(--bg-card, #ffffff);
1543
+ color: var(--foreground, #0f172a);
1544
+ margin: auto;
1545
+ position: relative;
1546
+ border-radius: 12px;
1547
+ overflow: hidden;
1548
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
1549
+ display: flex;
1550
+ flex-direction: column;
1551
+ }
1509
1552
 
1510
- .--reduced-zoom {
1511
- zoom: 0.9123;
1512
- }
1553
+ body .context-image-viewer .viewer .wrapper {
1554
+ display: flex;
1555
+ flex-direction: column;
1556
+ width: 100%;
1557
+ height: 100%;
1558
+ overflow: hidden;
1559
+ }
1513
1560
 
1514
- .--hide-overflow {
1515
- overflow: hidden;
1516
- }
1561
+ body .context-image-viewer .viewer .prev-btn,
1562
+ body .context-image-viewer .viewer .next-btn {
1563
+ width: 44px;
1564
+ height: 44px;
1565
+ border-radius: 50%;
1566
+ display: flex;
1567
+ align-items: center;
1568
+ justify-content: center;
1569
+ background: rgba(0, 0, 0, 0.55);
1570
+ color: #ffffff;
1571
+ cursor: pointer;
1572
+ position: absolute;
1573
+ top: 50%;
1574
+ transform: translateY(-50%);
1575
+ z-index: 100;
1576
+ transition: all 0.15s ease;
1577
+ user-select: none;
1578
+ }
1517
1579
 
1518
- .--disabled {
1519
- color: #00000014 !important;
1520
- background: #00000014 !important;
1521
- cursor: not-allowed !important;
1522
- transform: none !important;
1523
- transition: none !important;
1524
- }
1580
+ body .context-image-viewer .viewer .prev-btn { left: 16px; }
1581
+ body .context-image-viewer .viewer .next-btn { right: 16px; }
1582
+
1583
+ body .context-image-viewer .viewer .prev-btn:hover,
1584
+ body .context-image-viewer .viewer .next-btn:hover {
1585
+ background: rgba(0, 0, 0, 0.85);
1586
+ transform: translateY(-50%) scale(1.1);
1587
+ }
1588
+
1589
+ body .context-image-viewer .viewer .prev-btn span,
1590
+ body .context-image-viewer .viewer .next-btn span {
1591
+ font-size: 22px;
1592
+ font-weight: 300;
1593
+ line-height: 1;
1594
+ }
1595
+
1596
+ body .context-image-viewer .viewer .zoom-in-btn,
1597
+ body .context-image-viewer .viewer .zoom-out-btn {
1598
+ position: absolute;
1599
+ bottom: 20px;
1600
+ width: 38px;
1601
+ height: 38px;
1602
+ border-radius: 50%;
1603
+ display: flex;
1604
+ align-items: center;
1605
+ justify-content: center;
1606
+ background: rgba(0, 0, 0, 0.6);
1607
+ color: #ffffff;
1608
+ cursor: pointer;
1609
+ z-index: 100;
1610
+ transition: all 0.15s ease;
1611
+ user-select: none;
1612
+ }
1613
+
1614
+ body .context-image-viewer .viewer .zoom-out-btn { left: calc(50% - 46px); }
1615
+ body .context-image-viewer .viewer .zoom-in-btn { left: calc(50% + 8px); }
1616
+
1617
+ body .context-image-viewer .viewer .zoom-in-btn:hover,
1618
+ body .context-image-viewer .viewer .zoom-out-btn:hover {
1619
+ background: rgba(0, 0, 0, 0.85);
1620
+ transform: scale(1.1);
1621
+ }
1622
+
1623
+ body .context-image-viewer .viewer .zoom-in-btn span,
1624
+ body .context-image-viewer .viewer .zoom-out-btn span {
1625
+ font-size: 20px;
1626
+ font-weight: 400;
1627
+ line-height: 1;
1628
+ }
1629
+
1630
+ body .context-image-viewer .viewer .wrapper .toolbar {
1631
+ border-bottom: 1px solid var(--border);
1632
+ background-color: var(--bg-card);
1633
+ height: 52px;
1634
+ padding: 0 20px;
1635
+ display: flex;
1636
+ flex-direction: row;
1637
+ align-items: center;
1638
+ justify-content: space-between;
1639
+ flex-shrink: 0;
1640
+ gap: 16px;
1641
+ }
1642
+
1643
+ body .context-image-viewer .viewer .wrapper .toolbar .page-title-wrapper {
1644
+ display: flex;
1645
+ align-items: center;
1646
+ gap: 10px;
1647
+ overflow: hidden;
1648
+ flex: 1;
1649
+ }
1650
+
1651
+ body .context-image-viewer .viewer .wrapper .toolbar .page-title-wrapper .page-count {
1652
+ font-size: 12px;
1653
+ font-weight: 700;
1654
+ color: var(--accent);
1655
+ background: rgba(234, 88, 12, 0.1);
1656
+ padding: 3px 8px;
1657
+ border-radius: 4px;
1658
+ white-space: nowrap;
1659
+ }
1660
+
1661
+ body .context-image-viewer .viewer .wrapper .toolbar .page-title-wrapper .page-title {
1662
+ font-size: 14.5px;
1663
+ font-weight: 600;
1664
+ color: var(--foreground);
1665
+ white-space: nowrap;
1666
+ overflow: hidden;
1667
+ text-overflow: ellipsis;
1668
+ }
1669
+
1670
+ body .context-image-viewer .viewer .wrapper .toolbar .context-switcher-wrapper {
1671
+ display: flex;
1672
+ align-items: center;
1673
+ gap: 8px;
1674
+ font-size: 13px;
1675
+ color: var(--text-muted);
1676
+ }
1677
+
1678
+ body .context-image-viewer .viewer .wrapper .toolbar .context-switcher-wrapper label {
1679
+ white-space: nowrap;
1680
+ }
1681
+
1682
+ body .context-image-viewer .viewer .wrapper .toolbar .context-switcher-wrapper select.context-dropdown {
1683
+ padding: 4px 10px;
1684
+ border: 1px solid var(--border);
1685
+ border-radius: 6px;
1686
+ background-color: var(--bg-card);
1687
+ color: var(--foreground);
1688
+ font-size: 13px;
1689
+ max-width: 260px;
1690
+ outline: none;
1691
+ cursor: pointer;
1692
+ }
1693
+
1694
+ body .context-image-viewer .viewer .wrapper .toolbar .smart-compare-wrapper {
1695
+ display: flex;
1696
+ align-items: center;
1697
+ gap: 8px;
1698
+ font-size: 13px;
1699
+ color: var(--text-muted);
1700
+ justify-content: flex-end;
1701
+ }
1702
+
1703
+ body .context-image-viewer .viewer .wrapper .toolbar .smart-compare-wrapper .switch-wrapper {
1704
+ position: relative;
1705
+ width: 40px;
1706
+ height: 22px;
1707
+ border-radius: 20px;
1708
+ background-color: #cbd5e1;
1709
+ cursor: pointer;
1710
+ transition: background-color 0.2s ease;
1711
+ }
1712
+
1713
+ body .context-image-viewer .viewer .wrapper .toolbar .smart-compare-wrapper .switch-wrapper .switch-knob {
1714
+ position: absolute;
1715
+ width: 16px;
1716
+ height: 16px;
1717
+ border-radius: 50%;
1718
+ background-color: #ffffff;
1719
+ top: 3px;
1720
+ left: 4px;
1721
+ transition: left 0.2s ease;
1722
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
1723
+ }
1724
+
1725
+ body .context-image-viewer .viewer .wrapper .image-section {
1726
+ display: flex;
1727
+ flex: 1;
1728
+ overflow: hidden;
1729
+ width: 100%;
1730
+ height: calc(100% - 52px);
1731
+ background-color: var(--bg-body);
1732
+ position: relative;
1733
+ }
1734
+
1735
+ body .context-image-viewer .viewer .wrapper .image-section .split-view {
1736
+ width: 100%;
1737
+ height: 100%;
1738
+ display: flex;
1739
+ gap: 12px;
1740
+ padding: 14px;
1741
+ box-sizing: border-box;
1742
+ }
1743
+
1744
+ body .context-image-viewer .viewer .wrapper .image-section .split-view .source-image-wrapper,
1745
+ body .context-image-viewer .viewer .wrapper .image-section .split-view .target-image-wrapper {
1746
+ width: 100%;
1747
+ height: 100%;
1748
+ overflow: hidden;
1749
+ flex: 1;
1750
+ display: flex;
1751
+ align-items: center;
1752
+ justify-content: center;
1753
+ border: 1px solid var(--border);
1754
+ border-radius: 8px;
1755
+ background-color: var(--bg-card);
1756
+ position: relative;
1757
+ }
1758
+
1759
+ body .context-image-viewer .viewer .wrapper .image-section .split-view .source-image-wrapper img,
1760
+ body .context-image-viewer .viewer .wrapper .image-section .split-view .target-image-wrapper img {
1761
+ max-width: 100%;
1762
+ max-height: 100%;
1763
+ object-fit: contain;
1764
+ transform: translate(0, 0) scale(1);
1765
+ transition: transform 0.1s ease-out;
1766
+ pointer-events: none;
1767
+ }
1768
+
1769
+ body .context-image-viewer .viewer .wrapper .image-section .split-view .source-image-wrapper .locale-name-bar,
1770
+ body .context-image-viewer .viewer .wrapper .image-section .split-view .target-image-wrapper .locale-name-bar {
1771
+ position: absolute;
1772
+ top: 12px;
1773
+ left: 12px;
1774
+ background-color: rgba(15, 23, 42, 0.75);
1775
+ color: #ffffff;
1776
+ padding: 4px 10px;
1777
+ border-radius: 4px;
1778
+ font-size: 11.5px;
1779
+ font-weight: 600;
1780
+ letter-spacing: 0.5px;
1781
+ z-index: 5;
1782
+ pointer-events: none;
1783
+ }
1784
+
1785
+ body .context-image-viewer .viewer .wrapper .image-section .split-view .source-image-wrapper .locale-name-bar span,
1786
+ body .context-image-viewer .viewer .wrapper .image-section .split-view .target-image-wrapper .locale-name-bar span {
1787
+ opacity: 0.95;
1788
+ }
1525
1789
 
1526
- .--disabled:hover {
1527
- color: #00000014 !important;
1528
- background: #00000014 !important;
1529
- transform: none !important;
1530
- transition: none !important;
1531
- }`;
1790
+ .--hidden {
1791
+ display: none !important;
1792
+ }
1793
+
1794
+ .--disabled {
1795
+ opacity: 0.3 !important;
1796
+ cursor: not-allowed !important;
1797
+ pointer-events: none !important;
1798
+ }
1799
+
1800
+ /* ApexCharts theme adjustments */
1801
+ .apexcharts-tooltip.apexcharts-theme-dark {
1802
+ background: #18181b !important;
1803
+ border: 1px solid #27272a !important;
1804
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
1805
+ }
1806
+
1807
+ .apexcharts-text {
1808
+ fill: var(--text-muted) !important;
1809
+ }
1810
+ `;
1532
1811
  }
1533
1812
  function renderHtml({
1534
1813
  appName,
1535
1814
  reportTime,
1815
+ body,
1536
1816
  script,
1537
1817
  style,
1538
- body,
1539
1818
  dataFilePaths = [],
1540
1819
  logData
1541
1820
  }) {
1821
+ const dataScripts = dataFilePaths.map((v) => '<script src="' + v + '" type="text/javascript"><\/script>').join("\n ");
1822
+ const logScript = logData ? '<script type="text/javascript">window.logData = ' + JSON.stringify(logData) + ";<\/script>" : "";
1542
1823
  return `<!DOCTYPE html>
1543
- <html lang="en">
1824
+ <html lang="en" data-theme="light">
1544
1825
  <head>
1545
1826
  <meta charset="UTF-8" />
1546
1827
  <meta name="charset" content="charset='UTF-8'" />
@@ -1549,177 +1830,153 @@ function renderHtml({
1549
1830
  <meta name="product" content="zAutomate.AI" />
1550
1831
  <meta name="author" content="Jitendra Maheshwari" />
1551
1832
  <meta name="email" content="jm@zeesoft.com" />
1552
- <meta
1553
- name="description"
1554
- content="zAutomate.AI report"
1555
- />
1556
- <title>${appName} - zAutomate.AI report | ${reportTime}</title>
1557
- <!-- 3rd party dependencies -->
1558
- <link
1559
- rel="stylesheet"
1560
- href="https://cdn.datatables.net/2.0.3/css/dataTables.dataTables.min.css"
1561
- />
1562
- ${dataFilePaths.map(
1563
- (v) => `<script
1564
- src="${v}"
1565
- type="text/javascript">
1566
- <\/script>`
1567
- ).join("")}
1568
- ${logData ? `<script type="text/javascript" async/>window.logData = \`${logData}\`;<\/script>` : ""}
1569
- <script
1570
- src="https://code.jquery.com/jquery-3.7.1.slim.min.js"
1571
- integrity="sha256-kmHvs0B+OpCW5GVHUNjv9rOmY0IvSIRcf7zGUDTDQM8="
1572
- crossorigin="anonymous"
1573
- defer
1574
- ><\/script>
1575
- <script src="https://cdn.jsdelivr.net/npm/apexcharts" defer><\/script>
1576
- <script
1577
- src="https://cdn.datatables.net/2.0.3/js/dataTables.min.js"
1578
- defer
1579
- ><\/script>
1580
- <style>
1581
- ${style}
1582
- </style>
1583
- </head>
1584
- <body>
1585
- ${body}
1586
- </body>
1587
- <script type="text/javascript" defer>
1588
- ${script}
1589
- <\/script>
1590
- </html>
1591
- `;
1833
+ <meta name="description" content="` + appName + ' - zAutomate.AI Quality Automation Report" />\n <title>' + appName + " - zAutomate.AI Report | " + reportTime + '</title>\n \n <!-- Google Fonts: Inter, Outfit, JetBrains Mono -->\n <link rel="preconnect" href="https://fonts.googleapis.com" />\n <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />\n <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Outfit:wght@500;600;700;800&display=swap" rel="stylesheet" />\n \n <!-- DataTables CSS -->\n <link rel="stylesheet" href="https://cdn.datatables.net/2.0.3/css/dataTables.dataTables.min.css" />\n \n <!-- Early Theme Detection -->\n <script>\n (function() {\n try {\n var params = new URLSearchParams(window.location.search);\n var themeParam = params.get("theme");\n var storedTheme = localStorage.getItem("zqa_report_theme");\n var systemDark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;\n var activeTheme = themeParam || storedTheme || (systemDark ? "dark" : "light");\n document.documentElement.setAttribute("data-theme", activeTheme);\n if (params.get("standalone") === "false") {\n document.documentElement.classList.add("embedded");\n }\n } catch(e) {}\n })();\n <\/script>\n \n ' + dataScripts + "\n " + logScript + '\n \n <script src="https://code.jquery.com/jquery-3.7.1.slim.min.js" integrity="sha256-kmHvs0B+OpCW5GVHUNjv9rOmY0IvSIRcf7zGUDTDQM8=" crossorigin="anonymous" defer><\/script>\n <script src="https://cdn.jsdelivr.net/npm/apexcharts" defer><\/script>\n <script src="https://cdn.datatables.net/2.0.3/js/dataTables.min.js" defer><\/script>\n <style>\n ' + style + "\n </style>\n </head>\n <body>\n " + body + '\n </body>\n <script type="text/javascript" defer>\n ' + script + "\n <\/script>\n</html>\n";
1592
1834
  }
1593
1835
  const menuBar = () => `(() => {
1594
- // for sidebar menu
1595
- // hide insights tab
1596
- if(DataStore.hasRuntimeError() || !DataStore.ranSuccessfully() || DataStore.isContextRun()) {
1597
- document.querySelector('.menu-item[data-page="insights"]')?.remove();
1598
- }
1599
-
1600
- const loadContent = (section, highlightMenu = false) => {
1601
- if (highlightMenu) {
1602
- document
1603
- .querySelector('li[data-page="overview"]')
1604
- ?.classList.add('selected');
1605
- }
1606
-
1607
- const contents = document.querySelectorAll('.content');
1608
- const wrapper = document.querySelector('.content-wrapper');
1609
-
1610
- contents.forEach((content) => {
1611
- content.id !== section
1612
- ? content.classList.remove('active')
1613
- : content.classList.add('active');
1614
-
1615
- section === 'overview' &&
1616
- window.persistOverviewCharts &&
1617
- window.persistOverviewCharts();
1618
-
1619
- ['log', 'locale'].includes(section) ? wrapper.classList.add('--hide-overflow') : !DataStore.isContextRun() && !DataStore.isSanityRun() && wrapper.classList.remove('--hide-overflow');
1620
- window.currentPage = section;
1621
- });
1622
- };
1623
-
1624
- document.addEventListener('DOMContentLoaded', function () {
1625
- const createMenuItems = (() => {
1626
- if(DataStore.isContextRun()) {
1627
- return;
1628
- }
1629
- const ul = document.querySelector('.sidebar .submenu');
1630
- const createListItems = (locale) => {
1631
- const li = document.createElement('li');
1632
- li.classList.add('sub-menu-item');
1633
- li.dataset.locale = locale;
1634
-
1635
- const a = document.createElement('a');
1636
- a.href = '#';
1637
- a.textContent = locale;
1638
-
1639
- li.appendChild(a);
1640
- return li;
1641
- };
1642
-
1643
- for (const locale of DataStore.getLocales()) {
1644
- ul.appendChild(createListItems(locale));
1645
- }
1646
- })();
1647
-
1648
- const menuItems = document.querySelectorAll('.menu-item'),
1649
- submenuItems = document.querySelectorAll('.sub-menu-item');
1650
-
1651
- menuItems.forEach((item) => {
1652
- item.addEventListener('click', function (event) {
1653
- const selectedMenuItem = document.querySelector(
1654
- '.menu-item.selected'
1655
- ),
1656
- selectedSubmenu = document.querySelector('.submenu.active'),
1657
- page = item.dataset.page;
1836
+ if (DataStore.hasRuntimeError() || !DataStore.ranSuccessfully() || DataStore.isContextRun()) {
1837
+ var insightTab = document.querySelector('#insightsTabDropdown') || document.querySelector('[data-page="insights"]');
1838
+ if (insightTab) insightTab.remove();
1839
+ }
1658
1840
 
1659
- if (selectedMenuItem) {
1660
- selectedMenuItem.classList.remove('selected');
1661
- }
1841
+ var loadContent = function(section, highlightMenu = false) {
1842
+ if (highlightMenu) {
1843
+ document.querySelectorAll('.tab-item').forEach(function(b) { b.classList.remove('selected'); });
1844
+ var ovTab = document.querySelector('.tab-item[data-page="overview"]');
1845
+ if (ovTab) ovTab.classList.add('selected');
1846
+ }
1847
+ var contents = document.querySelectorAll('.content');
1848
+ contents.forEach(function(content) {
1849
+ if (content.id !== section) {
1850
+ content.classList.remove('active');
1851
+ } else {
1852
+ content.classList.add('active');
1853
+ }
1854
+ });
1855
+ if (section === 'overview' && window.persistOverviewCharts) {
1856
+ window.persistOverviewCharts();
1857
+ }
1858
+ window.currentPage = section;
1859
+ };
1662
1860
 
1663
- if (selectedSubmenu) {
1664
- selectedSubmenu.classList.remove('active');
1665
- }
1861
+ document.addEventListener('DOMContentLoaded', function() {
1862
+ if (!DataStore.isContextRun()) {
1863
+ var ul = document.querySelector('.tabs-list .submenu');
1864
+ if (ul) {
1865
+ ul.innerHTML = '';
1866
+ DataStore.getLocales().forEach(function(locale) {
1867
+ var li = document.createElement('li');
1868
+ li.classList.add('sub-menu-item');
1869
+ li.dataset.locale = locale;
1870
+ var a = document.createElement('a');
1871
+ a.href = '#';
1872
+ a.innerHTML = '<span class="locale-code">' + locale + '</span>';
1873
+ li.appendChild(a);
1874
+ ul.appendChild(li);
1875
+ });
1876
+ }
1877
+ }
1666
1878
 
1667
- if (item.classList.contains('has-submenu')) {
1668
- event.preventDefault();
1669
- item.classList.add('selected');
1670
- const submenu = item.querySelector('.submenu');
1671
- submenu.classList.add('active');
1672
- } else {
1673
- item.classList.add('selected');
1674
- }
1879
+ var tabButtons = document.querySelectorAll('.tab-item');
1880
+ tabButtons.forEach(function(btn) {
1881
+ btn.addEventListener('click', function(event) {
1882
+ var page = btn.dataset.page;
1883
+ if (btn.classList.contains('has-submenu')) {
1884
+ event.preventDefault();
1885
+ var submenu = btn.parentElement.querySelector('.submenu');
1886
+ if (submenu) {
1887
+ submenu.classList.toggle('active');
1888
+ }
1889
+ tabButtons.forEach(function(b) { b.classList.remove('selected'); });
1890
+ btn.classList.add('selected');
1891
+ loadContent('insights');
1892
+ } else {
1893
+ tabButtons.forEach(function(b) { b.classList.remove('selected'); });
1894
+ btn.classList.add('selected');
1895
+ var activeSubmenu = document.querySelector('.submenu.active');
1896
+ if (activeSubmenu) activeSubmenu.classList.remove('active');
1897
+ loadContent(page);
1898
+ }
1899
+ });
1900
+ });
1675
1901
 
1676
- if (selectedSubmenu) {
1677
- selectedSubmenu
1678
- .querySelectorAll('.sub-menu-item')
1679
- .forEach((submenuItem) => {
1680
- submenuItem.textContent !== item.textContent &&
1681
- submenuItem.classList.remove('selected');
1682
- });
1683
- }
1902
+ document.addEventListener('click', function(e) {
1903
+ if (!e.target.closest('.tab-dropdown')) {
1904
+ var openSub = document.querySelector('.submenu.active');
1905
+ if (openSub) openSub.classList.remove('active');
1906
+ }
1907
+ });
1684
1908
 
1685
- loadContent(page);
1686
- });
1909
+ document.addEventListener('click', function(e) {
1910
+ var sItem = e.target.closest('.sub-menu-item');
1911
+ if (sItem) {
1912
+ e.preventDefault();
1913
+ e.stopPropagation();
1914
+ var openSub = document.querySelector('.submenu.active');
1915
+ if (openSub) openSub.classList.remove('active');
1916
+ tabButtons.forEach(function(b) { b.classList.remove('selected'); });
1917
+ var insBtn = document.querySelector('.tab-item[data-page="insights"]');
1918
+ if (insBtn) insBtn.classList.add('selected');
1919
+ loadContent('locale');
1920
+ if (window.renderLocaleGrid) {
1921
+ window.renderLocaleGrid(sItem.dataset.locale);
1922
+ }
1923
+ }
1924
+ });
1687
1925
 
1688
- loadContent('overview', true);
1689
- });
1926
+ var backBtn = document.getElementById('backToInsightsBtn');
1927
+ if (backBtn) {
1928
+ backBtn.addEventListener('click', function() {
1929
+ tabButtons.forEach(function(b) { b.classList.remove('selected'); });
1930
+ var insBtn = document.querySelector('.tab-item[data-page="insights"]');
1931
+ if (insBtn) insBtn.classList.add('selected');
1932
+ loadContent('insights');
1933
+ });
1934
+ }
1690
1935
 
1691
- submenuItems.forEach((sItem) => {
1692
- sItem.addEventListener('click', function (event) {
1693
- const selectedSubMenuItem = document.querySelector(
1694
- '.sub-menu-item.selected'
1695
- );
1696
- event.preventDefault();
1697
- event.stopPropagation();
1936
+ var productNameEl = document.getElementById('productName');
1937
+ if (productNameEl) productNameEl.textContent = DataStore.getAppName() || 'Application';
1938
+
1939
+ var modeLabelEl = document.getElementById('modeLabel');
1940
+ var modePillEl = document.getElementById('modePill');
1941
+ if (modeLabelEl && modePillEl) {
1942
+ if (DataStore.isSanityRun()) {
1943
+ modeLabelEl.textContent = 'Quick Sanity';
1944
+ modePillEl.className = 'mode-pill mode-sanity';
1945
+ } else if (DataStore.isContextRun()) {
1946
+ modeLabelEl.textContent = 'Context Creation';
1947
+ modePillEl.className = 'mode-pill mode-context';
1948
+ } else {
1949
+ modeLabelEl.textContent = 'i18n Verification';
1950
+ modePillEl.className = 'mode-pill mode-i18n';
1951
+ }
1952
+ }
1698
1953
 
1699
- if (selectedSubMenuItem) {
1700
- selectedSubMenuItem.classList.remove('selected');
1701
- window.previousSelectedLocale =
1702
- selectedSubMenuItem.dataset.locale;
1703
- }
1954
+ var statusPillEl = document.getElementById('statusPill');
1955
+ var statusLabelEl = document.getElementById('statusLabel');
1956
+ var hasError = DataStore.hasRuntimeError() || !DataStore.ranSuccessfully();
1957
+ if (statusPillEl && statusLabelEl) {
1958
+ if (hasError) {
1959
+ statusPillEl.className = 'status-pill status-failed';
1960
+ statusLabelEl.textContent = 'Failed';
1961
+ } else {
1962
+ statusPillEl.className = 'status-pill status-passed';
1963
+ statusLabelEl.textContent = 'Passed';
1964
+ }
1965
+ }
1704
1966
 
1705
- sItem.classList.add('selected');
1706
- loadContent('locale');
1707
- });
1708
- });
1967
+ var timestampEl = document.getElementById('reportTimestamp');
1968
+ if (timestampEl) {
1969
+ try {
1970
+ var ts = DataStore.getTimestamp();
1971
+ timestampEl.textContent = ts ? new Date(ts).toLocaleString() : new Date().toLocaleString();
1972
+ } catch(e) {
1973
+ timestampEl.textContent = new Date().toLocaleString();
1974
+ }
1975
+ }
1709
1976
 
1710
- // update footer info
1711
- const footer = document.querySelector('.sidebar .footer');
1712
- footer.textContent = \`\${new Date().getFullYear()} @ Zeesoft. All rights reserved.\`;
1713
-
1714
- // update project info
1715
- document.querySelector(
1716
- 'header .logo'
1717
- ).innerHTML = \`zAutomate.AI | \${DataStore.getAppName()} [\${DataStore.isSanityRun() ? 'Quick Sanity' : DataStore.isContextRun() ? 'Context Creation' : 'I18n Verification'}]\`;
1718
- document.querySelector(
1719
- 'header .report-timestamp .info'
1720
- ).innerHTML = \`Report generated at: \${toLocaleString(Datastore.getTimestamp())}\`;
1721
- });
1722
- })();`;
1977
+ loadContent('overview', true);
1978
+ });
1979
+ })();`;
1723
1980
  const overview = () => `//overview content
1724
1981
  (() => {
1725
1982
  if (DataStore.hasRuntimeError()) {
@@ -2132,6 +2389,12 @@ const overview = () => `//overview content
2132
2389
  targetImageEl.onload = () => {
2133
2390
  hasTargetLoaded = true;
2134
2391
  };
2392
+ sourceImageEl.onerror = () => {
2393
+ showLoader(false);
2394
+ };
2395
+ targetImageEl.onerror = () => {
2396
+ showLoader(false);
2397
+ };
2135
2398
  }
2136
2399
  }
2137
2400
  else {
@@ -2598,6 +2861,18 @@ const overview = () => `//overview content
2598
2861
 
2599
2862
  titleEl.textContent = title;
2600
2863
  infoEl.innerHTML = info;
2864
+ if (DataStore.isSanityRun()) {
2865
+ var sec = document.querySelector('#overview .common-info .section');
2866
+ if (sec) {
2867
+ sec.innerHTML = '';
2868
+ var logBtn = document.createElement('button');
2869
+ logBtn.type = 'button';
2870
+ logBtn.className = 'btn-view-log';
2871
+ logBtn.innerHTML = '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="4 17 10 11 4 5"/><line x1="12" x2="20" y1="19" y2="19"/></svg><span>View Log →</span>';
2872
+ logBtn.addEventListener('click', function() { var lb = document.querySelector('.tab-item[data-page="log"]'); if (lb) lb.click(); });
2873
+ sec.appendChild(logBtn);
2874
+ }
2875
+ }
2601
2876
  }
2602
2877
 
2603
2878
  return;
@@ -3671,6 +3946,9 @@ const localeGrid = () => `// locale grid
3671
3946
  }
3672
3947
 
3673
3948
  document.addEventListener('DOMContentLoaded', function () {
3949
+ document.getElementById('backToInsightsBtn')?.addEventListener('click', function() {
3950
+ document.querySelector('.tab-item[data-page="insights"]')?.click();
3951
+ });
3674
3952
  let table;
3675
3953
  document.querySelectorAll('.sub-menu-item').forEach((menu) => {
3676
3954
  menu.addEventListener('click', (e) => {
@@ -3736,7 +4014,8 @@ const localeGrid = () => `// locale grid
3736
4014
  searchable: false,
3737
4015
  data: null,
3738
4016
  render: function (data) {
3739
- return \`<a href="#" class="view-screenshot-btn" onclick="openImageViewer('\${data[1]}')"><img title="View screenshot for '\${data[0]}'" class="view-screenshot-image"></img></a\`;
4017
+ if (!data || !data[1]) return '<span style="color: var(--text-muted);">-</span>';
4018
+ return \`<a href="javascript:void(0)" class="view-screenshot-btn" data-image="\${data[1]}" onclick="openImageViewer('\${data[1]}')" title="View screenshot for '\${data[0]}'"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg><span>View</span></a>\`;
3740
4019
  },
3741
4020
  className: 'dt-head-center dt-body-center'
3742
4021
  }
@@ -3761,7 +4040,8 @@ const localeGrid = () => `// locale grid
3761
4040
  searchable: false,
3762
4041
  data: null,
3763
4042
  render: function (data) {
3764
- return \`<a href="#" class="view-screenshot-btn" onclick="openImageViewer('\${data[3]}')"><img title="View screenshot for '\${data[2]}'" class="view-screenshot-image"></img></a>\`;
4043
+ if (!data || !data[3]) return '<span style="color: var(--text-muted);">-</span>';
4044
+ return \`<a href="javascript:void(0)" class="view-screenshot-btn" data-image="\${data[3]}" onclick="openImageViewer('\${data[3]}')" title="View screenshot for '\${data[2]}'"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg><span>View</span></a>\`;
3765
4045
  },
3766
4046
  className: 'dt-head-center dt-body-center'
3767
4047
  }
@@ -3867,6 +4147,7 @@ const localeGrid = () => `// locale grid
3867
4147
  };
3868
4148
 
3869
4149
  const render = (locale) => {
4150
+ window.renderLocaleGrid = render;
3870
4151
  if (table) {
3871
4152
  table.destroy();
3872
4153
  }
@@ -3975,62 +4256,172 @@ const data = (metaData) => `// DataStore
3975
4256
  DataStore = new SimpleDataStore();
3976
4257
  })();`;
3977
4258
  const global = () => `var DataStore;
3978
- // global functions
3979
- function openImageViewer(imageSrc) {
3980
- var imageView = document.getElementById('imageView');
3981
- imageView.src = \`\${window.getProductUrl()}/\${imageSrc}\`;
3982
- document.getElementById('imageViewer').style.display = 'block';
3983
- }
4259
+ window.initTheme = function() {
4260
+ try {
4261
+ var params = new URLSearchParams(window.location.search);
4262
+ var themeParam = params.get("theme");
4263
+ var storedTheme = localStorage.getItem("zqa_report_theme");
4264
+ var systemDark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
4265
+ var activeTheme = themeParam || storedTheme || (systemDark ? "dark" : "light");
4266
+ document.documentElement.setAttribute("data-theme", activeTheme);
4267
+ } catch(e) {}
4268
+ };
3984
4269
 
3985
- function closeImageViewer() {
3986
- delete document.getElementById('imageView').src;
3987
- document.getElementById('imageViewer').style.display = 'none';
3988
- }
4270
+ function openImageViewer(imageSrc) {
4271
+ var imageView = document.getElementById("imageView");
4272
+ if (imageView) {
4273
+ imageView.src = window.getProductUrl() + "/" + imageSrc;
4274
+ }
4275
+ var viewer = document.getElementById("imageViewer");
4276
+ if (viewer) {
4277
+ viewer.style.display = "block";
4278
+ }
4279
+ }
3989
4280
 
3990
- document.addEventListener('DOMContentLoaded', () => {
3991
- document.addEventListener('keydown', (e) => {
3992
- const viewer = document.getElementById('imageViewer');
3993
- if (e.key === 'Escape' && viewer && viewer.style.display === 'block') {
3994
- closeImageViewer();
3995
- }
3996
- });
4281
+ function closeImageViewer() {
4282
+ var imageView = document.getElementById("imageView");
4283
+ if (imageView) {
4284
+ imageView.src = "";
4285
+ }
4286
+ var viewer = document.getElementById("imageViewer");
4287
+ if (viewer) {
4288
+ viewer.style.display = "none";
4289
+ }
4290
+ }
4291
+
4292
+ window.openImageViewer = openImageViewer;
4293
+ window.closeImageViewer = closeImageViewer;
4294
+
4295
+ document.addEventListener("DOMContentLoaded", function() {
4296
+ window.initTheme();
4297
+ });
4298
+
4299
+ document.addEventListener('click', function(e) {
4300
+ var btn = e.target.closest('.view-screenshot-btn');
4301
+ if (btn) {
4302
+ e.preventDefault();
4303
+ var imgPath = btn.getAttribute('data-image') || (btn.getAttribute('onclick') && btn.getAttribute('onclick').match(/'([^']+)'/)?.[1]);
4304
+ if (imgPath && typeof window.openImageViewer === 'function') {
4305
+ window.openImageViewer(imgPath);
4306
+ }
4307
+ return;
4308
+ }
4309
+
4310
+ var closeBtn = e.target.closest('.close-button') || (e.target.classList && e.target.classList.contains('image-viewer-backdrop'));
4311
+ if (closeBtn) {
4312
+ e.preventDefault();
4313
+ if (typeof window.closeImageViewer === 'function') {
4314
+ window.closeImageViewer();
4315
+ }
4316
+ }
4317
+ });
4318
+
4319
+ document.addEventListener('keydown', function(e) {
4320
+ if (e.key === 'Escape') {
4321
+ if (typeof window.closeImageViewer === 'function') {
4322
+ window.closeImageViewer();
4323
+ }
4324
+ }
4325
+ });
4326
+
4327
+ window.getProductUrl = function() {
4328
+ if (window.productUrl) {
4329
+ return window.productUrl;
4330
+ }
4331
+ try {
4332
+ var href = window.location.href.split('?')[0].split('#')[0];
4333
+ var dir = href.substring(0, href.lastIndexOf('/'));
4334
+ window.productUrl = dir;
4335
+ return window.productUrl;
4336
+ } catch (e) {
4337
+ var m = window.location.pathname.match(/^.+[^\\/report\\.html]/g);
4338
+ window.productUrl = window.location.protocol + "//" + window.location.host + (m ? m[0] : "");
4339
+ return window.productUrl;
4340
+ }
4341
+ };
4342
+ var params = new URLSearchParams(location.href.match(/(\\?.*$)/g)?.[0] || "");
4343
+ window.isStandaloneReport = params.size ? (params.get("standalone") === "true") : true;
4344
+ `;
4345
+ const log = () => `(() => {
4346
+ document.addEventListener("DOMContentLoaded", function() {
4347
+ var rawLog = window.logData || (DataStore.hasRuntimeError() ? 'We are facing internal issue. Please try again after sometime.' : 'No log data found!');
4348
+ var logPre = document.getElementById("logPre");
4349
+ var copyBtn = document.getElementById("copyLogBtn");
4350
+ var searchInput = document.getElementById("logSearchInput");
4351
+ var currentFilteredText = rawLog;
4352
+
4353
+ var colorizeAndRender = function(filterText) {
4354
+ if (!logPre) return;
4355
+ var lines = rawLog.split("\\n");
4356
+ var filtered = filterText ? lines.filter(function(l) { return l.toLowerCase().indexOf(filterText.toLowerCase()) !== -1; }) : lines;
4357
+ currentFilteredText = filtered.join("\\n");
4358
+ var html = filtered.map(function(line) {
4359
+ var formatted = line.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4360
+ formatted = formatted.replace(/\\[INFO\\]/g, '<span class="log-badge-info">[INFO]</span>');
4361
+ formatted = formatted.replace(/\\[WARN\\]/g, '<span class="log-badge-warn">[WARN]</span>');
4362
+ formatted = formatted.replace(/\\[ERROR\\]/g, '<span class="log-badge-error">[ERROR]</span>');
4363
+ return formatted;
4364
+ }).join("\\n");
4365
+ logPre.innerHTML = html;
4366
+ };
4367
+
4368
+ colorizeAndRender();
4369
+
4370
+ if (searchInput) {
4371
+ searchInput.addEventListener("input", function(e) {
4372
+ colorizeAndRender(e.target.value.trim());
3997
4373
  });
4374
+ }
3998
4375
 
3999
- //to dynamically show/hide header based upon query param: ?standalone=<true|false>
4000
- window.getProductUrl = () => {
4001
- if (window.productUrl) {
4002
- return window.productUrl;
4003
- } else {
4004
- window.productUrl = \`\${window.location.protocol}//\${
4005
- window.location.host
4006
- }\${window.location.pathname.match(/^.+[^\\/report\\.html]/g)?.[0]}\`;
4007
- return window.productUrl;
4008
- }
4376
+ if (copyBtn) {
4377
+ var showCopied = function() {
4378
+ copyBtn.innerHTML = '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2.5"><polyline points="20 6 9 17 4 12"/></svg><span style="color: #10b981;">Copied!</span>';
4379
+ setTimeout(function() {
4380
+ copyBtn.innerHTML = '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg><span>Copy</span>';
4381
+ }, 2000);
4009
4382
  };
4010
- const params = new URLSearchParams(location.href.match(/(\\?.*$)/g)?.[0]);
4011
- if (params.size) {
4012
- window.isStandaloneReport = params.get('standalone') === 'true';
4013
- if(!window.isStandaloneReport) {
4014
- const overview = document.getElementById('overview');
4015
- if(overview) {
4016
- overview.classList.add('--reduced-zoom');
4383
+
4384
+ var fallbackCopy = function(text) {
4385
+ var textArea = document.createElement("textarea");
4386
+ textArea.value = text;
4387
+ textArea.style.position = "fixed";
4388
+ textArea.style.top = "-9999px";
4389
+ textArea.style.left = "-9999px";
4390
+ textArea.style.opacity = "0";
4391
+ textArea.setAttribute("readonly", "");
4392
+ document.body.appendChild(textArea);
4393
+ textArea.focus();
4394
+ textArea.select();
4395
+ textArea.setSelectionRange(0, textArea.value.length);
4396
+ try {
4397
+ var successful = document.execCommand("copy");
4398
+ document.body.removeChild(textArea);
4399
+ if (successful) {
4400
+ showCopied();
4401
+ } else {
4402
+ console.error("document.execCommand copy was unsuccessful");
4017
4403
  }
4404
+ } catch (err) {
4405
+ document.body.removeChild(textArea);
4406
+ console.error("Fallback copy error:", err);
4018
4407
  }
4019
- } else {
4020
- window.isStandaloneReport = true;
4021
- }`;
4022
- const log = () => `// log content
4023
- (() => {
4024
- document.addEventListener('DOMContentLoaded', function () {
4025
- const pre = document.querySelector('#log .log-content pre');
4026
- pre.textContent = 'Loading...';
4027
- document
4028
- .querySelector('li[data-page="log"]')
4029
- ?.addEventListener('click', (e) => {
4030
- pre.textContent = window.logData || (DataStore.hasRuntimeError() ? 'We are facing internal issue. Please try again after sometime.' : 'No log data found!');
4408
+ };
4409
+
4410
+ copyBtn.addEventListener("click", function() {
4411
+ var textToCopy = currentFilteredText || rawLog;
4412
+ if (navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
4413
+ navigator.clipboard.writeText(textToCopy).then(function() {
4414
+ showCopied();
4415
+ }).catch(function() {
4416
+ fallbackCopy(textToCopy);
4031
4417
  });
4418
+ } else {
4419
+ fallbackCopy(textToCopy);
4420
+ }
4032
4421
  });
4033
- })();`;
4422
+ }
4423
+ });
4424
+ })();`;
4034
4425
  const getJsData = (metaData) => `${global()}
4035
4426
  ${data(metaData)}
4036
4427
  ${menuBar()}