CtrlK
BlogDocsLog inGet started
Tessl Logo

tessleng/agent-insight-experiment

Scan a repository to surface actionable findings about agent performance. Analyzes source code, git history, GitHub data, agent logs, and agent context, then synthesizes cross-referenced findings with targeted actions informed by Tessl product awareness. Supports incremental multi-developer contributions and produces a self-contained HTML report.

70

Quality

88%

Does it follow best practices?

Impact

No eval scenarios have been run

SecuritybySnyk

Advisory

Suggest reviewing before use

Overview
Quality
Evals
Security
Files

report-template.htmlreferences/

<!doctype html>
<html lang="en" class="dark">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Tessl | Agent Insights Report</title>
        <!-- Favicon: fixed-color variants per color scheme. The `media` attr
             is honoured by Safari, Firefox, and recent Chromium; the first
             link acts as the default for browsers that ignore `media` on
             icon links. -->
        <link
            rel="icon"
            type="image/svg+xml"
            href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOTIiIGhlaWdodD0iMTkyIiBmaWxsPSJub25lIiB2aWV3Qm94PSIwIDAgMTkyIDE5MiI+PHBhdGggZmlsbD0iIzA5MDkwYiIgZD0iTTU3LjQ2IDgzLjc4MWMuMDAyLTEuNzI0IDEuODc0LTIuNzg2IDMuMzY4LTEuOTM3bDMwLjY0NCAxNy42MXYzOS42MTdjMCA2LjkzMSA3LjU4NyAxMS4yMTIgMTMuNTY2IDcuNjhsMjkuNDQtMTcuNDIydjQzLjMxM2wtMjkuNTI3IDE2Ljk2OWExOC4wMiAxOC4wMiAwIDAgMS0xNy45MzQgMEw1Ny40NiAxNzIuNjQyek0xODIgMTM1LjA5NWExNy44MyAxNy44MyAwIDAgMS04Ljk3MSAxNS40NTNsLTI5LjU0OSAxNi45Njl2LTQzLjUwMUwxODIgMTAxLjIwM3pNNDguNDk3IDEyMy4yNzRoLS4wMjR2NDQuMjJsLTI5LjUwMi0xNi45NDZBMTcuODMgMTcuODMgMCAwIDEgMTAgMTM1LjA5NVYxMDEuMTh6bTEyNC41MDgtODEuNzlhMTcuODMgMTcuODMgMCAwIDEgOC45NzIgMTUuNDUzVjkwLjgybC03OC4xNDMgNDYuMjY3Yy0xLjQ5My44OTctMy4zODItLjE5MS0zLjM4NC0xLjkxNVY5OS41MDhsMzcuNDI2LTIxLjUxNmM0LjQ4Mi0yLjU3NyA0LjUwNS04Ljk3Ny4wNDgtMTEuNTc4bC0zMy40MDUtMTkuNTMyIDM4LjkzNy0yMi4zNzV6bS00Ni4yNjMgMjguNzU4YzEuNDkzLjg1IDEuNDk0IDMuMDAyIDAgMy44NTFMOTYuMDEyIDkxLjc1IDU4LjYxNyA3MC4yNjVjLTQuNDg0LTIuNTc1LTEwLjA5Mi42MzgtMTAuMTIgNS43OXYzNi45MTRMMTAgOTAuODc1VjU2LjkzN2MwLTYuMzcyIDMuNDItMTIuMjY2IDguOTcxLTE1LjQ1M2wyOS41NS0xN3ptLTIyLjIyMy0yMy4zNi0uMDE2LjAxNnYtLjAyNHpNODcuMDE3IDIuMzg5YTE4LjAyIDE4LjAyIDAgMCAxIDE3LjkzNCAwbDI5LjUyNyAxNi45NDZMOTUuNjEgNDEuNjYzIDU3LjQ2IDE5LjM1OHoiLz48L3N2Zz4="
            media="(prefers-color-scheme: light)" />
        <link
            rel="icon"
            type="image/svg+xml"
            href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOTIiIGhlaWdodD0iMTkyIiBmaWxsPSJub25lIiB2aWV3Qm94PSIwIDAgMTkyIDE5MiI+PHBhdGggZmlsbD0iI2ZhZmFmYSIgZD0iTTU3LjQ2IDgzLjc4MWMuMDAyLTEuNzI0IDEuODc0LTIuNzg2IDMuMzY4LTEuOTM3bDMwLjY0NCAxNy42MXYzOS42MTdjMCA2LjkzMSA3LjU4NyAxMS4yMTIgMTMuNTY2IDcuNjhsMjkuNDQtMTcuNDIydjQzLjMxM2wtMjkuNTI3IDE2Ljk2OWExOC4wMiAxOC4wMiAwIDAgMS0xNy45MzQgMEw1Ny40NiAxNzIuNjQyek0xODIgMTM1LjA5NWExNy44MyAxNy44MyAwIDAgMS04Ljk3MSAxNS40NTNsLTI5LjU0OSAxNi45Njl2LTQzLjUwMUwxODIgMTAxLjIwM3pNNDguNDk3IDEyMy4yNzRoLS4wMjR2NDQuMjJsLTI5LjUwMi0xNi45NDZBMTcuODMgMTcuODMgMCAwIDEgMTAgMTM1LjA5NVYxMDEuMTh6bTEyNC41MDgtODEuNzlhMTcuODMgMTcuODMgMCAwIDEgOC45NzIgMTUuNDUzVjkwLjgybC03OC4xNDMgNDYuMjY3Yy0xLjQ5My44OTctMy4zODItLjE5MS0zLjM4NC0xLjkxNVY5OS41MDhsMzcuNDI2LTIxLjUxNmM0LjQ4Mi0yLjU3NyA0LjUwNS04Ljk3Ny4wNDgtMTEuNTc4bC0zMy40MDUtMTkuNTMyIDM4LjkzNy0yMi4zNzV6bS00Ni4yNjMgMjguNzU4YzEuNDkzLjg1IDEuNDk0IDMuMDAyIDAgMy44NTFMOTYuMDEyIDkxLjc1IDU4LjYxNyA3MC4yNjVjLTQuNDg0LTIuNTc1LTEwLjA5Mi42MzgtMTAuMTIgNS43OXYzNi45MTRMMTAgOTAuODc1VjU2LjkzN2MwLTYuMzcyIDMuNDItMTIuMjY2IDguOTcxLTE1LjQ1M2wyOS41NS0xN3ptLTIyLjIyMy0yMy4zNi0uMDE2LjAxNnYtLjAyNHpNODcuMDE3IDIuMzg5YTE4LjAyIDE4LjAyIDAgMCAxIDE3LjkzNCAwbDI5LjUyNyAxNi45NDZMOTUuNjEgNDEuNjYzIDU3LjQ2IDE5LjM1OHoiLz48L3N2Zz4="
            media="(prefers-color-scheme: dark)" />
        <link rel="preconnect" href="https://fonts.googleapis.com" />
        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
        <link
            rel="stylesheet"
            href="https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible+Mono:wght@400..700&family=Atkinson+Hyperlegible+Next:wght@400..700&display=swap" />
        <style>
            /* Reset & base */
            *,
            *::before,
            *::after {
                box-sizing: border-box;
                margin: 0;
                padding: 0;
            }
            html {
                -webkit-font-smoothing: antialiased;
                -moz-osx-font-smoothing: grayscale;
            }
            body {
                font-family: "Atkinson Hyperlegible Next", system-ui, sans-serif;
                background-color: #0a0a0a;
                color: var(--fg);
                font-size: 14px;
                line-height: 1.625;
            }
            a {
                color: inherit;
                text-decoration: none;
            }
            button {
                font: inherit;
                cursor: pointer;
                border: none;
                background: none;
                color: inherit;
            }
            ul,
            ol {
                list-style: none;
            }

            /* Background hex pattern (inlined SVG via base64) */
            .bg-hex {
                position: fixed;
                top: 0;
                left: 50%;
                transform: translateX(-50%);
                width: min(100%, 1600px);
                z-index: -1;
                pointer-events: none;
                user-select: none;
            }
            .bg-hex img {
                width: 100%;
                height: auto;
                display: block;
            }

            /* Colours */
            :root {
                --red: #f87171;
                --yellow: #fbbf24;
                --green: #4ade80;
                --blue: #60a5fa;
                --fg: #f9fafb;
                --fg-muted: #9ca3af;
                --fg-subtle: #6b7280;
                --border: rgba(255, 255, 255, 0.04);
                --surface: #111;
                --surface-raised: #161616;
            }

            /* Layout */
            .shell {
                min-height: 100vh;
                max-width: 1200px;
                margin: 0 auto;
                padding: 0 32px;
                display: grid;
                grid-template-columns: repeat(12, 1fr);
                column-gap: 32px;
            }
            .sidebar {
                grid-column: 1 / 4;
                position: sticky;
                top: 0;
                height: 100vh;
                background: transparent;
                overflow-y: auto;
                padding: 28px 0;
                display: flex;
                flex-direction: column;
            }
            .sidebar-meta {
                margin-bottom: 24px;
            }
            .sidebar-meta-item {
                font-size: 12px;
                color: var(--fg-subtle);
                padding: 3px 0;
                display: flex;
                gap: 6px;
            }
            .sidebar-meta-item strong {
                color: var(--fg-subtle);
                font-weight: 500;
            }
            .sidebar-divider {
                height: 1px;
                background: var(--border);
                margin: 4px 0 16px;
            }
            .sidebar-nav-label {
                font-size: 12px;
                font-weight: 600;
                text-transform: uppercase;
                letter-spacing: 0.1em;
                color: var(--fg-subtle);
                margin-bottom: 12px;
            }
            .sidebar-nav {
                list-style: none;
                margin: 0;
                padding: 0;
                flex: 1;
            }
            .sidebar-nav-item {
                display: block;
                padding: 5px 0;
                font-size: 14px;
                color: var(--fg-muted);
                cursor: pointer;
                transition: color 0.12s;
                text-decoration: none;
            }
            .sidebar-nav-item:hover {
                color: var(--fg);
            }
            .sidebar-nav-item.active {
                color: var(--fg);
            }
            .sidebar-nav-item .nav-count {
                font-size: 12px;
                color: var(--fg-subtle);
                background: rgba(255, 255, 255, 0.04);
                padding: 1px 6px;
                border-radius: 8px;
                margin-left: 6px;
            }
            .sidebar-nav-item.active .nav-count {
                color: var(--fg-subtle);
                background: rgba(255, 255, 255, 0.06);
            }
            .main {
                grid-column: 4 / 13;
                padding: 28px 0 80px;
            }

            /* Right-side drill-down panel */
            .panel {
                position: fixed;
                top: 0;
                right: 0;
                width: 480px;
                height: 100vh;
                background: var(--surface);
                border-left: 1px solid var(--border);
                overflow-y: auto;
                z-index: 50;
                transform: translateX(100%);
                transition: transform 0.25s ease;
            }
            .shell.panel-open .panel {
                transform: translateX(0);
            }
            .panel-inner {
                width: 480px;
                padding: 32px 28px;
            }
            .panel-close {
                position: absolute;
                top: 16px;
                right: 16px;
                color: var(--fg-subtle);
                font-size: 20px;
                cursor: pointer;
            }
            .panel-close:hover {
                color: var(--fg-muted);
            }
            .panel-title {
                font-size: 16px;
                font-weight: 600;
                color: var(--fg);
                margin-bottom: 4px;
                padding-right: 32px;
            }
            .panel-subtitle {
                font-size: 14px;
                color: var(--fg-subtle);
                margin-bottom: 24px;
            }
            .panel-section {
                margin-bottom: 24px;
            }
            .panel-section-label {
                font-size: 12px;
                font-weight: 600;
                text-transform: uppercase;
                letter-spacing: 0.05em;
                color: var(--fg-subtle);
                margin-bottom: 10px;
            }

            /* Page header bar */
            .page-header {
                max-width: 1200px;
                margin: 0 auto;
                padding: 32px 32px 0;
                display: flex;
                justify-content: space-between;
                align-items: center;
            }
            .page-header-logo {
                display: flex;
                align-items: center;
                gap: 10px;
            }
            .page-header-link {
                font-size: 14px;
                color: var(--fg-subtle);
                text-decoration: none;
                transition: color 0.15s;
            }
            .page-header-link:hover {
                color: var(--fg-muted);
            }
            .alpha-tag {
                font-size: 12px;
                font-weight: 600;
                letter-spacing: 0.1em;
                padding: 2px 7px;
                border-radius: 4px;
                background: rgba(251, 191, 36, 0.14);
                color: var(--yellow);
                text-transform: uppercase;
                display: inline-block;
                line-height: 1.375;
            }

            /* Readiness band */
            .readiness {
                position: relative;
                background: rgba(255, 255, 255, 0.02);
                border: 1px solid var(--border);
                border-radius: 8px;
                padding: 24px;
                margin-bottom: 32px;
            }
            .band-row {
                display: flex;
                align-items: center;
                gap: 16px;
                margin-bottom: 16px;
            }
            .band-indicator {
                display: flex;
                gap: 3px;
                width: 120px;
                flex-shrink: 0;
            }
            .band-seg {
                height: 6px;
                border-radius: 3px;
                flex: 1;
                opacity: 0.25;
            }
            .band-seg.blocked {
                background: var(--red);
            }
            .band-seg.constrained {
                background: var(--yellow);
            }
            .band-seg.productive {
                background: var(--green);
            }
            .band-seg.active {
                opacity: 1;
            }
            .band-label {
                font-size: 20px;
                font-weight: 600;
                color: var(--yellow);
            }
            .band-label.blocked {
                color: var(--red);
            }
            .band-label.constrained {
                color: var(--yellow);
            }
            .band-label.productive {
                color: var(--green);
            }
            .band-narrative {
                font-size: 14px;
                color: var(--fg-muted);
                line-height: 1.625;
            }
            .band-narrative strong {
                color: var(--fg);
                font-weight: 500;
            }
            .band-narrative code {
                font-family: "Atkinson Hyperlegible Mono", monospace;
                font-size: 12px;
                background: rgba(255, 255, 255, 0.04);
                padding: 1px 5px;
                border-radius: 3px;
                color: var(--fg);
            }
            .band-explain {
                position: absolute;
                top: 20px;
                right: 20px;
                font-size: 12px;
                color: var(--fg-subtle);
                cursor: pointer;
            }
            .band-explain:hover {
                color: var(--fg-muted);
            }

            /* Modal */
            .modal-overlay {
                display: none;
                position: fixed;
                inset: 0;
                background: rgba(0, 0, 0, 0.6);
                z-index: 200;
                justify-content: center;
                align-items: center;
            }
            .modal-overlay.open {
                display: flex;
            }
            .modal-box {
                background: #161616;
                border: 1px solid var(--border);
                border-radius: 12px;
                padding: 28px;
                max-width: 520px;
                width: 90%;
                max-height: 80vh;
                overflow-y: auto;
            }
            .modal-box h3 {
                font-size: 16px;
                font-weight: 600;
                color: var(--fg);
                margin-bottom: 16px;
            }
            .modal-box p {
                font-size: 14px;
                color: var(--fg-muted);
                line-height: 1.625;
                margin-bottom: 12px;
            }
            .modal-close {
                float: right;
                color: var(--fg-subtle);
                font-size: 20px;
                cursor: pointer;
                background: none;
                border: none;
            }
            .modal-close:hover {
                color: var(--fg-muted);
            }
            .modal-band-item {
                padding: 8px 0;
                border-bottom: 1px solid rgba(255, 255, 255, 0.04);
                font-size: 14px;
                color: var(--fg-muted);
            }
            .modal-band-item:last-child {
                border-bottom: none;
            }
            .modal-band-item strong {
                font-weight: 600;
            }

            /* Stats row */
            .stats-row {
                display: grid;
                grid-auto-flow: column;
                grid-auto-columns: 1fr;
                gap: 16px;
                margin-bottom: 40px;
                padding: 20px 0;
                border-top: 1px solid var(--border);
                border-bottom: 1px solid var(--border);
            }
            .stats-row:empty {
                display: none;
            }
            .stat-item {
                text-align: center;
                display: flex;
                flex-direction: column;
                align-items: center;
                gap: 4px;
            }
            .stat-value {
                font-size: 24px;
                font-weight: 600;
                color: var(--fg);
            }
            .stat-label {
                font-size: 12px;
                color: var(--fg-subtle);
                text-transform: uppercase;
                letter-spacing: 0.05em;
            }

            /* Data sources & bar chart rows */
            .source-bar-row {
                display: flex;
                align-items: center;
                gap: 12px;
                margin-bottom: 12px;
            }
            .source-bar-label {
                font-size: 12px;
                color: var(--fg-muted);
                white-space: nowrap;
                flex-shrink: 0;
                min-width: var(--bar-label-width, 100px);
            }
            .source-bar-container {
                flex: 1;
                height: 6px;
                background: rgba(255, 255, 255, 0.04);
                border-radius: 3px;
                overflow: hidden;
            }
            .source-bar-fill {
                height: 100%;
                background: var(--blue);
            }
            .source-bar-count {
                font-size: 12px;
                color: var(--fg-subtle);
                width: 32px;
                text-align: right;
                flex-shrink: 0;
            }

            /* Section dividers */
            .section-divider {
                margin: 48px 0 32px;
                scroll-margin-top: 20px;
            }
            .section-title {
                font-size: 14px;
                font-weight: 600;
                text-transform: uppercase;
                letter-spacing: 0.1em;
                color: var(--fg-subtle);
                margin-bottom: 8px;
            }

            /* Panel back button */
            .panel-back {
                display: flex;
                align-items: center;
                gap: 6px;
                font-size: 12px;
                color: var(--fg-subtle);
                cursor: pointer;
                margin-bottom: 16px;
                padding: 4px 0;
                transition: color 0.1s;
            }
            .panel-back:hover {
                color: var(--fg-muted);
            }

            /* Finding rows */
            #findingsList {
                counter-reset: finding-counter;
            }
            .finding-row {
                display: flex;
                align-items: center;
                gap: 12px;
                padding: 10px 0;
                border-bottom: 1px solid var(--border);
                cursor: pointer;
                transition: background 0.1s;
            }
            .finding-row::before {
                counter-increment: finding-counter;
                content: counter(finding-counter);
                flex-shrink: 0;
                width: 24px;
                height: 24px;
                border-radius: 50%;
                background: rgba(255, 255, 255, 0.06);
                color: var(--fg-muted);
                font-size: 12px;
                font-weight: 600;
                font-variant-numeric: tabular-nums;
                display: flex;
                align-items: center;
                justify-content: center;
            }
            .finding-row:hover {
                background: rgba(255, 255, 255, 0.02);
                margin: 0 -8px;
                padding: 10px 8px;
                border-radius: 6px;
                border-color: transparent;
            }
            .finding-badge {
                font-size: 12px;
                font-weight: 500;
                padding: 2px 8px;
                border-radius: 3px;
                letter-spacing: 0.025em;
                white-space: nowrap;
                flex-shrink: 0;
                background: rgba(255, 255, 255, 0.05);
                color: var(--fg-subtle);
            }
            .finding-desc {
                flex: 1;
                font-size: 14px;
                color: var(--fg);
                line-height: 1.5;
            }
            .finding-priority {
                font-size: 12px;
                flex-shrink: 0;
                font-weight: 500;
            }
            .finding-priority.critical {
                color: var(--red);
            }
            .finding-priority.high {
                color: var(--yellow);
            }
            .finding-priority.medium {
                color: var(--yellow);
                opacity: 0.75;
            }
            .finding-priority.low {
                color: var(--blue);
            }

            /* Filter row */
            .filter-row {
                margin-bottom: 20px;
                display: flex;
                align-items: center;
                gap: 10px;
            }
            .search-box {
                flex: 1;
                position: relative;
            }
            .search-box input {
                width: 100%;
                padding: 8px 12px 8px 32px;
                background: rgba(255, 255, 255, 0.03);
                border: 1px solid var(--border);
                border-radius: 6px;
                color: var(--fg);
                font-size: 14px;
                font-family: inherit;
            }
            .search-box input::placeholder {
                color: var(--fg-subtle);
            }
            .search-box input:focus {
                outline: none;
                border-color: #333;
                background: rgba(255, 255, 255, 0.05);
            }
            .search-box::before {
                content: "";
                position: absolute;
                left: 11px;
                top: 50%;
                width: 12px;
                height: 12px;
                transform: translateY(-50%);
                background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='7'/><path d='m21 21-4.3-4.3'/></svg>");
                background-repeat: no-repeat;
            }

            /* Dropdown */
            .dropdown-wrapper {
                position: relative;
            }
            .dropdown-trigger {
                display: inline-flex;
                align-items: center;
                gap: 8px;
                padding: 8px 12px;
                background: rgba(255, 255, 255, 0.03);
                border: 1px solid var(--border);
                border-radius: 6px;
                color: var(--fg);
                font-size: 14px;
                font-family: inherit;
                cursor: pointer;
                text-align: left;
                transition: all 0.15s;
            }
            .dropdown-trigger:hover {
                border-color: #333;
            }
            .dropdown-trigger.open {
                border-color: #333;
                background: rgba(255, 255, 255, 0.05);
            }
            .dropdown-trigger-label {
                color: var(--fg);
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
            }
            .dropdown-trigger-arrow {
                width: 10px;
                height: 10px;
                flex-shrink: 0;
                background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%23777' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
                background-repeat: no-repeat;
                background-position: center;
                transition: transform 0.15s;
            }
            .dropdown-trigger.open .dropdown-trigger-arrow {
                transform: rotate(180deg);
            }
            .dropdown-panel {
                position: absolute;
                top: calc(100% + 6px);
                right: 0;
                background: #161616;
                border: 1px solid rgba(255, 255, 255, 0.08);
                border-radius: 8px;
                min-width: 340px;
                padding: 6px;
                z-index: 100;
                display: none;
                box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
            }
            .dropdown-panel.open {
                display: block;
            }
            .dropdown-option {
                display: flex;
                align-items: flex-start;
                gap: 12px;
                padding: 9px 10px;
                border-radius: 6px;
                cursor: pointer;
                transition: background 0.1s;
                user-select: none;
            }
            .dropdown-option:hover {
                background: rgba(255, 255, 255, 0.04);
            }
            .dropdown-checkbox {
                width: 16px;
                height: 16px;
                border: 1px solid #333;
                border-radius: 3px;
                background: transparent;
                flex-shrink: 0;
                display: flex;
                align-items: center;
                justify-content: center;
                transition: all 0.1s;
                margin-top: 1px;
            }
            .dropdown-option.selected .dropdown-checkbox {
                background: rgba(255, 255, 255, 0.9);
                border-color: rgba(255, 255, 255, 0.9);
            }
            .dropdown-option.selected .dropdown-checkbox::after {
                content: "";
                width: 10px;
                height: 10px;
                background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%230a0a0a' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
                background-repeat: no-repeat;
                background-position: center;
            }
            .dropdown-option-body {
                flex: 1;
                min-width: 0;
            }
            .dropdown-option-label {
                color: var(--fg);
                font-size: 14px;
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
            }
            .dropdown-option-desc {
                font-size: 12px;
                color: var(--fg-subtle);
                margin-top: 2px;
                line-height: 1.375;
            }
            .dropdown-option-count {
                font-size: 12px;
                font-weight: 500;
                background: rgba(255, 255, 255, 0.06);
                color: var(--fg-subtle);
                padding: 2px 9px;
                border-radius: 10px;
                flex-shrink: 0;
                min-width: 28px;
                text-align: center;
                align-self: flex-start;
                margin-top: 1px;
            }
            .dropdown-divider {
                height: 1px;
                background: rgba(255, 255, 255, 0.04);
                margin: 4px 6px;
            }

            /* Filter-state bar (shown when any filter is active) */
            .filter-state-bar {
                display: none;
                align-items: center;
                gap: 8px;
                flex-wrap: wrap;
                font-size: 12px;
                color: var(--fg-subtle);
                margin: -8px 0 16px;
            }
            .filter-state-bar.active {
                display: flex;
            }
            .filter-state-count {
                color: var(--fg-muted);
            }
            .filter-state-chip {
                display: inline-flex;
                align-items: center;
                gap: 6px;
                padding: 2px 8px;
                border-radius: 999px;
                font-size: 12px;
                color: var(--fg-muted);
                background: rgba(255, 255, 255, 0.04);
                border: 1px solid var(--border);
            }
            .filter-state-chip-close {
                cursor: pointer;
                opacity: 0.6;
                font-size: 12px;
                line-height: 1;
            }
            .filter-state-chip-close:hover {
                opacity: 1;
            }
            .filter-state-clear {
                color: var(--blue);
                cursor: pointer;
                font-size: 12px;
                margin-left: 4px;
                text-decoration: underline;
                text-decoration-color: rgba(96, 165, 250, 0.3);
            }
            .filter-state-clear:hover {
                text-decoration-color: var(--blue);
            }

            /* Findings empty state */
            .findings-empty {
                padding: 40px 16px;
                text-align: center;
                color: var(--fg-subtle);
                font-size: 12px;
                border: 1px dashed var(--border);
                border-radius: 8px;
                margin-top: 4px;
            }
            .findings-empty-action {
                display: inline-block;
                margin-top: 10px;
                color: var(--blue);
                cursor: pointer;
                text-decoration: underline;
                text-decoration-color: rgba(96, 165, 250, 0.3);
            }
            .findings-empty-action:hover {
                text-decoration-color: var(--blue);
            }

            /* Related items in drawer */
            .panel-related-item {
                display: flex;
                align-items: center;
                gap: 10px;
                padding: 8px 10px;
                margin: 4px 0;
                border-radius: 6px;
                background: rgba(255, 255, 255, 0.02);
                border: 1px solid var(--border);
                cursor: pointer;
                transition: all 0.1s;
            }
            .panel-related-item:hover {
                background: rgba(255, 255, 255, 0.05);
                border-color: #333;
            }
            .panel-related-item-title {
                flex: 1;
                font-size: 12px;
                color: var(--fg-muted);
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }
            .panel-related-item-tag {
                font-size: 12px;
                font-weight: 500;
                padding: 1px 7px;
                border-radius: 10px;
                background: rgba(255, 255, 255, 0.05);
                color: var(--fg-subtle);
                flex-shrink: 0;
            }

            /* Empty state (legacy fallback) */
            .empty-state {
                padding: 32px;
                border: 1px dashed var(--border);
                border-radius: 8px;
                color: var(--fg-subtle);
                font-size: 14px;
                text-align: center;
            }

            /* What was analysed / data sources */
            .source-grid {
                display: flex;
                justify-content: space-around;
                text-align: center;
                padding: 24px 0;
                gap: 24px;
            }
            .source-grid:empty {
                display: none;
            }
            .source-num {
                font-size: 24px;
                font-weight: 600;
                color: var(--fg);
            }
            .source-label {
                font-size: 12px;
                color: var(--fg-subtle);
                margin-top: 4px;
            }
            .section-label {
                font-size: 12px;
                font-weight: 600;
                text-transform: uppercase;
                letter-spacing: 0.1em;
                color: var(--fg-subtle);
                margin-bottom: 12px;
            }
            .source-tags {
                display: flex;
                flex-wrap: wrap;
                gap: 8px;
            }
            .source-tag {
                padding: 8px 14px;
                border-radius: 8px;
                background: rgba(255, 255, 255, 0.03);
                border: 1px solid var(--border);
                font-size: 12px;
                color: var(--fg-subtle);
                display: flex;
                align-items: center;
                gap: 8px;
            }
            .source-tag a {
                color: var(--blue);
                text-decoration: none;
                font-weight: 500;
            }
            .source-tag a:hover {
                text-decoration: underline;
            }
            .ev-pill {
                font-size: 12px;
                font-weight: 600;
                padding: 2px 8px;
                border-radius: 4px;
                white-space: nowrap;
                flex-shrink: 0;
                background: rgba(255, 255, 255, 0.05);
                color: var(--fg-subtle);
            }

            /* Context inventory — Tessl toggle chip */
            .ci-tessl-chip {
                display: inline-flex;
                align-items: center;
                gap: 8px;
                padding: 8px 12px;
                background: rgba(255, 255, 255, 0.03);
                border: 1px solid var(--border);
                border-radius: 6px;
                color: var(--fg-subtle);
                font-size: 14px;
                font-family: inherit;
                cursor: pointer;
                transition: all 0.15s;
                white-space: nowrap;
            }
            .ci-tessl-chip:hover {
                border-color: #333;
                color: var(--fg-muted);
            }
            .ci-tessl-chip.active {
                background: rgba(4, 221, 124, 0.08);
                border-color: rgba(4, 221, 124, 0.35);
                color: var(--fg);
            }
            .ci-tessl-chip-icon {
                display: inline-flex;
                align-items: center;
                justify-content: center;
                width: 14px;
                height: 14px;
                font-size: 14px;
                line-height: 1;
                color: var(--fg-subtle);
            }
            .ci-tessl-chip.active .ci-tessl-chip-icon {
                color: #04dd7c;
            }
            .ci-tessl-chip-count {
                font-size: 12px;
                font-weight: 500;
                background: rgba(255, 255, 255, 0.06);
                color: var(--fg-subtle);
                padding: 1px 7px;
                border-radius: 10px;
                font-variant-numeric: tabular-nums;
            }
            .ci-tessl-chip.active .ci-tessl-chip-count {
                background: rgba(4, 221, 124, 0.15);
                color: #04dd7c;
            }

            /* Entry dots */
            .ci-dot {
                width: 8px;
                height: 8px;
                border-radius: 50%;
                display: inline-block;
                flex-shrink: 0;
            }
            .ci-dot-useful {
                background: var(--green);
            }
            .ci-dot-partial {
                background: var(--yellow);
            }
            .ci-dot-unused {
                background: var(--red);
                opacity: 0.7;
            }

            .ci-list {
                display: flex;
                flex-direction: column;
                gap: 0;
            }

            /* File grouping */
            .ci-file {
                padding: 12px 0 10px;
                border-bottom: 1px solid var(--border);
            }
            .ci-file[hidden] {
                display: none;
            }
            .ci-file-header {
                display: flex;
                align-items: baseline;
                gap: 12px;
                padding: 0 4px 6px;
            }
            .ci-file-path {
                font-family: "Atkinson Hyperlegible Mono", "SF Mono", monospace;
                font-size: 14px;
                font-weight: 500;
                color: var(--fg);
                flex: 1;
                min-width: 0;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }
            .ci-file-meta {
                display: flex;
                align-items: center;
                gap: 10px;
                flex-shrink: 0;
            }
            .ci-file-tokens {
                font-size: 12px;
                color: var(--fg-subtle);
                font-variant-numeric: tabular-nums;
            }
            .ci-file-entries {
                display: flex;
                flex-direction: column;
            }

            /* Per-entry row */
            .ci-entry {
                display: flex;
                align-items: center;
                gap: 10px;
                padding: 7px 4px;
                cursor: pointer;
                transition: background 0.1s;
                border-radius: 4px;
            }
            .ci-entry[hidden] {
                display: none;
            }
            .ci-entry:hover {
                background: rgba(255, 255, 255, 0.03);
            }
            .ci-entry-dot {
                width: 8px;
                height: 8px;
                border-radius: 50%;
                flex-shrink: 0;
            }
            .ci-entry-name {
                flex: 1;
                min-width: 0;
                font-size: 14px;
                color: var(--fg-muted);
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }
            .ci-entry-right {
                display: flex;
                align-items: center;
                gap: 6px;
                flex-shrink: 0;
            }
            .ci-entry-type {
                font-size: 12px;
                font-weight: 500;
                padding: 1px 7px;
                border-radius: 10px;
                background: rgba(255, 255, 255, 0.05);
                color: var(--fg-subtle);
            }
            .ci-entry-harness {
                font-size: 12px;
                padding: 1px 7px;
                border-radius: 3px;
                background: rgba(255, 255, 255, 0.04);
                color: var(--fg-subtle);
            }

            /* Plugin card — Tessl-brand framing */
            .ci-file-plugin {
                cursor: pointer;
                background: rgba(4, 221, 124, 0.03);
                border: 1px solid rgba(4, 221, 124, 0.18);
                border-radius: 8px;
                padding: 10px 14px;
                margin: 6px 0;
                transition: all 0.12s;
            }
            .ci-file-plugin:hover {
                background: rgba(4, 221, 124, 0.06);
                border-color: rgba(4, 221, 124, 0.35);
            }
            .ci-file-plugin .ci-entry {
                pointer-events: none;
                padding-left: 0;
                padding-right: 0;
            }
            .ci-file-plugin .ci-file-header {
                padding-left: 0;
                padding-right: 0;
            }
            .ci-file-plugin .ci-file-path {
                color: #04dd7c;
            }
            .ci-file-plugin .ci-entry-type {
                background: rgba(4, 221, 124, 0.12);
                color: #04dd7c;
                border: 1px solid rgba(4, 221, 124, 0.28);
            }

            .ci-empty {
                padding: 32px 16px;
                text-align: center;
                color: var(--fg-subtle);
                font-size: 14px;
            }

            /* Drawer-specific (context entry) */
            .panel-meta-grid {
                display: grid;
                grid-template-columns: 90px 1fr;
                gap: 8px 12px;
                font-size: 12px;
                margin-top: 4px;
            }
            .panel-meta-key {
                color: var(--fg-subtle);
                text-transform: uppercase;
                letter-spacing: 0.05em;
                font-size: 12px;
                font-weight: 600;
                padding-top: 3px;
            }
            .panel-meta-val {
                color: var(--fg-muted);
                word-break: break-all;
            }
            .panel-meta-val.mono {
                font-family: "Atkinson Hyperlegible Mono", monospace;
                font-size: 12px;
                color: var(--fg-muted);
            }
            .panel-link {
                display: block;
                padding: 6px 10px;
                margin: 3px 0;
                border-radius: 6px;
                font-family: "Atkinson Hyperlegible Mono", monospace;
                font-size: 12px;
                color: var(--fg-muted);
                background: rgba(255, 255, 255, 0.02);
                border: 1px solid var(--border);
                cursor: pointer;
                transition: all 0.1s;
                word-break: break-all;
            }
            .panel-link:hover {
                background: rgba(255, 255, 255, 0.05);
                color: var(--fg);
                border-color: #333;
            }

            /* Richer two-line card used in plugin "Contents" lists */
            .panel-entry-card {
                display: flex;
                align-items: flex-start;
                gap: 10px;
                padding: 8px 10px;
                margin: 3px 0;
                border-radius: 6px;
                background: rgba(255, 255, 255, 0.02);
                border: 1px solid var(--border);
                cursor: pointer;
                transition: all 0.1s;
            }
            .panel-entry-card:hover {
                background: rgba(255, 255, 255, 0.05);
                border-color: #333;
            }
            .panel-entry-card-dot {
                width: 8px;
                height: 8px;
                border-radius: 50%;
                margin-top: 5px;
                flex-shrink: 0;
            }
            .panel-entry-card-body {
                flex: 1;
                min-width: 0;
            }
            .panel-entry-card-title {
                font-size: 13px;
                color: var(--fg);
                font-weight: 500;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }
            .panel-entry-card-path {
                font-family: "Atkinson Hyperlegible Mono", monospace;
                font-size: 11px;
                color: var(--fg-subtle);
                margin-top: 2px;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }
            .panel-entry-card-meta {
                font-size: 11px;
                color: var(--fg-subtle);
                font-variant-numeric: tabular-nums;
                flex-shrink: 0;
                margin-top: 4px;
            }

            /* Asymmetries callout */
            .ci-asymmetries {
                margin-top: 16px;
                padding: 14px 16px;
                background: rgba(248, 113, 113, 0.06);
                border: 1px solid rgba(248, 113, 113, 0.25);
                border-radius: 8px;
            }
            .ci-asymmetries h3 {
                font-size: 12px;
                font-weight: 700;
                letter-spacing: 0.1em;
                text-transform: uppercase;
                color: var(--red);
                margin-bottom: 8px;
            }
            .ci-asymmetries ul {
                list-style: none;
                padding: 0;
                margin: 0;
                font-size: 14px;
                color: var(--fg);
            }
            .ci-asymmetries li {
                padding: 3px 0;
                display: flex;
                gap: 8px;
                align-items: flex-start;
            }
            .ci-asymmetries li::before {
                content: "!";
                color: var(--red);
                font-weight: 700;
            }

            /* Methodology */
            .methodology {
                font-size: 14px;
                color: var(--fg-muted);
                line-height: 1.625;
            }
            .methodology p {
                margin-bottom: 12px;
            }

            /* Footer */
            .site-footer {
                border-top: 1px solid rgba(255, 255, 255, 0.06);
                margin-top: 80px;
            }
            .footer-inner {
                max-width: 1200px;
                margin: 0 auto;
                padding: 56px 32px 40px;
            }
            .footer-logo {
                display: flex;
                align-items: center;
                gap: 10px;
                margin-bottom: 40px;
            }
            .footer-columns {
                display: grid;
                grid-template-columns: repeat(4, 1fr);
                gap: 32px;
                margin-bottom: 48px;
            }
            .footer-col-title {
                font-size: 14px;
                font-weight: 600;
                color: var(--fg);
                margin-bottom: 16px;
            }
            .footer-col a {
                display: block;
                font-size: 14px;
                color: var(--fg-subtle);
                text-decoration: none;
                padding: 4px 0;
                transition: color 0.15s;
            }
            .footer-col a:hover {
                color: var(--fg-muted);
            }
            .footer-address {
                font-size: 12px;
                color: var(--fg-subtle);
                padding-top: 24px;
                border-top: 1px solid rgba(255, 255, 255, 0.04);
            }
            @media (max-width: 600px) {
                .footer-columns {
                    grid-template-columns: repeat(2, 1fr);
                }
            }
            @media (max-width: 900px) {
                .shell {
                    display: block;
                    padding: 0 24px;
                }
                .sidebar {
                    display: none;
                }
                .main {
                    padding: 32px 0 60px;
                }
                .panel {
                    width: 100%;
                }
                .stats-row {
                    grid-auto-flow: row;
                    grid-template-columns: repeat(2, 1fr);
                    grid-auto-columns: auto;
                }
            }
        </style>
    </head>
    <body>
        <!-- Background hex pattern -->
        <div class="bg-hex" aria-hidden="true">
            <img
                alt=""
                src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCAyMTE4IDExMDMiPgogIDxnIGNsaXAtcGF0aD0idXJsKCNhKSI+CiAgICA8bWFzayBpZD0iYyIgd2lkdGg9IjIxMTgiIGhlaWdodD0iMTEwMyIgeD0iMCIgeT0iMCIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgc3R5bGU9Im1hc2stdHlwZTphbHBoYSI+CiAgICAgIDxwYXRoIGZpbGw9InVybCgjYikiIGQ9Ik0yMTE4IDEwODNhMjAgMjAgMCAwIDEtMjAgMjBIMjBhMjAgMjAgMCAwIDEtMjAtMjBWMjBBMjAgMjAgMCAwIDEgMjAgMGgyMDc4YTIwIDIwIDAgMCAxIDIwIDIweiIvPgogICAgPC9tYXNrPgogICAgPGcgbWFzaz0idXJsKCNjKSI+CiAgICAgIDxwYXRoIGZpbGw9InVybCgjZCkiIGQ9Ik0yOTQuMiA5NTAuODZhMjQgMjQgMCAwIDEtMjQuMTEgMEwxNjguNiA4OTEuOWEyNCAyNCAwIDAgMS0xMS45NC0yMC43NVY3NTIuOTdhMjQgMjQgMCAwIDEgMTEuOTQtMjAuNzZsMTAxLjQ4LTU4Ljk2YTI0IDI0IDAgMCAxIDI0LjExIDBsMTAxLjQ4IDU4Ljk2YTI0IDI0IDAgMCAxIDExLjk0IDIwLjc1djExOC4xOWEyNCAyNCAwIDAgMS0xMS45NCAyMC43NXoiLz4KICAgICAgPHBhdGggc3Ryb2tlPSJ1cmwoI2UpIiBzdHJva2Utb3BhY2l0eT0iLjE5IiBzdHJva2Utd2lkdGg9IjEuNTUiIGQ9Ik0yOTMuODEgOTUwLjE5YTIzLjIgMjMuMiAwIDAgMS0yMy4zMyAwTDE2OSA4OTEuMjNhMjMuMiAyMy4yIDAgMCAxLTExLjU2LTIwLjA4Vjc1Mi45N2MwLTguMjggNC40LTE1LjkzIDExLjU2LTIwLjA5bDEwMS40OC01OC45NmEyMy4yIDIzLjIgMCAwIDEgMjMuMzMgMGwxMDEuNDggNTguOTZhMjMuMiAyMy4yIDAgMCAxIDExLjU2IDIwLjA5djExOC4xOGMwIDguMjctNC40IDE1LjkyLTExLjU2IDIwLjA4eiIvPgogICAgICA8cGF0aCBmaWxsPSJ1cmwoI2YpIiBkPSJNNDM5IDcwMC45M2EyNCAyNCAwIDAgMS0yNC4xMiAwbC0xMDEuNDctNTguOTZhMjQgMjQgMCAwIDEtMTEuOTUtMjAuNzVWNTAzLjA0YTI0IDI0IDAgMCAxIDExLjk1LTIwLjc2bDEwMS40Ny01OC45NWEyNCAyNCAwIDAgMSAyNC4xMiAwbDEwMS40NyA1OC45NWEyNCAyNCAwIDAgMSAxMS45NCAyMC43NnYxMTguMThhMjQgMjQgMCAwIDEtMTEuOTQgMjAuNzV6Ii8+CiAgICAgIDxwYXRoIGZpbGw9InVybCgjZykiIHN0cm9rZT0idXJsKCNoKSIgc3Ryb2tlLXdpZHRoPSIxLjU1IiBkPSJNODYyLjkxIDk1MC4xOWEyMy4yIDIzLjIgMCAwIDEtMjMuMzMgMEw3MzguMSA4OTEuMjNhMjMuMiAyMy4yIDAgMCAxLTExLjU2LTIwLjA4Vjc1Mi45N2MwLTguMjggNC40LTE1LjkzIDExLjU2LTIwLjA5bDEwMS40OC01OC45NmEyMy4yIDIzLjIgMCAwIDEgMjMuMzMgMGwxMDEuNDggNTguOTZhMjMuMiAyMy4yIDAgMCAxIDExLjU2IDIwLjA5djExOC4xOGMwIDguMjctNC40IDE1LjkyLTExLjU2IDIwLjA4eiIvPgogICAgICA8cGF0aCBmaWxsPSJ1cmwoI2kpIiBmaWxsLW9wYWNpdHk9Ii41IiBkPSJNNzE4LjUxIDcwMC45M2EyNCAyNCAwIDAgMS0yNC4xMSAwbC0xMDEuNDgtNTguOTZhMjQgMjQgMCAwIDEtMTEuOTQtMjAuNzVWNTAzLjA0YTI0IDI0IDAgMCAxIDExLjk0LTIwLjc2bDEwMS40OC01OC45NWEyNCAyNCAwIDAgMSAyNC4xMSAwbDEwMS40NyA1OC45NWEyNCAyNCAwIDAgMSAxMS45NSAyMC43NnYxMTguMThhMjQgMjQgMCAwIDEtMTEuOTUgMjAuNzV6Ii8+CiAgICAgIDxnIGZpbHRlcj0idXJsKCNqKSI+CiAgICAgICAgPHBhdGggZmlsbD0idXJsKCNrKSIgZD0iTTU3My42NiA5NTFhMjQgMjQgMCAwIDEtMjQuMTEgMGwtMTAxLjQ4LTU4Ljk2YTI0IDI0IDAgMCAxLTExLjk0LTIwLjc2Vzc1My4xYTI0IDI0IDAgMCAxIDExLjk0LTIwLjc1bDEwMS40OC01OC45NmEyNCAyNCAwIDAgMSAyNC4xMSAwbDEwMS40OCA1OC45NmEyNCAyNCAwIDAgMSAxMS45NCAyMC43NXYxMTguMThhMjQgMjQgMCAwIDEtMTEuOTUgMjAuNzZ6Ii8+CiAgICAgICAgPHBhdGggc3Ryb2tlPSJ1cmwoI2wpIiBzdHJva2Utd2lkdGg9IjEuNTUiIGQ9Ik01NzMuMjcgOTUwLjMzYTIzLjIgMjMuMiAwIDAgMS0yMy4zNCAwbC0xMDEuNDctNTguOTZhMjMuMiAyMy4yIDAgMCAxLTExLjU2LTIwLjA5Vjc1My4xYzAtOC4yNyA0LjQtMTUuOTIgMTEuNTYtMjAuMDhsMTAxLjQ3LTU4Ljk2YTIzLjIgMjMuMiAwIDAgMSAyMy4zNCAwbDEwMS40OCA1OC45NmEyMy4yIDIzLjIgMCAwIDEgMTEuNTUgMjAuMDh2MTE4LjE4YzAgOC4yOC00LjQgMTUuOTMtMTEuNTUgMjAuMDl6Ii8+CiAgICAgIDwvZz4KICAgICAgPHBhdGggZmlsbD0idXJsKCNtKSIgZD0iTTMwNi42MSA0NDUuNmEyNCAyNCAwIDAgMS0yNC4xMSAwbC0xMDEuNDgtNTguOTVhMjQgMjQgMCAwIDEtMTEuOTQtMjAuNzVWMjQ3LjcyYTI0IDI0IDAgMCAxIDExLjk0LTIwLjc2TDI4Mi41IDE2OGEyNCAyNCAwIDAgMSAyNC4xMSAwbDEwMS40OCA1OC45NmEyNCAyNCAwIDAgMSAxMS45NCAyMC43NVYzNjUuOWEyNCAyNCAwIDAgMS0xMS45NCAyMC43NXoiLz4KICAgICAgPHBhdGggc3Ryb2tlPSJ1cmwoI24pIiBzdHJva2Utb3BhY2l0eT0iLjExIiBzdHJva2Utd2lkdGg9IjEuNTUiIGQ9Ik0zMDYuMjIgNDQ0Ljk0YTIzLjIgMjMuMiAwIDAgMS0yMy4zMyAwTDE4MS40IDM4NS45OGEyMy4yIDIzLjIgMCAwIDEtMTEuNTYtMjAuMDhWMjQ3LjcyYzAtOC4yOCA0LjQtMTUuOTMgMTEuNTYtMjAuMDlsMTAxLjQ4LTU4Ljk2YTIzLjIgMjMuMiAwIDAgMSAyMy4zMyAwbDEwMS40OCA1OC45NmEyMy4yIDIzLjIgMCAwIDEgMTEuNTYgMjAuMDlWMzY1LjljMCA4LjI3LTQuNCAxNS45Mi0xMS41NiAyMC4wOHoiLz4KICAgICAgPHBhdGggZmlsbD0idXJsKCNvKSIgZD0iTTE2MS45NCA3MDAuNTZhMjQgMjQgMCAwIDEtMjQuMTEgMEwzNi4zNSA2NDEuNmEyNCAyNCAwIDAgMS0xMS45NC0yMC43NVY1MDIuNjdhMjQgMjQgMCAwIDEgMTEuOTQtMjAuNzVsMTAxLjQ4LTU4Ljk2YTI0IDI0IDAgMCAxIDI0LjExIDBsMTAxLjQ3IDU4Ljk2YTI0IDI0IDAgMCAxIDExLjk1IDIwLjc1djExOC4xOGEyNCAyNCAwIDAgMS0xMS45NSAyMC43NXoiLz4KICAgICAgPHBhdGggc3Ryb2tlPSJ1cmwoI3ApIiBzdHJva2Utb3BhY2l0eT0iLjE3IiBzdHJva2Utd2lkdGg9IjEuNTUiIGQ9Ik0xNjEuNTUgNjk5LjlhMjMuMiAyMy4yIDAgMCAxLTIzLjM0IDBMMzYuNzQgNjQwLjkyYTIzLjIgMjMuMiAwIDAgMS0xMS41Ni0yMC4wOFY1MDIuNjdjMC04LjI4IDQuNC0xNS45MyAxMS41Ni0yMC4wOWwxMDEuNDctNTguOTVhMjMuMiAyMy4yIDAgMCAxIDIzLjM0IDBsMTAxLjQ3IDU4Ljk1YTIzLjIgMjMuMiAwIDAgMSAxMS41NiAyMC4wOXYxMTguMThjMCA4LjI4LTQuNCAxNS45My0xMS41NSAyMC4wOHoiLz4KICAgICAgPHBhdGggZmlsbD0idXJsKCNxKSIgc3Ryb2tlPSJ1cmwoI3IpIiBzdHJva2Utd2lkdGg9IjEuNTUiIGQ9Ik0xNzcxLjMxLTY4LjMzYTIzLjIgMjMuMiAwIDAgMSAyMy4zNCAwbDEwMS40OCA1OC45NmEyMy4yIDIzLjIgMCAwIDEgMTEuNTUgMjAuMDlWMTI4LjljMCA4LjI3LTQuNCAxNS45Mi0xMS41NSAyMC4wOGwtMTAxLjQ4IDU4Ljk2YTIzLjIgMjMuMiAwIDAgMS0yMy4zNCAwbC0xMDEuNDctNTguOTZhMjMuMiAyMy4yIDAgMCAxLTExLjU2LTIwLjA4VjEwLjcyYzAtOC4yOCA0LjQtMTUuOTMgMTEuNTYtMjAuMDl6Ii8+CiAgICAgIDxwYXRoIGZpbGw9InVybCgjcykiIHN0cm9rZT0idXJsKCN0KSIgc3Ryb2tlLXdpZHRoPSIxLjU1IiBkPSJNMTQ4NC40Mi02OC4zM2EyMy4yIDIzLjIgMCAwIDEgMjMuMzQgMGwxMDEuNDcgNTguOTZhMjMuMiAyMy4yIDAgMCAxIDExLjU2IDIwLjA5VjEyOC45YzAgOC4yNy00LjQgMTUuOTItMTEuNTYgMjAuMDhsLTEwMS40NyA1OC45NmEyMy4yIDIzLjIgMCAwIDEtMjMuMzQgMGwtMTAxLjQ3LTU4Ljk2YTIzLjIgMjMuMiAwIDAgMS0xMS41Ni0yMC4wOFYxMC43MmMwLTguMjggNC40LTE1LjkzIDExLjU2LTIwLjA5eiIvPgogICAgICA8cGF0aCBmaWxsPSJ1cmwoI3UpIiBkPSJNMTYyNi4xNCAxODAuOTRhMjQgMjQgMCAwIDEgMjQuMTEgMGwxMDEuNDcgNTguOTVhMjQgMjQgMCAwIDEgMTEuOTUgMjAuNzZ2MTE4LjE4YTI0IDI0IDAgMCAxLTExLjk1IDIwLjc1bC0xMDEuNDcgNTguOTZhMjQgMjQgMCAwIDEtMjQuMTEgMGwtMTAxLjQ4LTU4Ljk2YTI0IDI0IDAgMCAxLTExLjk0LTIwLjc1VjI2MC42NWEyNCAyNCAwIDAgMSAxMS45NC0yMC43NnoiLz4KICAgICAgPHBhdGggZmlsbD0idXJsKCN2KSIgc3Ryb2tlPSJ1cmwoI3cpIiBzdHJva2Utd2lkdGg9IjEuNTUiIGQ9Ik0xMjAyLjIyLTY4LjMzYTIzLjIgMjMuMiAwIDAgMSAyMy4zMyAwbDEwMS40OCA1OC45NmEyMy4yIDIzLjIgMCAwIDEgMTEuNTYgMjAuMDlWMTI4LjljMCA4LjI3LTQuNDEgMTUuOTItMTEuNTYgMjAuMDhsLTEwMS40OCA1OC45NmEyMy4yIDIzLjIgMCAwIDEtMjMuMzMgMGwtMTAxLjQ4LTU4Ljk2YTIzLjIgMjMuMiAwIDAgMS0xMS41Ni0yMC4wOFYxMC43MmMwLTguMjggNC40MS0xNS45MyAxMS41Ni0yMC4wOXoiLz4KICAgICAgPHBhdGggZmlsbD0idXJsKCN4KSIgZmlsbC1vcGFjaXR5PSIuNSIgZD0iTTEzNDYuNjIgMTgwLjk0YTI0IDI0IDAgMCAxIDI0LjExIDBsMTAxLjQ3IDU4Ljk1YTI0IDI0IDAgMCAxIDExLjk1IDIwLjc2djExOC4xOGEyNCAyNCAwIDAgMS0xMS45NSAyMC43NWwtMTAxLjQ3IDU4Ljk2YTI0IDI0IDAgMCAxLTI0LjExIDBsLTEwMS40OC01OC45NmEyNCAyNCAwIDAgMS0xMS45NC0yMC43NVYyNjAuNjVhMjQgMjQgMCAwIDEgMTEuOTQtMjAuNzZ6Ii8+CiAgICAgIDxwYXRoIGZpbGw9InVybCgjeSkiIGQ9Ik0xNzU4LjUyIDQzNi4yNmEyNCAyNCAwIDAgMSAyNC4xMSAwbDEwMS40OCA1OC45NWEyNCAyNCAwIDAgMSAxMS45NCAyMC43NnYxMTguMThhMjQgMjQgMCAwIDEtMTEuOTQgMjAuNzVsLTEwMS40OCA1OC45NmEyNCAyNCAwIDAgMS0yNC4xMSAwbC0xMDEuNDgtNTguOTZhMjQgMjQgMCAwIDEtMTEuOTQtMjAuNzVWNTE1Ljk3YTI0IDI0IDAgMCAxIDExLjk0LTIwLjc2eiIvPgogICAgICA8cGF0aCBzdHJva2U9InVybCgjeikiIHN0cm9rZS1vcGFjaXR5PSIuOSIgc3Ryb2tlLXdpZHRoPSIxLjU1IiBkPSJNMTc1OC45MSA0MzYuOTJhMjMuMiAyMy4yIDAgMCAxIDIzLjMzIDBsMTAxLjQ4IDU4Ljk2YTIzLjIgMjMuMiAwIDAgMSAxMS41NSAyMC4wOXYxMTguMThjMCA4LjI3LTQuNCAxNS45Mi0xMS41NSAyMC4wOGwtMTAxLjQ4IDU4Ljk2YTIzLjIgMjMuMiAwIDAgMS0yMy4zMyAwbC0xMDEuNDgtNTguOTZhMjMuMiAyMy4yIDAgMCAxLTExLjU2LTIwLjA4VjUxNS45N2MwLTguMjggNC40MS0xNS45MyAxMS41Ni0yMC4wOXoiLz4KICAgICAgPHBhdGggZmlsbD0idXJsKCNBKSIgZD0iTTE5MDMuMTkgMTgxLjNhMjQgMjQgMCAwIDEgMjQuMTEgMGwxMDEuNDcgNTguOTZhMjQgMjQgMCAwIDEgMTEuOTUgMjAuNzVWMzc5LjJhMjQgMjQgMCAwIDEtMTEuOTUgMjAuNzVMMTkyNy4zIDQ1OC45YTI0IDI0IDAgMCAxLTI0LjExIDBsLTEwMS40OC01OC45NWEyNCAyNCAwIDAgMS0xMS45NC0yMC43NVYyNjFhMjQgMjQgMCAwIDEgMTEuOTQtMjAuNzV6Ii8+CiAgICAgIDxwYXRoIHN0cm9rZT0idXJsKCNCKSIgc3Ryb2tlLW9wYWNpdHk9Ii44IiBzdHJva2Utd2lkdGg9IjEuNTUiIGQ9Ik0xOTAzLjU4IDE4MS45N2EyMy4yIDIzLjIgMCAwIDEgMjMuMzMgMGwxMDEuNDggNTguOTZhMjMuMiAyMy4yIDAgMCAxIDExLjU1IDIwLjA4VjM3OS4yYzAgOC4yNy00LjQgMTUuOTItMTEuNTUgMjAuMDhsLTEwMS40OCA1OC45NmEyMy4yIDIzLjIgMCAwIDEtMjMuMzMgMGwtMTAxLjQ4LTU4Ljk2YTIzLjIgMjMuMiAwIDAgMS0xMS41Ni0yMC4wOVYyNjEuMDFjMC04LjI3IDQuNDEtMTUuOTIgMTEuNTYtMjAuMDh6Ii8+CiAgICA8L2c+CiAgPC9nPgogIDxkZWZzPgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJiIiB4MT0iMTA1OSIgeDI9IjEwNTkiIHkxPSIxMTAzIiB5Mj0iLTE3NTAuNSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgogICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjMmMyYzJjIiBzdG9wLW9wYWNpdHk9IjAiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMmMyYzJjIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJkIiB4MT0iMjgyLjE0IiB4Mj0iMjgyLjE0IiB5MT0iOTU3Ljg2IiB5Mj0iNjY2LjI1IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CiAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMwOTA5MGIiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMjcyNzJhIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJlIiB4MT0iMjE2LjYyIiB4Mj0iMjMyLjcxIiB5MT0iNjU3Ljc3IiB5Mj0iODk1LjQ2IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CiAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiNmYWZhZmEiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDkwOTBiIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJmIiB4MT0iNDI2Ljk0IiB4Mj0iNDI2Ljk0IiB5MT0iNzA3LjkzIiB5Mj0iNDE2LjMyIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CiAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMyNzI3MmEiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDkwOTBiIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJnIiB4MT0iODUxLjI1IiB4Mj0iODUxLjI1IiB5MT0iOTU3Ljg2IiB5Mj0iNjY2LjI1IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CiAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMwOTA5MGIiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMjcyNzJhIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJoIiB4MT0iNzg1LjcyIiB4Mj0iODAxLjgxIiB5MT0iNjU3Ljc2IiB5Mj0iODk1LjQ2IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CiAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMwOTA5MGIiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMjcyNzJhIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJpIiB4MT0iNzA2LjQ1IiB4Mj0iNzA2Ljc4IiB5MT0iNzA3LjkzIiB5Mj0iNDAzLjk3IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CiAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMyNzI3MmEiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDkwOTBiIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJrIiB4MT0iNjA0LjM5IiB4Mj0iNDE0LjU4IiB5MT0iNjE5LjQiIHkyPSI5MjcuMzkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzA5MDkwYiIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM3MTcxN2EiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9ImwiIHgxPSI1NTkuNTIiIHgyPSI0NDcuNDIiIHkxPSI2NzEuNTQiIHkyPSI4ODEuMzgiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzA5MDkwYiIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNmZmYiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9Im0iIHgxPSIyOTQuNTYiIHgyPSIyOTQuNTYiIHkxPSI0NTIuNjEiIHkyPSIxNjEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzA5MDkwYiIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyNzI3MmEiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9Im4iIHgxPSIyMjkuMDMiIHgyPSIyNDUuMTIiIHkxPSIxNTIuNTIiIHkyPSIzOTAuMjEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iI2ZhZmFmYSIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwOTA5MGIiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9Im8iIHgxPSIxNDkuODgiIHgyPSIxNDkuODgiIHkxPSI3MDcuNTciIHkyPSI0MTUuOTUiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzA5MDkwYiIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyNzI3MmEiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9InAiIHgxPSI4NC4zNiIgeDI9IjEwMC40NCIgeTE9IjQwNy40NyIgeTI9IjY0NS4xNiIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgogICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjZmFmYWZhIi8+CiAgICAgIDxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzA5MDkwYiIvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0icSIgeDE9IjE3ODIuOTgiIHgyPSIxNzgyLjk4IiB5MT0iLTIiIHkyPSIyMTUuNjEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzA5MDkwYiIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyNzI3MmEiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9InIiIHgxPSIxODQ4LjUxIiB4Mj0iMTgzMi40MiIgeTE9IjIyNC4xIiB5Mj0iLTEzLjU5IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CiAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMzZjNmNDYiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDkwOTBiIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJzIiB4MT0iMTQ5Ni4wOSIgeDI9IjE0OTYuMDkiIHkxPSItMiIgeTI9IjIxNS42MSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgogICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjMDkwOTBiIi8+CiAgICAgIDxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzI3MjcyYSIvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0idCIgeDE9IjE1NjEuNjEiIHgyPSIxNTQ1LjUzIiB5MT0iMjI0LjEiIHkyPSItMTMuNTkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzNmM2Y0NiIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwOTA5MGIiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9InUiIHgxPSIxNjM4LjE5IiB4Mj0iMTYzOC4xOSIgeTE9IjE3My45MyIgeTI9IjQ2NS41NCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgogICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjMjcyNzJhIi8+CiAgICAgIDxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzA5MDkwYiIvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0idiIgeDE9IjEyMTMuODgiIHgyPSIxMjEzLjg4IiB5MT0iLTIiIHkyPSIyMTUuNjEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzA5MDkwYiIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyNzI3MmEiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9InciIHgxPSIxMjc5LjQxIiB4Mj0iMTI2My4zMiIgeTE9IjIyNC4xIiB5Mj0iLTEzLjU5IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CiAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMzZjNmNDYiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDkwOTBiIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJ4IiB4MT0iMTM1OC42NyIgeDI9IjEzNTguMzQiIHkxPSIxNzMuOTMiIHkyPSI0NzcuODkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzI3MjcyYSIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwOTA5MGIiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9InkiIHgxPSIxNzcwLjU3IiB4Mj0iMTc3MC41NyIgeTE9IjQyOS4yNSIgeTI9IjcyMC44NiIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgogICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjMDkwOTBiIi8+CiAgICAgIDxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzI3MjcyYSIvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0ieiIgeDE9IjE4MzYuMSIgeDI9IjE4MjAuMDEiIHkxPSI3MjkuMzUiIHkyPSI0OTEuNjUiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzcxNzE3YSIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwOTA5MGIiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9IkEiIHgxPSIxOTE1LjI0IiB4Mj0iMTkxNS4yNCIgeTE9IjE3NC4zIiB5Mj0iNDY1LjkxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CiAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMwOTA5MGIiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMjcyNzJhIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJCIiB4MT0iMTk4MC43NyIgeDI9IjE5NjQuNjgiIHkxPSI0NzQuMzkiIHkyPSIyMzYuNyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgogICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjNzE3MTdhIi8+CiAgICAgIDxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzA5MDkwYiIvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDxjbGlwUGF0aCBpZD0iYSI+CiAgICAgIDxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMjExOHYxMTAzSDB6Ii8+CiAgICA8L2NsaXBQYXRoPgogICAgPGZpbHRlciBpZD0iaiIgd2lkdGg9IjU0OC4wNCIgaGVpZ2h0PSI1ODEuMTkiIHg9IjI4Ny41OCIgeT0iNTY3LjI0IiBjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnM9InNSR0IiIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CiAgICAgIDxmZUZsb29kIGZsb29kLW9wYWNpdHk9IjAiIHJlc3VsdD0iQmFja2dyb3VuZEltYWdlRml4Ii8+CiAgICAgIDxmZUNvbG9yTWF0cml4IGluPSJTb3VyY2VBbHBoYSIgcmVzdWx0PSJoYXJkQWxwaGEiIHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMTI3IDAiLz4KICAgICAgPGZlT2Zmc2V0IGR5PSI0NS42NCIvPgogICAgICA8ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSI3NC4yNyIvPgogICAgICA8ZmVDb21wb3NpdGUgaW4yPSJoYXJkQWxwaGEiIG9wZXJhdG9yPSJvdXQiLz4KICAgICAgPGZlQ29sb3JNYXRyaXggdmFsdWVzPSIwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwLjE2IDAiLz4KICAgICAgPGZlQmxlbmQgaW4yPSJCYWNrZ3JvdW5kSW1hZ2VGaXgiIHJlc3VsdD0iZWZmZWN0MV9kcm9wU2hhZG93XzIyODJfNTc5MzYiLz4KICAgICAgPGZlQmxlbmQgaW49IlNvdXJjZUdyYXBoaWMiIGluMj0iZWZmZWN0MV9kcm9wU2hhZG93XzIyODJfNTc5MzYiIHJlc3VsdD0ic2hhcGUiLz4KICAgICAgPGZlQ29sb3JNYXRyaXggaW49IlNvdXJjZUFscGhhIiByZXN1bHQ9ImhhcmRBbHBoYSIgdmFsdWVzPSIwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAxMjcgMCIvPgogICAgICA8ZmVPZmZzZXQvPgogICAgICA8ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIzNC40NCIvPgogICAgICA8ZmVDb21wb3NpdGUgaW4yPSJoYXJkQWxwaGEiIGsyPSItMSIgazM9IjEiIG9wZXJhdG9yPSJhcml0aG1ldGljIi8+CiAgICAgIDxmZUNvbG9yTWF0cml4IHZhbHVlcz0iMCAwIDAgMCAxIDAgMCAwIDAgMSAwIDAgMCAwIDEgMCAwIDAgMC4xNCAwIi8+CiAgICAgIDxmZUJsZW5kIGluMj0ic2hhcGUiIHJlc3VsdD0iZWZmZWN0Ml9pbm5lclNoYWRvd18yMjgyXzU3OTM2Ii8+CiAgICA8L2ZpbHRlcj4KICA8L2RlZnM+Cjwvc3ZnPgo=" />
        </div>

        <!-- Page header -->
        <header class="page-header">
            <div class="page-header-logo">
                <svg width="78" height="28" viewBox="0 0 78 28" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <mask
                        id="mask0_hdr"
                        style="mask-type: luminance"
                        maskUnits="userSpaceOnUse"
                        x="30"
                        y="6"
                        width="48"
                        height="16">
                        <path d="M77.3953 6.70508H30.6836V21.5867H77.3953V6.70508Z" fill="white" />
                    </mask>
                    <g mask="url(#mask0_hdr)">
                        <path
                            d="M35.4451 21.2513V8.63531H30.748V6.7041H42.4032V8.63531H37.7063V21.2416H35.4451V21.2513Z"
                            fill="white" />
                        <path
                            d="M50.7885 16.4942H42.8113C42.8502 18.2216 43.8692 19.8326 45.9265 19.8326C47.7606 19.8326 48.469 18.6486 48.6535 17.9596H50.6915C50.1382 19.949 48.6146 21.4532 45.8876 21.4532C42.5881 21.4532 40.7637 19.1144 40.7637 15.941C40.7637 12.7676 42.7143 10.4482 45.8876 10.4482C49.061 10.4482 50.8079 12.5251 50.8079 15.7372C50.8079 16.0187 50.8079 16.3292 50.7885 16.4942ZM48.7311 14.922C48.7311 13.2917 47.5957 12.0786 45.8197 12.0786C44.1506 12.0786 42.9278 13.214 42.8113 14.922H48.7311Z"
                            fill="white" />
                        <path
                            d="M52.7969 17.688H54.8057C54.8833 18.8913 55.6209 19.823 57.5521 19.823C59.299 19.823 59.7647 19.0466 59.7647 18.2993C59.7647 16.999 58.377 16.8534 57.0378 16.572C55.223 16.1449 53.1559 15.6112 53.1559 13.4568C53.1559 11.6712 54.6019 10.4678 57.1057 10.4678C59.9492 10.4678 61.3174 11.9914 61.463 13.7867H59.4444C59.299 12.9909 58.872 12.0787 57.1446 12.0787C55.8053 12.0787 55.2327 12.6028 55.2327 13.3792C55.2327 14.4564 56.3875 14.5632 57.853 14.8834C59.7647 15.3298 61.8415 15.8829 61.8415 18.2023C61.8415 20.2112 60.2985 21.434 57.5716 21.434C54.4176 21.434 52.8551 19.8036 52.7871 17.688H52.7969Z"
                            fill="white" />
                        <path
                            d="M63.7149 17.688H65.7237C65.8013 18.8913 66.5388 19.823 68.4701 19.823C70.2169 19.823 70.6827 19.0466 70.6827 18.2993C70.6827 16.999 69.295 16.8534 67.9558 16.572C66.141 16.1449 64.0739 15.6112 64.0739 13.4568C64.0739 11.6712 65.5199 10.4678 68.0237 10.4678C70.8671 10.4678 72.2354 11.9914 72.381 13.7867H70.3624C70.2169 12.9909 69.7899 12.0787 68.0625 12.0787C66.7233 12.0787 66.1507 12.6028 66.1507 13.3792C66.1507 14.4564 67.3055 14.5632 68.7709 14.8834C70.6827 15.3298 72.7595 15.8829 72.7595 18.2023C72.7595 20.2112 71.2164 21.434 68.4895 21.434C65.3355 21.434 63.7731 19.8036 63.7051 17.688H63.7149Z"
                            fill="white" />
                        <path d="M75.332 21.2513V6.7041H77.3215V21.2513H75.332Z" fill="white" />
                    </g>
                    <path
                        d="M6.87137 12.2181C6.87168 11.9667 7.1427 11.8117 7.35901 11.9355L11.7957 14.5036V20.2812C11.7957 21.292 12.8941 21.9163 13.7598 21.4012L18.0221 18.8605V25.1769L13.7473 27.6516C12.9434 28.1161 11.9546 28.1161 11.1507 27.6516L6.87137 25.1769V12.2181ZM24.9025 19.7013C24.9024 20.6306 24.4075 21.4902 23.6037 21.9549L19.3256 24.4295V18.0857L24.9025 14.7588V19.7013ZM5.57365 17.9774H5.57023V24.4262L1.29885 21.9549C0.495145 21.4902 0.00016839 20.6305 0 19.7013V14.7554L5.57365 17.9774ZM23.6003 6.04969C24.404 6.51447 24.8992 7.37397 24.8992 8.3033V13.2446L13.5855 19.9918C13.3693 20.1227 13.0958 19.964 13.0956 19.7126V14.5115L18.5142 11.3739C19.1632 10.998 19.1664 10.0648 18.5211 9.68532L13.6846 6.83697L19.3221 3.5739L23.6003 6.04969ZM16.9021 10.2436C17.1183 10.3676 17.1184 10.6814 16.9021 10.8053L12.453 13.3802L7.03884 10.247C6.38961 9.8714 5.5777 10.3401 5.57365 11.0913V16.4746L0 13.2526V8.3033C0 7.37399 0.495181 6.51448 1.29885 6.04969L5.57707 3.57048L16.9021 10.2436ZM13.6846 6.83697L13.6823 6.83925V6.83583L13.6846 6.83697ZM11.1507 0.348424C11.9546 -0.116155 12.9434 -0.116127 13.7473 0.348424L18.0221 2.81966L12.3949 6.07589L6.87137 2.82307L11.1507 0.348424Z"
                        fill="white" />
                </svg>
                <span class="alpha-tag">Alpha</span>
            </div>
            <a class="page-header-link" href="https://tessl.io/registry" target="_blank" rel="noopener">
                https://tessl.io/registry
            </a>
        </header>

        <div class="shell" id="shell">
            <!-- Sidebar -->
            <nav class="sidebar" id="sidebar">
                <div class="sidebar-meta" id="sidebarMeta"></div>
                <div class="sidebar-divider"></div>
                <div class="sidebar-nav-label">Table of Contents</div>
                <div class="sidebar-nav" id="sidebarNav">
                    <a
                        class="sidebar-nav-item active"
                        data-section="section-overview"
                        onclick="scrollToSection('section-overview')">
                        Overview
                    </a>
                    <a
                        class="sidebar-nav-item"
                        data-section="section-readiness"
                        onclick="scrollToSection('section-readiness')">
                        Readiness
                    </a>
                    <a
                        class="sidebar-nav-item"
                        data-section="section-findings"
                        onclick="scrollToSection('section-findings')">
                        Findings
                        <span class="nav-count" id="navFindingCount">0</span>
                    </a>
                    <a
                        class="sidebar-nav-item"
                        data-section="section-context"
                        onclick="scrollToSection('section-context')">
                        Context inventory
                        <span class="nav-count" id="navContextCount">0</span>
                    </a>
                    <a
                        class="sidebar-nav-item"
                        data-section="section-analytics"
                        onclick="scrollToSection('section-analytics')">
                        Analytics
                    </a>
                    <a
                        class="sidebar-nav-item"
                        data-section="section-sources"
                        onclick="scrollToSection('section-sources')">
                        Data sources
                    </a>
                    <a
                        class="sidebar-nav-item"
                        data-section="section-methodology"
                        onclick="scrollToSection('section-methodology')">
                        Methodology
                    </a>
                </div>
            </nav>

            <!-- Main -->
            <div class="main">
                <div id="section-overview"></div>

                <!-- Readiness band -->
                <div class="readiness" id="section-readiness">
                    <div class="band-row">
                        <div class="band-indicator" id="bandIndicator"></div>
                        <div class="band-label" id="bandLabel">Unknown</div>
                    </div>
                    <div class="band-narrative" id="bandNarrative"></div>
                    <div class="band-explain" onclick="openCalcModal()">How is this calculated? &rarr;</div>
                </div>

                <!-- Calculation modal -->
                <div class="modal-overlay" id="calcModal" onclick="closeCalcModal()">
                    <div class="modal-box" onclick="event.stopPropagation()">
                        <button class="modal-close" onclick="closeCalcModal()">&times;</button>
                        <h3>How is readiness calculated?</h3>
                        <p>
                            The readiness band reflects how well this repository supports coding agents today, based on
                            the distribution of critical and high-severity findings across failure patterns that affect
                            agent performance, plus the share of developers and PRs they touch.
                        </p>
                        <div class="modal-band-item">
                            <strong style="color: var(--red)">Blocked</strong>
                            : Agents produce incorrect output with high confidence. Context is actively reducing
                            performance rather than supporting it.
                        </div>
                        <div class="modal-band-item">
                            <strong style="color: var(--yellow)">Constrained</strong>
                            : Agents handle routine tasks well but struggle with anything requiring
                            organisation-specific knowledge. Context exists but remains incomplete or inconsistent.
                        </div>
                        <div class="modal-band-item">
                            <strong style="color: var(--green)">Productive</strong>
                            : Agents handle the majority of tasks correctly. Context is well-structured, consistent, and
                            directly actionable.
                        </div>
                    </div>
                </div>

                <!-- Stats row -->
                <div class="stats-row" id="statsRow"></div>

                <!-- Findings -->
                <div class="section-divider" id="section-findings">
                    <div class="section-title">Findings</div>
                </div>

                <div class="filter-row">
                    <div class="search-box">
                        <input
                            type="text"
                            id="findingSearch"
                            placeholder="Search findings..."
                            oninput="applyFindingFilters()" />
                    </div>
                    <div class="dropdown-wrapper">
                        <button
                            class="dropdown-trigger"
                            id="categoryTrigger"
                            onclick="toggleDropdown('category', event)">
                            <span class="dropdown-trigger-label" id="categoryLabel"> All categories </span>
                            <span class="dropdown-trigger-arrow"></span>
                        </button>
                        <div class="dropdown-panel" id="categoryPanel"></div>
                    </div>
                    <div class="dropdown-wrapper">
                        <button
                            class="dropdown-trigger"
                            id="severityTrigger"
                            onclick="toggleDropdown('severity', event)">
                            <span class="dropdown-trigger-label" id="severityLabel"> All severities </span>
                            <span class="dropdown-trigger-arrow"></span>
                        </button>
                        <div class="dropdown-panel" id="severityPanel"></div>
                    </div>
                </div>

                <div class="filter-state-bar" id="findingsFilterState"></div>
                <div id="findingsList"></div>
                <div id="findingsEmpty" class="findings-empty" style="display: none">
                    No findings match the current filters.
                    <div class="findings-empty-action" onclick="clearAllFindingFilters()">Clear filters</div>
                </div>

                <!-- Context inventory -->
                <div class="section-divider" id="section-context">
                    <div class="section-title">Context Inventory</div>
                </div>
                <div id="contextInventoryRoot"></div>
                <div id="contextInventoryEmpty" class="ci-empty" style="display: none">
                    Context inventory will appear here once the analyzer publishes it.
                </div>

                <!-- Analytics -->
                <div class="section-divider" id="section-analytics">
                    <div class="section-title">Analytics</div>
                </div>
                <div>
                    <div class="section-label">Findings by category</div>
                    <div id="categoryBars"></div>
                    <div class="section-label" style="margin-top: 32px">Findings by severity</div>
                    <div id="severityBars"></div>
                </div>

                <!-- Data sources -->
                <div class="section-divider" id="section-sources"></div>
                <div>
                    <div class="section-title">What was analysed</div>

                    <div class="source-grid" id="sourceGrid"></div>

                    <div class="section-label" style="margin-top: 32px">Sources analysed</div>
                    <div class="source-tags" id="sourceTags"></div>

                    <div class="section-label" style="margin-top: 32px">Data sources</div>
                    <div
                        style="
                            display: flex;
                            flex-direction: column;
                            gap: 8px;
                            font-size: 14px;
                            color: var(--fg-subtle);
                        ">
                        <div style="display: flex; gap: 8px; align-items: baseline">
                            <span class="ev-pill">PR Scan</span>
                            <span>
                                Pattern-matched agent-generated PRs for deprecated APIs, undocumented wrappers, and
                                convention gaps.
                            </span>
                        </div>
                        <div style="display: flex; gap: 8px; align-items: baseline">
                            <span class="ev-pill">Agent Log</span>
                            <span>
                                Analysed session transcripts for fabricated routes, incorrect tool calls, and context
                                gaps.
                            </span>
                        </div>
                        <div style="display: flex; gap: 8px; align-items: baseline">
                            <span class="ev-pill">CI Data</span>
                            <span>
                                Correlated CI failures with agent-generated commits to surface systematic patterns.
                            </span>
                        </div>
                        <div style="display: flex; gap: 8px; align-items: baseline">
                            <span class="ev-pill">Static Analysis</span>
                            <span>
                                Scanned context files for conflicts, duplications, stale references, and signal-to-noise
                                issues.
                            </span>
                        </div>
                        <div style="display: flex; gap: 8px; align-items: baseline">
                            <span class="ev-pill">Code Review</span>
                            <span> Flagged reviewer comments on agent-generated code indicating knowledge gaps. </span>
                        </div>
                    </div>

                    <div class="section-label" style="margin-top: 32px">Findings by data source</div>
                    <div id="dataSourceBars"></div>
                </div>

                <!-- Methodology -->
                <div class="section-divider" id="section-methodology">
                    <div class="section-title">Methodology</div>
                </div>
                <div class="methodology">
                    <p>
                        This report aggregates findings from multiple data sources: source code analysis, git history,
                        GitHub data, agent context files, and agent session logs. Each finding is assessed for severity,
                        confidence, and impact on agent workflows.
                    </p>
                    <p>
                        Findings are categorised (Knowledge Gap, Conflicting Signals, Recurrent Failure, Structural
                        Complexity, Tooling Gap) and each carries a suggested remediation. The readiness band reflects
                        the distribution of critical and high-severity findings across the areas that affect agent
                        performance, plus the share of developers and PRs they touch.
                    </p>
                </div>
            </div>

            <!-- Right-side drill-down panel -->
            <div class="panel" id="panel">
                <div class="panel-inner" id="panelInner"></div>
                <div class="panel-close" onclick="closePanel()">&#10005;</div>
            </div>
        </div>

        <!-- Footer -->
        <footer class="site-footer">
            <div class="footer-inner">
                <div class="footer-logo">
                    <svg width="78" height="28" viewBox="0 0 78 28" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <mask
                            id="mask0_ftr"
                            style="mask-type: luminance"
                            maskUnits="userSpaceOnUse"
                            x="30"
                            y="6"
                            width="48"
                            height="16">
                            <path d="M77.3953 6.70508H30.6836V21.5867H77.3953V6.70508Z" fill="white" />
                        </mask>
                        <g mask="url(#mask0_ftr)">
                            <path
                                d="M35.4451 21.2513V8.63531H30.748V6.7041H42.4032V8.63531H37.7063V21.2416H35.4451V21.2513Z"
                                fill="white" />
                            <path
                                d="M50.7885 16.4942H42.8113C42.8502 18.2216 43.8692 19.8326 45.9265 19.8326C47.7606 19.8326 48.469 18.6486 48.6535 17.9596H50.6915C50.1382 19.949 48.6146 21.4532 45.8876 21.4532C42.5881 21.4532 40.7637 19.1144 40.7637 15.941C40.7637 12.7676 42.7143 10.4482 45.8876 10.4482C49.061 10.4482 50.8079 12.5251 50.8079 15.7372C50.8079 16.0187 50.8079 16.3292 50.7885 16.4942ZM48.7311 14.922C48.7311 13.2917 47.5957 12.0786 45.8197 12.0786C44.1506 12.0786 42.9278 13.214 42.8113 14.922H48.7311Z"
                                fill="white" />
                            <path
                                d="M52.7969 17.688H54.8057C54.8833 18.8913 55.6209 19.823 57.5521 19.823C59.299 19.823 59.7647 19.0466 59.7647 18.2993C59.7647 16.999 58.377 16.8534 57.0378 16.572C55.223 16.1449 53.1559 15.6112 53.1559 13.4568C53.1559 11.6712 54.6019 10.4678 57.1057 10.4678C59.9492 10.4678 61.3174 11.9914 61.463 13.7867H59.4444C59.299 12.9909 58.872 12.0787 57.1446 12.0787C55.8053 12.0787 55.2327 12.6028 55.2327 13.3792C55.2327 14.4564 56.3875 14.5632 57.853 14.8834C59.7647 15.3298 61.8415 15.8829 61.8415 18.2023C61.8415 20.2112 60.2985 21.434 57.5716 21.434C54.4176 21.434 52.8551 19.8036 52.7871 17.688H52.7969Z"
                                fill="white" />
                            <path
                                d="M63.7149 17.688H65.7237C65.8013 18.8913 66.5388 19.823 68.4701 19.823C70.2169 19.823 70.6827 19.0466 70.6827 18.2993C70.6827 16.999 69.295 16.8534 67.9558 16.572C66.141 16.1449 64.0739 15.6112 64.0739 13.4568C64.0739 11.6712 65.5199 10.4678 68.0237 10.4678C70.8671 10.4678 72.2354 11.9914 72.381 13.7867H70.3624C70.2169 12.9909 69.7899 12.0787 68.0625 12.0787C66.7233 12.0787 66.1507 12.6028 66.1507 13.3792C66.1507 14.4564 67.3055 14.5632 68.7709 14.8834C70.6827 15.3298 72.7595 15.8829 72.7595 18.2023C72.7595 20.2112 71.2164 21.434 68.4895 21.434C65.3355 21.434 63.7731 19.8036 63.7051 17.688H63.7149Z"
                                fill="white" />
                            <path d="M75.332 21.2513V6.7041H77.3215V21.2513H75.332Z" fill="white" />
                        </g>
                        <path
                            d="M6.87137 12.2181C6.87168 11.9667 7.1427 11.8117 7.35901 11.9355L11.7957 14.5036V20.2812C11.7957 21.292 12.8941 21.9163 13.7598 21.4012L18.0221 18.8605V25.1769L13.7473 27.6516C12.9434 28.1161 11.9546 28.1161 11.1507 27.6516L6.87137 25.1769V12.2181ZM24.9025 19.7013C24.9024 20.6306 24.4075 21.4902 23.6037 21.9549L19.3256 24.4295V18.0857L24.9025 14.7588V19.7013ZM5.57365 17.9774H5.57023V24.4262L1.29885 21.9549C0.495145 21.4902 0.00016839 20.6305 0 19.7013V14.7554L5.57365 17.9774ZM23.6003 6.04969C24.404 6.51447 24.8992 7.37397 24.8992 8.3033V13.2446L13.5855 19.9918C13.3693 20.1227 13.0958 19.964 13.0956 19.7126V14.5115L18.5142 11.3739C19.1632 10.998 19.1664 10.0648 18.5211 9.68532L13.6846 6.83697L19.3221 3.5739L23.6003 6.04969ZM16.9021 10.2436C17.1183 10.3676 17.1184 10.6814 16.9021 10.8053L12.453 13.3802L7.03884 10.247C6.38961 9.8714 5.5777 10.3401 5.57365 11.0913V16.4746L0 13.2526V8.3033C0 7.37399 0.495181 6.51448 1.29885 6.04969L5.57707 3.57048L16.9021 10.2436ZM13.6846 6.83697L13.6823 6.83925V6.83583L13.6846 6.83697ZM11.1507 0.348424C11.9546 -0.116155 12.9434 -0.116127 13.7473 0.348424L18.0221 2.81966L12.3949 6.07589L6.87137 2.82307L11.1507 0.348424Z"
                            fill="white" />
                    </svg>
                </div>

                <div class="footer-columns">
                    <div class="footer-col">
                        <div class="footer-col-title">Product</div>
                        <a href="https://tessl.io/registry" target="_blank" rel="noopener"> Registry </a>
                        <a href="https://tessl.io/enterprise/" target="_blank" rel="noopener"> Enterprise </a>
                        <a href="https://docs.tessl.io/" target="_blank" rel="noopener"> Docs </a>
                        <a href="https://tesslstatus.io/" target="_blank" rel="noopener"> System Status </a>
                    </div>
                    <div class="footer-col">
                        <div class="footer-col-title">Company</div>
                        <a href="https://tessl.io/about/" target="_blank" rel="noopener"> About </a>
                        <a href="https://tessl.io/careers/#job-listings" target="_blank" rel="noopener"> Careers </a>
                        <a href="https://tessl.gitbook.io/tessl-press-kit" target="_blank" rel="noopener">
                            Press Kit
                        </a>
                        <a href="https://tessl.io/policies/privacy-cookies/" target="_blank" rel="noopener">
                            Cookie Notice &amp; Privacy Policy
                        </a>
                        <a href="https://tessl.io/policies/terms/" target="_blank" rel="noopener"> Terms of Service </a>
                    </div>
                    <div class="footer-col">
                        <div class="footer-col-title">Community</div>
                        <a href="https://tessl.io/blog/" target="_blank" rel="noopener"> News &amp; Articles </a>
                        <a href="https://tessl.io/podcast/" target="_blank" rel="noopener"> Podcast </a>
                        <a href="https://tessl.io/events/" target="_blank" rel="noopener"> Events </a>
                        <a href="https://tessl.io/devcon/" target="_blank" rel="noopener"> AI Native DevCon </a>
                    </div>
                    <div class="footer-col">
                        <div class="footer-col-title">Connect</div>
                        <a href="https://linkedin.com/company/tesslio/" target="_blank" rel="noopener"> LinkedIn </a>
                        <a href="https://x.com/tessl_io" target="_blank" rel="noopener"> X (Twitter) </a>
                        <a href="https://discord.com/invite/jbb2vHnHZQ" target="_blank" rel="noopener"> Discord </a>
                        <a href="https://www.youtube.com/@tessl-ai" target="_blank" rel="noopener"> YouTube </a>
                    </div>
                </div>

                <div class="footer-address">Tessl AI Ltd, 210 Pentonville Road, London, UK</div>
            </div>
        </footer>

        <script>
            const DATA = /*FINDINGS_JSON*/ {}; /*END_FINDINGS_JSON*/
        </script>

        <script>
            (function () {
                var findings = DATA.findings || [];
                var meta = DATA.metadata || {};
                var summary = DATA.summary || {};
                var overall = DATA.overall_score || null;
                var execSummary = DATA.executive_summary || "";

                var CATEGORY_NAMES = {
                    KCG: "Knowledge Gap",
                    CAS: "Conflicting Signals",
                    SCX: "Structural Complexity",
                    RAF: "Recurrent Failure",
                    TCG: "Tooling Gap",
                };
                var CATEGORY_DESC = {
                    KCG: "Undocumented APIs, patterns, tribal knowledge, or stale docs",
                    CAS: "Context files, conventions, or configs that contradict each other",
                    SCX: "Deep coupling, circular deps, non-obvious build or navigation",
                    RAF: "Areas where agents repeatedly err, iterate, or get reverted",
                    TCG: "Missing context files, MCP integrations, skills, or rules",
                };
                var SEVERITY_DESC = {
                    critical: "Blocks productive work or produces confident errors",
                    high: "Regularly degrades agent output quality or requires correction",
                    medium: "Noticeable friction, but agents can still make progress",
                    low: "Minor polish or edge-case issue worth tracking",
                };
                var SOURCE_LABELS = {
                    source_code: "Source Code",
                    git_history: "Git History",
                    github_data: "GitHub Data",
                    agent_logs: "Agent Logs",
                    agent_context: "Agent Context",
                };
                var TOOL_LABELS = {
                    claude_code: "Claude Code",
                    cursor: "Cursor",
                    copilot: "Copilot",
                    gemini_cli: "Gemini CLI",
                };

                function esc(s) {
                    if (s == null) return "";
                    var d = document.createElement("div");
                    d.textContent = String(s);
                    return d.innerHTML;
                }

                function renderInlineMd(text) {
                    var t = esc(text || "");
                    t = t.replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>");
                    t = t.replace(/`([^`]+)`/g, "<code>$1</code>");
                    t = t.replace(/\n\n+/g, "<br><br>");
                    return t;
                }

                function formatDate(iso) {
                    if (!iso) return "N/A";
                    try {
                        var d = new Date(iso);
                        if (isNaN(d.getTime())) return iso;
                        var months = [
                            "Jan",
                            "Feb",
                            "Mar",
                            "Apr",
                            "May",
                            "Jun",
                            "Jul",
                            "Aug",
                            "Sep",
                            "Oct",
                            "Nov",
                            "Dec",
                        ];
                        var hh = String(d.getUTCHours()).padStart(2, "0");
                        var mm = String(d.getUTCMinutes()).padStart(2, "0");
                        return (
                            d.getUTCDate() +
                            " " +
                            months[d.getUTCMonth()] +
                            " " +
                            d.getUTCFullYear() +
                            " · " +
                            hh +
                            ":" +
                            mm +
                            " UTC"
                        );
                    } catch (e) {
                        return iso;
                    }
                }

                function githubUrlFor(action) {
                    if (!meta.repository) return null;
                    if (!/^[\w.-]+\/[\w.-]+$/.test(meta.repository)) return null;
                    var base = "https://github.com/" + meta.repository;
                    if (action === "repo") return base;
                    if (action === "prs") return base + "/pulls?q=is%3Apr+is%3Amerged";
                    if (action === "actions") return base + "/actions";
                    return base;
                }

                // Expose helpers for event handlers declared below
                var contextInventoryData =
                    DATA.context_inventory && Array.isArray(DATA.context_inventory.files)
                        ? DATA.context_inventory.files
                        : [];
                window.__reportData = {
                    findings: findings,
                    meta: meta,
                    summary: summary,
                    overall: overall,
                    execSummary: execSummary,
                    CATEGORY_NAMES: CATEGORY_NAMES,
                    SOURCE_LABELS: SOURCE_LABELS,
                    contextInventory: contextInventoryData,
                    esc: esc,
                };

                // ── Sidebar meta ──
                function renderSidebarMeta() {
                    var el = document.getElementById("sidebarMeta");
                    el.innerHTML =
                        '<div class="sidebar-meta-item"><strong>Repository</strong></div>' +
                        '<div class="sidebar-meta-item" style="color: var(--fg-muted); margin-top: -2px">' +
                        esc(meta.repository || "Unknown") +
                        "</div>" +
                        '<div class="sidebar-meta-item" style="margin-top: 6px"><strong>Generated</strong></div>' +
                        '<div class="sidebar-meta-item" style="color: var(--fg-muted); margin-top: -2px">' +
                        esc(formatDate(meta.generated_at)) +
                        "</div>";
                    document.getElementById("navFindingCount").textContent = findings.length;
                    var allCi =
                        DATA.context_inventory && Array.isArray(DATA.context_inventory.files)
                            ? DATA.context_inventory.files
                            : [];
                    // Match the default file-tree view: exclude tessl-vendored files (under .tessl/** or basename tessl__*).
                    var visibleCi = allCi.filter(function (f) {
                        return !ciIsTesslPath(f.path);
                    }).length;
                    document.getElementById("navContextCount").textContent = visibleCi;
                }

                // ── Readiness band ──
                function renderReadiness() {
                    var level = (overall && overall.level) || null;
                    var indicator = document.getElementById("bandIndicator");
                    var lbl = document.getElementById("bandLabel");
                    if (level) {
                        indicator.innerHTML =
                            '<div class="band-seg blocked' +
                            (level === "blocked" ? " active" : "") +
                            '"></div>' +
                            '<div class="band-seg constrained' +
                            (level === "constrained" ? " active" : "") +
                            '"></div>' +
                            '<div class="band-seg productive' +
                            (level === "productive" ? " active" : "") +
                            '"></div>';
                        lbl.className = "band-label " + level;
                        lbl.textContent = level.charAt(0).toUpperCase() + level.slice(1);
                    } else {
                        indicator.innerHTML =
                            '<div class="band-seg blocked"></div>' +
                            '<div class="band-seg constrained"></div>' +
                            '<div class="band-seg productive"></div>';
                        lbl.textContent = "Unknown";
                        lbl.className = "band-label";
                    }
                    var narrative = execSummary || (overall && overall.reasoning) || "";
                    document.getElementById("bandNarrative").innerHTML = renderInlineMd(narrative);
                }

                // ── Stats row ──
                function renderStats() {
                    var tiles = [];
                    var total = summary.total_findings != null ? summary.total_findings : findings.length;
                    tiles.push({ value: total, label: "Findings" });

                    var crit = summary.by_severity && summary.by_severity.critical;
                    if (crit == null) {
                        crit = findings.filter(function (f) {
                            return (f.impact && f.impact.level) === "critical";
                        }).length;
                    }
                    tiles.push({ value: crit, label: "Critical" });

                    if (summary.commit_authors_impacted && summary.commit_authors_impacted.total != null) {
                        var cai = summary.commit_authors_impacted;
                        tiles.push({
                            value: cai.value + "/" + cai.total,
                            label: "Commit authors impacted",
                        });
                    }
                    if (
                        summary.sessions_with_frustration_signals &&
                        summary.sessions_with_frustration_signals.total != null
                    ) {
                        var swfs = summary.sessions_with_frustration_signals;
                        tiles.push({
                            value: swfs.value + "/" + swfs.total,
                            label: "Sessions with frustration",
                        });
                    }

                    document.getElementById("statsRow").innerHTML = tiles
                        .map(function (t) {
                            return (
                                '<div class="stat-item"><div class="stat-value">' +
                                esc(t.value) +
                                '</div><div class="stat-label">' +
                                esc(t.label) +
                                "</div></div>"
                            );
                        })
                        .join("");
                }

                // ── Findings filter dropdowns ──
                function renderFilterDropdowns() {
                    var catCounts = {};
                    findings.forEach(function (f) {
                        catCounts[f.category] = (catCounts[f.category] || 0) + 1;
                    });

                    var catHTML =
                        '<div class="dropdown-option selected" data-value="all" onclick="handleDropdownOption(\'category\', \'all\')">' +
                        '<div class="dropdown-checkbox"></div>' +
                        '<div class="dropdown-option-body">' +
                        '<div class="dropdown-option-label">All categories</div>' +
                        '<div class="dropdown-option-desc">Show findings from every category</div>' +
                        "</div>" +
                        '<div class="dropdown-option-count">' +
                        findings.length +
                        "</div>" +
                        '</div><div class="dropdown-divider"></div>';
                    Object.keys(CATEGORY_NAMES).forEach(function (code) {
                        var n = catCounts[code] || 0;
                        catHTML +=
                            '<div class="dropdown-option" data-value="' +
                            esc(code) +
                            "\" onclick=\"handleDropdownOption('category', '" +
                            esc(code) +
                            "')\">" +
                            '<div class="dropdown-checkbox"></div>' +
                            '<div class="dropdown-option-body">' +
                            '<div class="dropdown-option-label">' +
                            esc(CATEGORY_NAMES[code]) +
                            "</div>" +
                            '<div class="dropdown-option-desc">' +
                            esc(CATEGORY_DESC[code]) +
                            "</div>" +
                            "</div>" +
                            '<div class="dropdown-option-count">' +
                            n +
                            "</div>" +
                            "</div>";
                    });
                    document.getElementById("categoryPanel").innerHTML = catHTML;

                    var sevCounts = summary.by_severity || {};
                    ["critical", "high", "medium", "low"].forEach(function (sev) {
                        if (!(sev in sevCounts)) {
                            sevCounts[sev] = findings.filter(function (f) {
                                return (f.impact && f.impact.level) === sev;
                            }).length;
                        }
                    });
                    var sevHTML =
                        '<div class="dropdown-option selected" data-value="all" onclick="handleDropdownOption(\'severity\', \'all\')">' +
                        '<div class="dropdown-checkbox"></div>' +
                        '<div class="dropdown-option-body">' +
                        '<div class="dropdown-option-label">All severities</div>' +
                        '<div class="dropdown-option-desc">Show findings at every severity level</div>' +
                        "</div>" +
                        '<div class="dropdown-option-count">' +
                        findings.length +
                        "</div>" +
                        '</div><div class="dropdown-divider"></div>';
                    ["critical", "high", "medium", "low"].forEach(function (sev) {
                        var n = sevCounts[sev] || 0;
                        sevHTML +=
                            '<div class="dropdown-option" data-value="' +
                            sev +
                            "\" onclick=\"handleDropdownOption('severity', '" +
                            sev +
                            "')\">" +
                            '<div class="dropdown-checkbox"></div>' +
                            '<div class="dropdown-option-body">' +
                            '<div class="dropdown-option-label">' +
                            sev.charAt(0).toUpperCase() +
                            sev.slice(1) +
                            "</div>" +
                            '<div class="dropdown-option-desc">' +
                            esc(SEVERITY_DESC[sev]) +
                            "</div>" +
                            "</div>" +
                            '<div class="dropdown-option-count">' +
                            n +
                            "</div>" +
                            "</div>";
                    });
                    document.getElementById("severityPanel").innerHTML = sevHTML;
                }

                // ── Findings list ──
                function renderFindings() {
                    var sorted = findings.slice().sort(function (a, b) {
                        return (b.priority_score || 0) - (a.priority_score || 0);
                    });
                    document.getElementById("findingsList").innerHTML = sorted
                        .map(function (f) {
                            var sev = (f.impact && f.impact.level) || "medium";
                            var catName = CATEGORY_NAMES[f.category] || f.category || "Uncategorised";
                            return (
                                '<div class="finding-row" data-category="' +
                                esc(f.category) +
                                '" data-severity="' +
                                esc(sev) +
                                '" onclick="openPanel(\'' +
                                esc(f.id) +
                                "')\">" +
                                '<span class="finding-desc">' +
                                esc(f.title) +
                                "</span>" +
                                '<span class="finding-badge">' +
                                esc(catName) +
                                "</span>" +
                                '<span class="finding-priority ' +
                                esc(sev) +
                                '">' +
                                esc(sev.charAt(0).toUpperCase() + sev.slice(1)) +
                                "</span>" +
                                "</div>"
                            );
                        })
                        .join("");
                }

                // ── Analytics ──
                function renderAnalytics() {
                    var catCounts = {};
                    findings.forEach(function (f) {
                        catCounts[f.category] = (catCounts[f.category] || 0) + 1;
                    });
                    var catValues = Object.keys(CATEGORY_NAMES).map(function (c) {
                        return catCounts[c] || 0;
                    });
                    var maxCat = Math.max.apply(null, catValues.concat([1]));
                    var catHTML = "";
                    Object.keys(CATEGORY_NAMES).forEach(function (code) {
                        var n = catCounts[code] || 0;
                        catHTML +=
                            '<div class="source-bar-row">' +
                            '<div class="source-bar-label">' +
                            esc(CATEGORY_NAMES[code]) +
                            "</div>" +
                            '<div class="source-bar-container"><div class="source-bar-fill" style="width:' +
                            (n / maxCat) * 100 +
                            '%"></div></div>' +
                            '<div class="source-bar-count">' +
                            n +
                            "</div>" +
                            "</div>";
                    });
                    document.getElementById("categoryBars").innerHTML = catHTML;

                    var sevCounts = summary.by_severity || {};
                    ["critical", "high", "medium", "low"].forEach(function (sev) {
                        if (!(sev in sevCounts)) {
                            sevCounts[sev] = findings.filter(function (f) {
                                return (f.impact && f.impact.level) === sev;
                            }).length;
                        }
                    });
                    var sevMax = Math.max.apply(
                        null,
                        ["critical", "high", "medium", "low"]
                            .map(function (s) {
                                return sevCounts[s] || 0;
                            })
                            .concat([1]),
                    );
                    var sevColors = {
                        critical: "#f87171",
                        high: "#fbbf24",
                        medium: "#facc15",
                        low: "var(--blue)",
                    };
                    var sevHTML = "";
                    ["critical", "high", "medium", "low"].forEach(function (sev) {
                        var n = sevCounts[sev] || 0;
                        sevHTML +=
                            '<div class="source-bar-row">' +
                            '<div class="source-bar-label">' +
                            sev.charAt(0).toUpperCase() +
                            sev.slice(1) +
                            "</div>" +
                            '<div class="source-bar-container"><div class="source-bar-fill" style="background:' +
                            sevColors[sev] +
                            "; width:" +
                            (n / sevMax) * 100 +
                            '%"></div></div>' +
                            '<div class="source-bar-count">' +
                            n +
                            "</div>" +
                            "</div>";
                    });
                    document.getElementById("severityBars").innerHTML = sevHTML;
                }

                // ── Source grid + tags + findings by source ──
                function renderSources() {
                    var dsu = meta.data_sources_used || [];
                    var agentLogEntries = dsu.filter(function (d) {
                        return d.source === "agent_logs";
                    });

                    var tiles = [];
                    var total = summary.total_findings != null ? summary.total_findings : findings.length;
                    tiles.push({ value: total, label: "Findings" });
                    if (agentLogEntries.length > 0) {
                        tiles.push({
                            value: agentLogEntries.length,
                            label: agentLogEntries.length === 1 ? "Agent Session" : "Agent Sessions",
                        });
                    }
                    document.getElementById("sourceGrid").innerHTML = tiles
                        .map(function (t) {
                            return (
                                '<div class="source-stat"><div class="source-num">' +
                                esc(t.value) +
                                '</div><div class="source-label">' +
                                esc(t.label) +
                                "</div></div>"
                            );
                        })
                        .join("");

                    // Source tags (one per distinct source present in data_sources_used)
                    var order = ["source_code", "git_history", "github_data", "agent_logs", "agent_context"];
                    var sourcesSeen = {};
                    dsu.forEach(function (d) {
                        sourcesSeen[d.source] = (sourcesSeen[d.source] || 0) + 1;
                    });

                    var tagsHTML = "";
                    order.forEach(function (src) {
                        if (!(src in sourcesSeen)) return;
                        var label = SOURCE_LABELS[src] || src;
                        var content = esc(label);
                        if (src === "source_code") {
                            var url = githubUrlFor("repo");
                            if (url)
                                content += ' <a href="' + url + '" target="_blank" rel="noopener">Browse &rarr;</a>';
                        } else if (src === "git_history") {
                            var url2 = githubUrlFor("prs");
                            if (url2)
                                content += ' <a href="' + url2 + '" target="_blank" rel="noopener">View PRs &rarr;</a>';
                        } else if (src === "github_data") {
                            var url3 = githubUrlFor("actions");
                            if (url3)
                                content += ' <a href="' + url3 + '" target="_blank" rel="noopener">CI runs &rarr;</a>';
                        } else if (src === "agent_logs") {
                            var tools = [];
                            agentLogEntries.forEach(function (d) {
                                (d.tools || []).forEach(function (t) {
                                    if (tools.indexOf(t) === -1) tools.push(t);
                                });
                            });
                            var toolLabels = tools.map(function (t) {
                                return TOOL_LABELS[t] || t;
                            });
                            var n = agentLogEntries.length;
                            var sessionLabel = n + " " + (n === 1 ? "session" : "sessions");
                            if (toolLabels.length) sessionLabel += " from " + toolLabels.join(" & ");
                            content = esc(label) + " &middot; " + esc(sessionLabel);
                        } else if (src === "agent_context") {
                            content =
                                esc(label) + " &middot; context files across AGENTS.md, rules, hooks, skills, MCP";
                        }
                        tagsHTML += '<div class="source-tag">' + content + "</div>";
                    });
                    document.getElementById("sourceTags").innerHTML = tagsHTML;

                    // Findings by data source (aggregate contributions by source)
                    var agg = {};
                    dsu.forEach(function (d) {
                        if (d.source === "context_inventory") return;
                        agg[d.source] = (agg[d.source] || 0) + (d.findings_contributed || 0);
                    });
                    var sortedSrc = Object.keys(agg).sort(function (a, b) {
                        return agg[b] - agg[a];
                    });
                    var aggMax = Math.max.apply(
                        null,
                        sortedSrc
                            .map(function (s) {
                                return agg[s];
                            })
                            .concat([1]),
                    );
                    var barsHTML = "";
                    sortedSrc.forEach(function (src) {
                        var n = agg[src];
                        barsHTML +=
                            '<div class="source-bar-row">' +
                            '<div class="source-bar-label">' +
                            esc(SOURCE_LABELS[src] || src) +
                            "</div>" +
                            '<div class="source-bar-container"><div class="source-bar-fill" style="width:' +
                            (n / aggMax) * 100 +
                            '%"></div></div>' +
                            '<div class="source-bar-count">' +
                            n +
                            "</div>" +
                            "</div>";
                    });
                    document.getElementById("dataSourceBars").innerHTML = barsHTML;
                }

                // ── Context inventory ──
                var CI_CATEGORIES = [
                    {
                        key: "entry_point",
                        label: "Entry points",
                        badge: "Entry point",
                        desc: "Files agents read first — AGENTS.md, CLAUDE.md",
                    },
                    {
                        key: "always_on_rule",
                        label: "Always-on rules",
                        badge: "Rule",
                        desc: "Rules loaded into every session",
                    },
                    {
                        key: "hook",
                        label: "Hooks",
                        badge: "Hook",
                        desc: "Event handlers for tool use or session events",
                    },
                    {
                        key: "skill",
                        label: "Skills",
                        badge: "Skill",
                        desc: "Capabilities available via SKILL.md",
                    },
                    {
                        key: "mcp",
                        label: "MCP",
                        badge: "MCP",
                        desc: "Model Context Protocol server configurations",
                    },
                    {
                        key: "referenced_doc",
                        label: "Referenced docs",
                        badge: "Referenced",
                        desc: "Docs linked from other context files",
                    },
                    {
                        key: "plugin",
                        label: "Plugins",
                        badge: "Plugin",
                        desc: "Tessl tiles bundling multiple skills and rules",
                    },
                ];
                var CI_HARNESSES = [
                    {
                        key: "claude",
                        label: "Claude",
                        desc: "Context files and configs read by Claude Code",
                    },
                    {
                        key: "cursor",
                        label: "Cursor",
                        desc: "Context files and configs read by Cursor",
                    },
                ];
                var CI_CATEGORY_BADGE = {};
                CI_CATEGORIES.forEach(function (c) {
                    CI_CATEGORY_BADGE[c.key] = c.badge;
                });

                function ciDirname(p) {
                    if (!p) return ".";
                    var i = p.lastIndexOf("/");
                    if (i < 0) return ".";
                    return p.slice(0, i) || "/";
                }
                function ciBasename(p) {
                    if (!p) return "";
                    var i = p.lastIndexOf("/");
                    return i < 0 ? p : p.slice(i + 1);
                }
                function ciIsTesslPath(p) {
                    if (!p) return false;
                    if (p === ".tessl" || p.startsWith(".tessl/") || p.indexOf("/.tessl/") !== -1) return true;
                    return ciBasename(p).indexOf("tessl__") === 0;
                }
                function ciExpandAgents(a) {
                    if (Array.isArray(a) && a.indexOf("cross-agent") !== -1) return ["claude", "cursor"];
                    return Array.isArray(a)
                        ? a.filter(function (x) {
                              return x === "claude" || x === "cursor";
                          })
                        : [];
                }
                function ciFormatTokens(n) {
                    if (n == null) return "~? tokens";
                    return "~" + n + " tokens";
                }

                function renderContextInventory() {
                    var inv = DATA.context_inventory;
                    var root = document.getElementById("contextInventoryRoot");
                    var emptyEl = document.getElementById("contextInventoryEmpty");
                    if (!inv || !Array.isArray(inv.files) || inv.files.length === 0) {
                        if (emptyEl) emptyEl.style.display = "";
                        return;
                    }
                    if (emptyEl) emptyEl.style.display = "none";
                    root.innerHTML = "";
                    var fileTokens = inv.file_tokens && typeof inv.file_tokens === "object" ? inv.file_tokens : {};

                    var selectedTypes = [];
                    var selectedHarnesses = [];
                    var showTesslTiles = false;
                    var searchQuery = "";

                    // ── Filter bar: search + type dropdown + harness dropdown + tessl chip
                    var filterBar = document.createElement("div");
                    filterBar.className = "filter-row";

                    var searchBox = document.createElement("div");
                    searchBox.className = "search-box";
                    searchBox.innerHTML = '<input type="text" placeholder="Search context..." />';
                    searchBox.querySelector("input").addEventListener("input", function () {
                        searchQuery = this.value.toLowerCase().trim();
                        applyFilters();
                    });
                    filterBar.appendChild(searchBox);

                    var typeDD = buildDropdown("ciType", "All types", CI_CATEGORIES, function (vals) {
                        selectedTypes = vals;
                        applyFilters();
                    });
                    filterBar.appendChild(typeDD.wrapper);

                    var harnessDD = buildDropdown("ciHarness", "All harnesses", CI_HARNESSES, function (vals) {
                        selectedHarnesses = vals;
                        applyFilters();
                    });
                    filterBar.appendChild(harnessDD.wrapper);

                    var tesslTileCount = inv.files.filter(function (f) {
                        return ciIsTesslPath(f.path);
                    }).length;
                    var tesslBtn = document.createElement("button");
                    tesslBtn.className = "ci-tessl-chip";
                    tesslBtn.type = "button";
                    tesslBtn.setAttribute("aria-pressed", "false");
                    tesslBtn.setAttribute("title", "Toggle Tessl-installed context");
                    var TESSL_PLUS_ICON = "+";
                    var TESSL_CHECK_ICON =
                        '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>';
                    function renderTesslBtn() {
                        tesslBtn.innerHTML =
                            '<span class="ci-tessl-chip-icon">' +
                            (showTesslTiles ? TESSL_CHECK_ICON : TESSL_PLUS_ICON) +
                            "</span><span>" +
                            (showTesslTiles ? "Tessl included" : "Tessl") +
                            '</span><span class="ci-tessl-chip-count">' +
                            tesslTileCount +
                            "</span>";
                    }
                    renderTesslBtn();
                    tesslBtn.addEventListener("click", function () {
                        showTesslTiles = !showTesslTiles;
                        tesslBtn.classList.toggle("active", showTesslTiles);
                        tesslBtn.setAttribute("aria-pressed", showTesslTiles ? "true" : "false");
                        renderTesslBtn();
                        applyFilters();
                    });
                    filterBar.appendChild(tesslBtn);

                    root.appendChild(filterBar);

                    // ── Tree ──
                    function fileGroupOf(p) {
                        var parent = ciDirname(p);
                        if (parent && /\.(json|jsonc|toml|yaml|yml)$/.test(parent)) {
                            return { file: parent, entryName: ciBasename(p) };
                        }
                        return { file: p, entryName: null };
                    }

                    var fileMap = new Map();
                    var fileOrder = [];
                    inv.files.forEach(function (f) {
                        var g = fileGroupOf(f.path);
                        if (!fileMap.has(g.file)) {
                            fileMap.set(g.file, []);
                            fileOrder.push(g.file);
                        }
                        fileMap.get(g.file).push(Object.assign({}, f, { _entryName: g.entryName }));
                    });
                    fileOrder.sort(function (a, b) {
                        var aRoot = a.indexOf("/") === -1;
                        var bRoot = b.indexOf("/") === -1;
                        if (aRoot !== bRoot) return aRoot ? -1 : 1;
                        return a.localeCompare(b);
                    });

                    var tree = document.createElement("div");
                    tree.className = "ci-list";

                    function dotClass(u) {
                        return u === "high" ? "ci-dot-useful" : u === "medium" ? "ci-dot-partial" : "ci-dot-unused";
                    }
                    function entryLabel(f) {
                        if (f._entryName) return esc(f._entryName);
                        var base = ciBasename(f.path);
                        var stem = base.replace(/\.(md|mdc|json|jsonc|toml|yaml|yml|txt)$/i, "");
                        return esc(stem || base);
                    }

                    function fileTokensFor(file, entries) {
                        // Prefer explicit file_tokens map, fall back to the first entry whose
                        // tokens field matches the grouped file, else undefined.
                        if (file in fileTokens) return fileTokens[file];
                        for (var i = 0; i < entries.length; i++) {
                            if (entries[i].tokens != null && entries[i].path === file) return entries[i].tokens;
                        }
                        for (var j = 0; j < entries.length; j++) {
                            if (entries[j].tokens != null) return entries[j].tokens;
                        }
                        return null;
                    }

                    fileOrder.forEach(function (file) {
                        var entries = fileMap.get(file);
                        var fileEl = document.createElement("div");
                        var isTesslFile = ciIsTesslPath(file);
                        fileEl.className = isTesslFile ? "ci-file ci-file-plugin" : "ci-file";
                        fileEl.dataset.file = file;
                        if (isTesslFile) fileEl.dataset.tessl = "1";
                        var pluginKey = (function () {
                            var m = file.match(/^\.tessl\/tiles\/([^\/]+)\/([^\/]+)/);
                            return m ? m[1] + "/" + m[2] : null;
                        })();
                        if (isTesslFile && pluginKey) {
                            fileEl.dataset.plugin = pluginKey;
                            fileEl.addEventListener("click", function () {
                                openContextPluginPanel(pluginKey);
                            });
                        }

                        var agentsSet = new Set();
                        entries.forEach(function (e) {
                            ciExpandAgents(e.agents).forEach(function (a) {
                                agentsSet.add(a);
                            });
                        });
                        fileEl.dataset.agents = [...agentsSet].join(",");

                        var fileHarnessHtml = "";
                        // Prefer "Cross-agent" when both harnesses apply.
                        if (agentsSet.has("claude") && agentsSet.has("cursor")) {
                            fileHarnessHtml = '<span class="ci-entry-harness">Cross-agent</span>';
                        } else if (agentsSet.has("claude")) {
                            fileHarnessHtml = '<span class="ci-entry-harness">Claude</span>';
                        } else if (agentsSet.has("cursor")) {
                            fileHarnessHtml = '<span class="ci-entry-harness">Cursor</span>';
                        }

                        var tokens = fileTokensFor(file, entries);
                        var headerEl = document.createElement("div");
                        headerEl.className = "ci-file-header";
                        headerEl.innerHTML =
                            '<span class="ci-file-path">' +
                            esc(file) +
                            "</span>" +
                            '<span class="ci-file-meta">' +
                            '<span class="ci-file-tokens">' +
                            ciFormatTokens(tokens) +
                            "</span>" +
                            fileHarnessHtml +
                            "</span>";
                        fileEl.appendChild(headerEl);

                        var entriesEl = document.createElement("div");
                        entriesEl.className = "ci-file-entries";
                        entries.forEach(function (f) {
                            var entryEl = document.createElement("div");
                            entryEl.className = "ci-entry";
                            entryEl.dataset.category = f.category || "";
                            entryEl.dataset.agents = ciExpandAgents(f.agents).join(",");
                            entryEl.dataset.tessl = ciIsTesslPath(f.path) ? "1" : "0";
                            entryEl.dataset.path = f.path;
                            entryEl.innerHTML =
                                '<span class="ci-entry-dot ' +
                                dotClass(f.usefulness) +
                                '" title="' +
                                esc(f.usefulness_reasoning || "") +
                                '"></span>' +
                                '<span class="ci-entry-name">' +
                                entryLabel(f) +
                                "</span>" +
                                '<span class="ci-entry-right">' +
                                '<span class="ci-entry-type">' +
                                esc(CI_CATEGORY_BADGE[f.category] || f.category || "") +
                                "</span>" +
                                "</span>";
                            entryEl.addEventListener("click", function (evt) {
                                evt.stopPropagation();
                                openContextEntryPanel(f.path);
                            });
                            entriesEl.appendChild(entryEl);
                        });
                        fileEl.appendChild(entriesEl);
                        tree.appendChild(fileEl);
                    });
                    root.appendChild(tree);

                    var asymmetryFindings = findings.filter(function (f) {
                        return (
                            f.subcategory === "TCG-5" ||
                            (f.category === "TCG" && /cross[- ]?tool|cross[- ]?agent|asymmetr/i.test(f.title || ""))
                        );
                    });
                    if (asymmetryFindings.length) {
                        var panel = document.createElement("div");
                        panel.className = "ci-asymmetries";
                        panel.innerHTML =
                            "<h3>Cross-Agent Asymmetries</h3><ul>" +
                            asymmetryFindings
                                .map(function (f) {
                                    return "<li><span>" + esc(f.title || "") + "</span></li>";
                                })
                                .join("") +
                            "</ul>";
                        root.appendChild(panel);
                    }

                    function entryMatchesType(entry, selTypes) {
                        if (!selTypes.length) return true;
                        for (var i = 0; i < selTypes.length; i++) {
                            var t = selTypes[i];
                            if (t === "plugin") {
                                if (entry.dataset.tessl === "1") return true;
                            } else if (entry.dataset.category === t) {
                                return true;
                            }
                        }
                        return false;
                    }

                    function applyFilters() {
                        // Entry-level counts (for dropdown badges) respect search + harness +
                        // tessl toggle, but not the type filter itself — each option shows how
                        // many entries it would reveal.
                        var totalVisible = 0;
                        var perType = {};
                        CI_CATEGORIES.forEach(function (c) {
                            perType[c.key] = 0;
                        });
                        var perHarness = { claude: 0, cursor: 0 };
                        var totalForHarnessPanel = 0;

                        tree.querySelectorAll(".ci-file").forEach(function (fileEl) {
                            var file = fileEl.dataset.file || "";
                            var pathMatch = !searchQuery || file.toLowerCase().indexOf(searchQuery) !== -1;
                            var visibleEntries = 0;
                            fileEl.querySelectorAll(".ci-entry").forEach(function (entry) {
                                var tesslMatch = showTesslTiles || entry.dataset.tessl !== "1";
                                var agents = (entry.dataset.agents || "").split(",").filter(Boolean);
                                var harnessMatch =
                                    selectedHarnesses.length === 0 ||
                                    selectedHarnesses.some(function (h) {
                                        return agents.indexOf(h) !== -1;
                                    });
                                var typeMatch = entryMatchesType(entry, selectedTypes);
                                var labelEl = entry.querySelector(".ci-entry-name");
                                var label = labelEl ? labelEl.textContent.toLowerCase() : "";
                                var textMatch = !searchQuery || pathMatch || label.indexOf(searchQuery) !== -1;
                                var visible = tesslMatch && harnessMatch && typeMatch && textMatch;
                                entry.hidden = !visible;
                                if (visible) {
                                    visibleEntries++;
                                    totalVisible++;
                                    var cat = entry.dataset.category;
                                    if (perType[cat] !== undefined) perType[cat]++;
                                    if (entry.dataset.tessl === "1") perType.plugin = (perType.plugin || 0) + 1;
                                }
                                // Unfiltered-by-type count (for type dropdown) — still respects tessl + harness + search
                                if (tesslMatch && harnessMatch && textMatch) {
                                    totalForHarnessPanel++;
                                }
                                // Unfiltered-by-harness count (for harness dropdown) — respects type + tessl + search
                                if (tesslMatch && typeMatch && textMatch) {
                                    agents.forEach(function (a) {
                                        if (perHarness[a] !== undefined) perHarness[a]++;
                                    });
                                }
                            });
                            fileEl.hidden = visibleEntries === 0;
                        });

                        // Update type dropdown counts
                        typeDD.setCounts(perType, totalForHarnessPanel);
                        // Update harness dropdown counts
                        harnessDD.setCounts(perHarness, totalVisible);
                    }
                    applyFilters();
                }

                // ── Reusable multi-select dropdown matching the findings-filter dropdowns
                function buildDropdown(id, defaultLabel, options, onChange) {
                    var wrapper = document.createElement("div");
                    wrapper.className = "dropdown-wrapper";
                    var trigger = document.createElement("button");
                    trigger.className = "dropdown-trigger";
                    trigger.type = "button";
                    trigger.id = id + "Trigger";
                    trigger.innerHTML =
                        '<span class="dropdown-trigger-label" id="' +
                        id +
                        'Label">' +
                        esc(defaultLabel) +
                        '</span><span class="dropdown-trigger-arrow"></span>';
                    var panel = document.createElement("div");
                    panel.className = "dropdown-panel";
                    panel.id = id + "Panel";
                    var selected = [];

                    trigger.addEventListener("click", function (evt) {
                        evt.stopPropagation();
                        var isOpen = panel.classList.contains("open");
                        document.querySelectorAll(".dropdown-panel.open").forEach(function (p) {
                            p.classList.remove("open");
                        });
                        document.querySelectorAll(".dropdown-trigger.open").forEach(function (t) {
                            t.classList.remove("open");
                        });
                        if (!isOpen) {
                            panel.classList.add("open");
                            trigger.classList.add("open");
                        }
                    });

                    var allOpt = document.createElement("div");
                    allOpt.className = "dropdown-option selected";
                    allOpt.dataset.value = "all";
                    allOpt.innerHTML =
                        '<div class="dropdown-checkbox"></div><div class="dropdown-option-body"><div class="dropdown-option-label">' +
                        esc(defaultLabel) +
                        '</div><div class="dropdown-option-desc">Show ' +
                        esc(defaultLabel.toLowerCase()) +
                        ' across every entry</div></div><div class="dropdown-option-count" data-value="__all__">0</div>';
                    panel.appendChild(allOpt);
                    var divider = document.createElement("div");
                    divider.className = "dropdown-divider";
                    panel.appendChild(divider);
                    options.forEach(function (o) {
                        var opt = document.createElement("div");
                        opt.className = "dropdown-option";
                        opt.dataset.value = o.key;
                        opt.innerHTML =
                            '<div class="dropdown-checkbox"></div><div class="dropdown-option-body"><div class="dropdown-option-label">' +
                            esc(o.label) +
                            '</div><div class="dropdown-option-desc">' +
                            esc(o.desc || "") +
                            '</div></div><div class="dropdown-option-count" data-value="' +
                            esc(o.key) +
                            '">0</div>';
                        panel.appendChild(opt);
                    });

                    panel.querySelectorAll(".dropdown-option").forEach(function (opt) {
                        opt.addEventListener("click", function () {
                            var v = opt.dataset.value;
                            if (v === "all") {
                                selected = [];
                            } else {
                                var idx = selected.indexOf(v);
                                if (idx === -1) selected.push(v);
                                else selected.splice(idx, 1);
                            }
                            updateUI();
                            onChange(selected.slice());
                        });
                    });

                    function updateUI() {
                        panel.querySelectorAll(".dropdown-option").forEach(function (opt) {
                            var v = opt.dataset.value;
                            var isSel = v === "all" ? selected.length === 0 : selected.indexOf(v) !== -1;
                            opt.classList.toggle("selected", isSel);
                        });
                        var labelEl = document.getElementById(id + "Label");
                        if (selected.length === 0) {
                            labelEl.textContent = defaultLabel;
                        } else if (selected.length === 1) {
                            var match = options.find(function (o) {
                                return o.key === selected[0];
                            });
                            labelEl.textContent = match ? match.label : selected[0];
                        } else {
                            labelEl.textContent = selected.length + " selected";
                        }
                    }

                    function setCounts(perOption, total) {
                        panel.querySelectorAll(".dropdown-option-count").forEach(function (el) {
                            var v = el.dataset.value;
                            if (v === "__all__") el.textContent = total;
                            else el.textContent = perOption && perOption[v] != null ? perOption[v] : 0;
                        });
                    }

                    wrapper.appendChild(trigger);
                    wrapper.appendChild(panel);
                    return { wrapper: wrapper, setCounts: setCounts };
                }

                renderSidebarMeta();
                renderReadiness();
                renderStats();
                renderFilterDropdowns();
                renderFindings();
                renderContextInventory();
                renderAnalytics();
                renderSources();

                // Align bar-row labels within each chart grouping
                setTimeout(function () {
                    document
                        .querySelectorAll("#categoryBars, #severityBars, #dataSourceBars")
                        .forEach(function (group) {
                            var labels = group.querySelectorAll(".source-bar-label");
                            if (labels.length < 2) return;
                            var maxW = 0;
                            labels.forEach(function (l) {
                                l.style.minWidth = "auto";
                                var w = l.getBoundingClientRect().width;
                                if (w > maxW) maxW = w;
                            });
                            labels.forEach(function (l) {
                                l.style.minWidth = Math.ceil(maxW) + "px";
                            });
                        });
                }, 0);
            })();

            // ── Interaction handlers (global for onclick attrs) ──
            var selectedCategories = [];
            var selectedSeverities = [];

            function sevColor(level) {
                if (level === "critical") return "#f87171";
                if (level === "high") return "#fbbf24";
                if (level === "medium") return "#facc15";
                return "#60a5fa";
            }

            function buildFindingHtml(finding) {
                var r = window.__reportData;
                var esc = r.esc;
                var CATEGORY_NAMES = r.CATEGORY_NAMES;
                var SOURCE_LABELS = r.SOURCE_LABELS;
                var html = "";
                html += '<div class="panel-title">' + esc(finding.title) + "</div>";
                html +=
                    '<div class="panel-subtitle">' +
                    esc(finding.id) +
                    " &middot; " +
                    esc(CATEGORY_NAMES[finding.category] || finding.category || "") +
                    "</div>";

                if (finding.description) {
                    html += '<div class="panel-section"><div class="panel-section-label">Description</div>';
                    html +=
                        '<div style="font-size: 14px; color: var(--fg); line-height: 1.625;">' +
                        esc(finding.description) +
                        "</div></div>";
                }

                if (finding.impact) {
                    var impLevel = finding.impact.level || "medium";
                    html += '<div class="panel-section"><div class="panel-section-label">Impact</div>';
                    html += '<div style="font-size: 14px; color: var(--fg-muted);">';
                    html +=
                        '<span style="color:' +
                        sevColor(impLevel) +
                        '; font-weight: 600; text-transform: capitalize;">' +
                        esc(impLevel) +
                        "</span>";
                    if (finding.impact.reasoning) {
                        html +=
                            '<div style="margin-top: 6px; font-size: 12px; color: var(--fg-subtle); line-height: 1.625;">' +
                            esc(finding.impact.reasoning) +
                            "</div>";
                    }
                    html += "</div></div>";
                }

                if (finding.effort) {
                    html += '<div class="panel-section"><div class="panel-section-label">Effort</div>';
                    html += '<div style="font-size: 14px; color: var(--fg-muted);">';
                    html +=
                        '<span style="color: var(--fg); font-weight: 600; text-transform: capitalize;">' +
                        esc(finding.effort.level || "") +
                        "</span>";
                    if (finding.effort.reasoning) {
                        html +=
                            '<div style="margin-top: 6px; font-size: 12px; color: var(--fg-subtle); line-height: 1.625;">' +
                            esc(finding.effort.reasoning) +
                            "</div>";
                    }
                    html += "</div></div>";
                }

                if (finding.evidence && finding.evidence.length > 0) {
                    html += '<div class="panel-section"><div class="panel-section-label">Evidence</div>';
                    for (var i = 0; i < finding.evidence.length; i++) {
                        var ev = finding.evidence[i];
                        html +=
                            '<div style="font-size: 12px; color: var(--fg-muted); margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid rgba(255,255,255,0.04);">';
                        var sourceLabel = SOURCE_LABELS[ev.source] || ev.source || "";
                        if (sourceLabel || ev.type) {
                            html +=
                                '<span style="color: var(--fg-subtle); font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em;">' +
                                esc(sourceLabel || ev.type) +
                                "</span><br>";
                        }
                        if (ev.location) {
                            html +=
                                "<span style=\"color: var(--fg-subtle); font-family: 'Atkinson Hyperlegible Mono', monospace; font-size: 12px;\">" +
                                esc(ev.location) +
                                "</span><br>";
                        }
                        if (ev.detail) html += "<span>" + esc(ev.detail) + "</span>";
                        if (ev.snippet) {
                            html +=
                                "<pre style=\"margin-top: 6px; padding: 8px; background: rgba(0,0,0,0.4); border-radius: 4px; font-family: 'Atkinson Hyperlegible Mono', monospace; font-size: 12px; color: var(--fg-muted); white-space: pre-wrap; overflow-x: auto;\">" +
                                esc(ev.snippet) +
                                "</pre>";
                        }
                        html += "</div>";
                    }
                    html += "</div>";
                }

                if (finding.action) {
                    var a = finding.action;
                    html += '<div class="panel-section"><div class="panel-section-label">Suggested action</div>';
                    html +=
                        '<div style="font-size: 14px; color: var(--fg-muted);"><strong style="color: var(--fg);">' +
                        esc(a.title || "") +
                        "</strong></div>";
                    if (a.description) {
                        html +=
                            '<div style="font-size: 12px; color: var(--fg-subtle); margin-top: 8px; line-height: 1.625;">' +
                            esc(a.description) +
                            "</div>";
                    }
                    var chips = [];
                    if (a.type) chips.push(esc(a.type));
                    if (a.effort_size) chips.push(esc(a.effort_size));
                    if (chips.length) {
                        html += '<div style="display: flex; gap: 6px; margin-top: 10px;">';
                        chips.forEach(function (c) {
                            html += '<span class="ev-pill">' + c + "</span>";
                        });
                        html += "</div>";
                    }
                    if (a.example_fix) {
                        html +=
                            "<pre style=\"margin-top: 12px; padding: 8px; background: rgba(0,0,0,0.4); border-radius: 4px; font-family: 'Atkinson Hyperlegible Mono', monospace; font-size: 12px; color: var(--fg-muted); white-space: pre-wrap; overflow-x: auto;\">" +
                            esc(a.example_fix) +
                            "</pre>";
                    }
                    html += "</div>";
                }

                return html;
            }

            function openPanel(findingId) {
                var r = window.__reportData;
                var finding = r.findings.find(function (f) {
                    return f.id === findingId;
                });
                if (!finding) return;
                document.getElementById("panelInner").innerHTML = buildFindingHtml(finding);
                document.getElementById("shell").classList.add("panel-open");
                document.getElementById("panelInner").scrollTop = 0;
            }

            function closePanel() {
                document.getElementById("shell").classList.remove("panel-open");
            }

            // ── Context inventory drawers ──
            var CI_TYPE_BADGE = {
                entry_point: "Entry point",
                always_on_rule: "Rule",
                hook: "Hook",
                skill: "Skill",
                mcp: "MCP",
                referenced_doc: "Referenced doc",
                plugin: "Plugin",
            };
            var CI_TYPE_LABELS = {
                entry_point: "Entry points",
                always_on_rule: "Always-on rules",
                hook: "Hooks",
                skill: "Skills",
                mcp: "MCP",
                referenced_doc: "Referenced docs",
                plugin: "Plugins",
            };

            function ciBasenameG(p) {
                if (!p) return "";
                var i = p.lastIndexOf("/");
                return i < 0 ? p : p.slice(i + 1);
            }
            function ciExpandAgentsG(a) {
                if (Array.isArray(a) && a.indexOf("cross-agent") !== -1) return ["claude", "cursor"];
                return Array.isArray(a)
                    ? a.filter(function (x) {
                          return x === "claude" || x === "cursor";
                      })
                    : [];
            }
            function ciEstimateTokens(entry) {
                var m = (entry && entry.usefulness_reasoning ? entry.usefulness_reasoning : "").match(/~(\d+)/);
                if (!m) return null;
                return parseInt(m[1], 10) * 15;
            }
            function ciFormatTokensG(n) {
                if (n === null || n === undefined) return "~? tokens";
                if (n < 1000) return "~" + n + " tokens";
                return "~" + (n / 1000).toFixed(1).replace(/\.0$/, "") + "k tokens";
            }
            function ciHarnessLabel(agents) {
                if (!agents || !agents.length) return "—";
                if (agents.length === 2) return "Cross-agent";
                return agents[0] === "claude" ? "Claude" : "Cursor";
            }
            function ciEntryTitle(entry) {
                if (entry.purpose) return entry.purpose;
                var name = ciBasenameG(entry.path);
                return name.replace(/\.[^.]+$/, "").replace(/[-_]/g, " ");
            }
            // A short, meaningful display name. For generic filenames (SKILL.md,
            // AGENTS.md, RULES.md, README.md, etc.) fall back to the parent folder
            // so adjacent entries don't all read as "SKILL".
            function ciDisplayName(entry) {
                var GENERIC = {
                    SKILL: 1,
                    AGENTS: 1,
                    CLAUDE: 1,
                    CURSOR: 1,
                    RULES: 1,
                    README: 1,
                    TILE: 1,
                    INDEX: 1,
                };
                var base = ciBasenameG(entry.path);
                var stem = base.replace(/\.[^.]+$/, "");
                if (stem.toUpperCase() in GENERIC) {
                    var parts = entry.path.split("/").filter(Boolean);
                    if (parts.length >= 2) return parts[parts.length - 2];
                }
                return stem;
            }
            function ciPluginKeyG(path) {
                var m = path.match(/^\.tessl\/tiles\/([^\/]+)\/([^\/]+)/);
                return m ? m[1] + "/" + m[2] : null;
            }

            function buildMetaGrid(rows) {
                var esc = window.__reportData.esc;
                var html = '<div class="panel-meta-grid">';
                rows.forEach(function (r) {
                    if (r.val === undefined || r.val === null || r.val === "") return;
                    html += '<div class="panel-meta-key">' + esc(r.key) + "</div>";
                    html +=
                        '<div class="panel-meta-val' +
                        (r.mono ? " mono" : "") +
                        '">' +
                        (r.html ? r.val : esc(String(r.val))) +
                        "</div>";
                });
                html += "</div>";
                return html;
            }

            function findRelatedFindings(filepath) {
                if (!filepath) return [];
                var fp = filepath.toLowerCase();
                var fpBase = fp.split("/").pop();
                return window.__reportData.findings.filter(function (f) {
                    if (!f.evidence) return false;
                    return f.evidence.some(function (ev) {
                        var loc = (ev.location || "").toLowerCase();
                        if (!loc) return false;
                        return loc === fp || loc.indexOf(fp) !== -1 || (fpBase && loc.indexOf(fpBase) !== -1);
                    });
                });
            }

            function openContextEntryPanel(path, backToPlugin, backToFinding) {
                var r = window.__reportData;
                var esc = r.esc;
                var entry = (r.contextInventory || []).find(function (e) {
                    return e.path === path;
                });
                if (!entry) return;
                var agents = ciExpandAgentsG(entry.agents);
                var tokens = ciEstimateTokens(entry);
                var usefulnessLabel =
                    entry.usefulness === "high" ? "Useful" : entry.usefulness === "medium" ? "Partial" : "Unused";
                var usefulnessColor =
                    entry.usefulness === "high"
                        ? "var(--green)"
                        : entry.usefulness === "medium"
                          ? "var(--yellow)"
                          : "var(--red)";
                var title = ciEntryTitle(entry);
                var html = "";
                if (backToPlugin) {
                    html +=
                        '<div class="panel-back" data-back="' +
                        esc(backToPlugin) +
                        '" onclick="openContextPluginPanel(this.dataset.back)"><span>&larr;</span> Back to ' +
                        esc(backToPlugin) +
                        "</div>";
                } else if (backToFinding) {
                    html +=
                        '<div class="panel-back" data-back="' +
                        esc(backToFinding) +
                        '" onclick="openPanel(this.dataset.back)"><span>&larr;</span> Back to finding ' +
                        esc(backToFinding) +
                        "</div>";
                }
                html += '<div class="panel-title">' + esc(title) + "</div>";
                html +=
                    '<div class="panel-subtitle">' +
                    esc(CI_TYPE_BADGE[entry.category] || entry.category || "") +
                    ' &middot; <span style="color:' +
                    usefulnessColor +
                    ';">' +
                    usefulnessLabel +
                    "</span></div>";

                if (entry.usefulness_reasoning) {
                    html += '<div class="panel-section"><div class="panel-section-label">Why this rating</div>';
                    html +=
                        '<div style="font-size: 14px; color: var(--fg-muted); line-height: 1.625;">' +
                        esc(entry.usefulness_reasoning) +
                        "</div></div>";
                }

                html += '<div class="panel-section"><div class="panel-section-label">Metadata</div>';
                html += buildMetaGrid([
                    { key: "Path", val: entry.path, mono: true },
                    {
                        key: "Type",
                        val: CI_TYPE_BADGE[entry.category] || entry.category,
                    },
                    { key: "Harness", val: ciHarnessLabel(agents) },
                    {
                        key: "Tokens",
                        val: tokens != null ? ciFormatTokensG(tokens) + " (estimate)" : ciFormatTokensG(null),
                    },
                    { key: "Scope", val: (entry.scope || []).join(", ") },
                ]);
                html += "</div>";

                var outLinks = Array.isArray(entry.links) ? entry.links : [];
                if (outLinks.length) {
                    html +=
                        '<div class="panel-section"><div class="panel-section-label">Links to (' +
                        outLinks.length +
                        ")</div>";
                    outLinks.forEach(function (p) {
                        html +=
                            '<div class="panel-link" data-p="' +
                            esc(p) +
                            '" onclick="openContextEntryPanel(this.dataset.p)">' +
                            esc(p) +
                            "</div>";
                    });
                    html += "</div>";
                }
                var inLinks = Array.isArray(entry.linked_from) ? entry.linked_from : [];
                if (inLinks.length) {
                    html +=
                        '<div class="panel-section"><div class="panel-section-label">Linked from (' +
                        inLinks.length +
                        ")</div>";
                    inLinks.forEach(function (p) {
                        html +=
                            '<div class="panel-link" data-p="' +
                            esc(p) +
                            '" onclick="openContextEntryPanel(this.dataset.p)">' +
                            esc(p) +
                            "</div>";
                    });
                    html += "</div>";
                }

                var relatedF = findRelatedFindings(path);
                if (relatedF.length) {
                    html +=
                        '<div class="panel-section"><div class="panel-section-label">Related findings (' +
                        relatedF.length +
                        ")</div>";
                    relatedF.forEach(function (f) {
                        var sev = (f.impact || {}).level || "medium";
                        var sc = sevColor(sev);
                        html +=
                            '<div class="panel-related-item" data-f="' +
                            esc(f.id) +
                            '" onclick="openPanel(this.dataset.f)">';
                        html += '<span class="panel-related-item-title">' + esc(f.title || "") + "</span>";
                        html +=
                            '<span style="color:' +
                            sc +
                            '; font-size: 12px;">' +
                            esc(sev.charAt(0).toUpperCase() + sev.slice(1)) +
                            "</span>";
                        html += "</div>";
                    });
                    html += "</div>";
                }

                document.getElementById("panelInner").innerHTML = html;
                document.getElementById("shell").classList.add("panel-open");
                document.getElementById("panelInner").scrollTop = 0;
            }

            function openContextPluginPanel(pluginKey) {
                var r = window.__reportData;
                var esc = r.esc;
                var all = r.contextInventory || [];
                var entries = all.filter(function (e) {
                    return ciPluginKeyG(e.path) === pluginKey;
                });
                if (!entries.length) return;
                var totalTokens = 0;
                var agentsSet = {};
                entries.forEach(function (e) {
                    var t = ciEstimateTokens(e);
                    if (t) totalTokens += t;
                    ciExpandAgentsG(e.agents).forEach(function (a) {
                        agentsSet[a] = 1;
                    });
                });
                var agentList = Object.keys(agentsSet);
                var worstUse = entries.some(function (e) {
                    return e.usefulness === "low";
                })
                    ? "low"
                    : entries.some(function (e) {
                            return e.usefulness === "medium";
                        })
                      ? "medium"
                      : "high";
                var usefulnessLabel = worstUse === "high" ? "Useful" : worstUse === "medium" ? "Partial" : "Unused";
                var usefulnessColor =
                    worstUse === "high" ? "var(--green)" : worstUse === "medium" ? "var(--yellow)" : "var(--red)";

                var html = "";
                html += '<div class="panel-title">' + esc(pluginKey) + "</div>";
                html +=
                    '<div class="panel-subtitle">Plugin &middot; <span style="color:' +
                    usefulnessColor +
                    ';">' +
                    usefulnessLabel +
                    "</span> &middot; " +
                    entries.length +
                    " entries</div>";

                html += '<div class="panel-section"><div class="panel-section-label">Metadata</div>';
                html += buildMetaGrid([
                    {
                        key: "Path",
                        val: ".tessl/tiles/" + pluginKey + "/",
                        mono: true,
                    },
                    { key: "Harness", val: ciHarnessLabel(agentList) },
                    { key: "Entries", val: entries.length },
                    {
                        key: "Tokens",
                        val: ciFormatTokensG(totalTokens) + " (total, estimate)",
                    },
                ]);
                html += "</div>";

                html +=
                    '<div class="panel-section"><div class="panel-section-label">Contents (' +
                    entries.length +
                    ")</div>";
                var byCat = {};
                entries.forEach(function (e) {
                    (byCat[e.category] = byCat[e.category] || []).push(e);
                });
                function dotClassFor(u) {
                    return u === "high" ? "ci-dot-useful" : u === "medium" ? "ci-dot-partial" : "ci-dot-unused";
                }
                Object.keys(byCat)
                    .sort()
                    .forEach(function (cat) {
                        html +=
                            '<div style="font-size: 12px; color: var(--fg-subtle); text-transform: uppercase; letter-spacing: 0.05em; margin: 10px 0 4px;">' +
                            esc(CI_TYPE_LABELS[cat] || cat) +
                            " (" +
                            byCat[cat].length +
                            ")</div>";
                        byCat[cat].forEach(function (e) {
                            var title = ciDisplayName(e);
                            var subtitle = e.purpose ? e.path : "";
                            // If the title already equals the parent folder, the path is
                            // the most useful secondary signal; include it either way.
                            if (!subtitle) subtitle = e.path;
                            var t = ciEstimateTokens(e);
                            var tokensLabel = t != null ? ciFormatTokensG(t) : "";
                            html +=
                                '<div class="panel-entry-card" data-p="' +
                                esc(e.path) +
                                '" data-back="' +
                                esc(pluginKey) +
                                '" onclick="openContextEntryPanel(this.dataset.p, this.dataset.back)">' +
                                '<span class="panel-entry-card-dot ' +
                                dotClassFor(e.usefulness) +
                                '" title="' +
                                esc(e.usefulness_reasoning || "") +
                                '"></span>' +
                                '<div class="panel-entry-card-body">' +
                                '<div class="panel-entry-card-title">' +
                                esc(title) +
                                "</div>" +
                                '<div class="panel-entry-card-path">' +
                                esc(subtitle) +
                                "</div>" +
                                "</div>" +
                                (tokensLabel
                                    ? '<span class="panel-entry-card-meta">' + esc(tokensLabel) + "</span>"
                                    : "") +
                                "</div>";
                        });
                    });
                html += "</div>";

                document.getElementById("panelInner").innerHTML = html;
                document.getElementById("shell").classList.add("panel-open");
                document.getElementById("panelInner").scrollTop = 0;
            }

            function scrollToSection(sectionId) {
                var elem = document.getElementById(sectionId);
                if (elem) {
                    elem.scrollIntoView({ behavior: "smooth" });
                    document.querySelectorAll(".sidebar-nav-item").forEach(function (e) {
                        e.classList.remove("active");
                    });
                    var nav = document.querySelector('[data-section="' + sectionId + '"]');
                    if (nav) nav.classList.add("active");
                }
            }

            function toggleDropdown(type, evt) {
                if (evt) evt.stopPropagation();
                var trigger = document.getElementById(type + "Trigger");
                var panel = document.getElementById(type + "Panel");
                var isOpen = panel.classList.contains("open");
                document.querySelectorAll(".dropdown-panel.open").forEach(function (p) {
                    p.classList.remove("open");
                });
                document.querySelectorAll(".dropdown-trigger.open").forEach(function (t) {
                    t.classList.remove("open");
                });
                if (!isOpen) {
                    panel.classList.add("open");
                    trigger.classList.add("open");
                }
            }

            function handleDropdownOption(type, value) {
                var arr = type === "category" ? selectedCategories : selectedSeverities;
                if (value === "all") {
                    arr.length = 0;
                } else {
                    var idx = arr.indexOf(value);
                    if (idx >= 0) arr.splice(idx, 1);
                    else arr.push(value);
                }
                if (type === "category") selectedCategories = arr;
                else selectedSeverities = arr;
                updateDropdownUI(type);
                applyFindingFilters();
            }

            function updateDropdownUI(type) {
                var panel = document.getElementById(type + "Panel");
                var label = document.getElementById(type + "Label");
                var arr = type === "category" ? selectedCategories : selectedSeverities;
                var defaultLabel = type === "category" ? "All categories" : "All severities";

                panel.querySelectorAll(".dropdown-option").forEach(function (opt) {
                    var val = opt.getAttribute("data-value");
                    var isSelected = val === "all" ? arr.length === 0 : arr.indexOf(val) !== -1;
                    opt.classList.toggle("selected", isSelected);
                });

                if (arr.length === 0) {
                    label.textContent = defaultLabel;
                } else if (arr.length === 1) {
                    var single = arr[0];
                    if (type === "category") {
                        var CATEGORY_NAMES = window.__reportData.CATEGORY_NAMES;
                        label.textContent = CATEGORY_NAMES[single] || single;
                    } else {
                        label.textContent = single.charAt(0).toUpperCase() + single.slice(1);
                    }
                } else {
                    label.textContent = arr.length + " selected";
                }
            }

            function applyFindingFilters() {
                var searchEl = document.getElementById("findingSearch");
                var query = ((searchEl && searchEl.value) || "").toLowerCase().trim();
                var rows = document.querySelectorAll("#findingsList .finding-row");
                var visible = 0;
                rows.forEach(function (r) {
                    var rowCat = r.getAttribute("data-category") || "";
                    var rowSev = r.getAttribute("data-severity") || "";
                    var descEl = r.querySelector(".finding-desc");
                    var desc = (descEl ? descEl.textContent : "").toLowerCase();
                    var catMatch = selectedCategories.length === 0 || selectedCategories.indexOf(rowCat) !== -1;
                    var sevMatch = selectedSeverities.length === 0 || selectedSeverities.indexOf(rowSev) !== -1;
                    var textMatch = !query || desc.indexOf(query) !== -1 || rowCat.toLowerCase().indexOf(query) !== -1;
                    var show = catMatch && sevMatch && textMatch;
                    r.style.display = show ? "flex" : "none";
                    if (show) visible++;
                });
                var empty = document.getElementById("findingsEmpty");
                if (empty) empty.style.display = visible === 0 && rows.length > 0 ? "block" : "none";
            }

            function clearAllFindingFilters() {
                selectedCategories.length = 0;
                selectedSeverities.length = 0;
                var searchEl = document.getElementById("findingSearch");
                if (searchEl) searchEl.value = "";
                updateDropdownUI("category");
                updateDropdownUI("severity");
                applyFindingFilters();
            }

            document.addEventListener("click", function (e) {
                if (!e.target.closest(".dropdown-wrapper")) {
                    document.querySelectorAll(".dropdown-panel.open").forEach(function (p) {
                        p.classList.remove("open");
                    });
                    document.querySelectorAll(".dropdown-trigger.open").forEach(function (t) {
                        t.classList.remove("open");
                    });
                }
            });

            function openCalcModal() {
                document.getElementById("calcModal").classList.add("open");
            }
            function closeCalcModal() {
                document.getElementById("calcModal").classList.remove("open");
            }

            document.addEventListener("keydown", function (e) {
                if (e.key === "Escape") {
                    closePanel();
                    closeCalcModal();
                }
            });
        </script>
    </body>
</html>

references

apex-taxonomy.md

findings-schema.md

insight-report-schema.md

report-template.html

tessl-product-context.md

README.md

tile.json