{
  "version": 3,
  "sources": ["../scripts/result_charts/legend_utils.js", "../scripts/result_charts/display.js", "../scripts/result_charts/comparison_charts.js", "../scripts/result_charts/config.js", "../scripts/result_charts/legend.js", "../scripts/result_charts/tooltip.js", "../scripts/result_charts/chart.js", "../scripts/result_charts/index.js"],
  "sourcesContent": ["// Pure filtering helpers for the chart legend. CommonJS so Jest can require them directly.\n\n/**\n * Filter legend items based on edge-modeling state.\n *\n * Items whose backing dataset carries isEdge: true represent the edge-device modeling\n * dimension. When edge modeling is off that dimension is inactive, so its legend entries\n * are hidden to avoid showing categories with no data.\n *\n * @param {Array} legendItems - Chart.js legend items\n * @param {Array} datasets    - Chart.js dataset array (chart.data.datasets)\n * @param {boolean} edgeModelingOn - Whether edge modeling is currently active\n * @returns {Array} Filtered legend items\n */\nfunction filterEdgeAwareItems(legendItems, datasets, edgeModelingOn) {\n    if (edgeModelingOn) return legendItems;\n    return legendItems.filter((item) => !datasets[item.datasetIndex]?.isEdge);\n}\n\nmodule.exports = { filterEdgeAwareItems };\n", "const UNIT_FAMILIES = [\n    [\"mg\", \"g\", \"kg\", \"t\", \"kt\", \"Mt\", \"Gt\", \"Tt\"],\n];\n\nfunction normalizeUnit(unit) {\n    if (unit === \"tonne\") {\n        return \"t\";\n    }\n    return unit;\n}\n\nfunction getUnitFamily(unit) {\n    const normalizedUnit = normalizeUnit(unit);\n    return UNIT_FAMILIES.find((family) => family.includes(normalizedUnit)) || null;\n}\n\nfunction convertValue(value, fromUnit, toUnit) {\n    const normalizedFrom = normalizeUnit(fromUnit);\n    const normalizedTo = normalizeUnit(toUnit);\n    const conversionToKg = { mg: 1e-6, g: 1e-3, kg: 1, t: 1e3, kt: 1e6, Mt: 1e9, Gt: 1e12, Tt: 1e15 };\n\n    if (!(normalizedFrom in conversionToKg) || !(normalizedTo in conversionToKg)) {\n        throw new Error(`Unsupported unit conversion from ${fromUnit} to ${toUnit}`);\n    }\n\n    return value * conversionToKg[normalizedFrom] / conversionToKg[normalizedTo];\n}\n\nfunction bestDisplayUnit(value, unit) {\n    const family = getUnitFamily(unit);\n    if (!family) {\n        return normalizeUnit(unit);\n    }\n\n    const representative = Math.abs(Number(value));\n    if (representative === 0) {\n        return family[0];\n    }\n\n    for (let idx = family.length - 1; idx >= 0; idx -= 1) {\n        const candidateUnit = family[idx];\n        if (Math.abs(convertValue(representative, unit, candidateUnit)) >= 1) {\n            return candidateUnit;\n        }\n    }\n\n    return family[0];\n}\n\nfunction roundToSigFigs(value, sigFigs = 3) {\n    if (value === 0) {\n        return 0;\n    }\n    if (Math.abs(value) >= 1000) {\n        return Math.round(value);\n    }\n    const digits = sigFigs - Math.floor(Math.log10(Math.abs(value))) - 1;\n    const scale = 10 ** digits;\n    return Math.round(value * scale) / scale;\n}\n\nfunction formatDisplayNumber(value) {\n    if (Object.is(value, -0)) {\n        return \"0\";\n    }\n    return Number(value).toLocaleString(\"en-US\", { maximumFractionDigits: 20 });\n}\n\nfunction humanReadableUnit(unit) {\n    return normalizeUnit(unit);\n}\n\nfunction formatQuantityForDisplay(value, unit, sigFigs = 3) {\n    const displayUnit = bestDisplayUnit(value, unit);\n    const convertedValue = convertValue(value, unit, displayUnit);\n    const roundedValue = roundToSigFigs(convertedValue, sigFigs);\n\n    return {\n        value: roundedValue,\n        unit: humanReadableUnit(displayUnit),\n        formattedValue: formatDisplayNumber(roundedValue),\n    };\n}\n\nfunction formatEmissionsQuantity(value, unit, sigFigs = 3) {\n    const formattedQuantity = formatQuantityForDisplay(value, unit, sigFigs);\n    return `${formattedQuantity.formattedValue} ${formattedQuantity.unit} CO2-eq`;\n}\n\nmodule.exports = {\n    bestDisplayUnit,\n    formatDisplayNumber,\n    formatEmissionsQuantity,\n    formatQuantityForDisplay,\n    humanReadableUnit,\n    roundToSigFigs,\n};\n", "// ============================================================================\n// Comparison dashboard charts\n// ============================================================================\n//\n// Three Chart.js variants for the comparison dashboard, all magnitude-honest: a single shared y-axis\n// and one legend per chart, so the two models' magnitudes read directly against each other. Model\n// identity is carried by a constant colour pair baked into the payload by the ComparisonService\n// adapter \u2014 never by per-chart auto-colours.\n//\n//   - paired bars: per-year, model A | model B side by side; within each model usage stacks on\n//     manufacturing (dark = usage, light = manufacturing). Two stacks (\"A\", \"B\") on one shared y-axis.\n//   - cumulative overlay: two curves on one axis; the gap between them is the running avoided/added\n//     emissions, the end gap the headline \u0394. The area between is shaded.\n//   - decomposition: horizontal diverging bars, one per category \u00D7 phase, signed (green left =\n//     reduction, red right = increase).\n//\n// The *_config builders below are pure (DOM-free) so Jest can assert the data-shaping; drawComparisonCharts\n// reads the swapped-in payloads and instantiates the charts.\n\nconst SHARED_FONT = {\n    family: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n    size: 12,\n};\nconst GRID_COLOR = \"rgba(0, 0, 0, 0.05)\";\nconst TICK_COLOR = \"#6b7280\";\n\n// Tooltip that prints the adapter's pre-formatted figure (``dataset.valueLabels``, shaped with the\n// library's best-unit + sig-fig helpers) instead of Chart.js's raw number, so hovers read in the same\n// units as the rest of the dashboard. Falls back to the default formatted value if none was shipped.\nconst FORMATTED_VALUE_TOOLTIP = {\n    callbacks: {\n        label(context) {\n            const labels = context.dataset.valueLabels;\n            const display = labels && labels[context.dataIndex] != null ? labels[context.dataIndex] : context.formattedValue;\n            return `${context.dataset.label}: ${display}`;\n        },\n    },\n};\n\n// Format a value-axis tick in the chart's shared display unit. The data rides in kg; the adapter\n// ships ``axisScale`` (the kg \u2192 display-unit factor) and ``axisUnit`` (the axis-title label) so a\n// tonne-scale comparison reads on a tonne axis instead of a six-figure kg one. The unit lives in the\n// axis title, so a tick is just the scaled number with its float-conversion noise trimmed. The\n// six-significant-figure cap is only that floating-point guard; it is not the precision policy for\n// reported values.\nfunction formatAxisTick(value, scale) {\n    return Number((value * (scale || 1)).toPrecision(6)).toLocaleString(\"en-US\");\n}\n\n// The axis title carries the chart's shared unit (``axisUnit``, falling back to kg for older payloads).\nfunction axisTitle(payload, suffix) {\n    return `${payload.axisUnit || \"kg\"} CO2-eq${suffix}`;\n}\n\n/**\n * Paired per-year bars on one shared y-axis (kg), one legend over the four series.\n * @param {Object} payload - {labels, datasets:[A usage, A fab, B usage, B fab]} from the adapter.\n * @returns {Object} Chart.js config.\n */\nfunction buildPairedChartConfig(payload) {\n    const datasets = payload.datasets.map((dataset) => ({\n        ...dataset,\n        borderWidth: 0,\n        // Each model is its own stack, so A and B sit side by side per year and usage/fab stack within.\n        stack: dataset.stack,\n    }));\n\n    return {\n        type: \"bar\",\n        data: { labels: payload.labels, datasets },\n        options: {\n            locale: \"en-US\",\n            responsive: true,\n            maintainAspectRatio: true,\n            aspectRatio: 2,\n            // One shared y-axis; bars from both models are measured against it (magnitude honesty).\n            scales: {\n                x: { stacked: true, grid: { display: false }, ticks: { font: SHARED_FONT, color: TICK_COLOR } },\n                y: {\n                    stacked: true,\n                    beginAtZero: true,\n                    title: { display: true, text: axisTitle(payload, \"\"), font: SHARED_FONT, color: TICK_COLOR },\n                    grid: { color: GRID_COLOR },\n                    ticks: {\n                        font: SHARED_FONT, color: TICK_COLOR,\n                        callback: (value) => formatAxisTick(value, payload.axisScale),\n                    },\n                },\n            },\n            // The built-in legend is replaced by a custom HTML legend rendered via renderPairedLegend,\n            // which groups series into one row per system with the real model name as the row label.\n            plugins: {\n                legend: { display: false },\n                tooltip: FORMATTED_VALUE_TOOLTIP,\n            },\n        },\n    };\n}\n\n/**\n * Cumulative overlay: two curves on one shared y-axis, the area between them shaded as the gap.\n * @param {Object} payload - {labels, datasets:[A, B]} of cumulative kg from the adapter.\n * @returns {Object} Chart.js config.\n */\nfunction buildCumulativeChartConfig(payload) {\n    const datasets = payload.datasets.map((dataset, index) => ({\n        ...dataset,\n        borderWidth: 2.5,\n        pointRadius: 3,\n        tension: 0.3,\n        spanGaps: false,\n        // Shade the band between the two curves (B fills to A): the gap is the running \u0394 (B \u2212 A).\n        // B above A \u21D2 B emits more \u21D2 red; B below A \u21D2 a reduction \u21D2 green.\n        fill: index === 1 ? { target: 0, above: \"rgba(198,40,40,0.12)\", below: \"rgba(46,125,50,0.12)\" } : false,\n    }));\n\n    return {\n        type: \"line\",\n        data: { labels: payload.labels, datasets },\n        options: {\n            locale: \"en-US\",\n            responsive: true,\n            maintainAspectRatio: true,\n            aspectRatio: 2,\n            scales: {\n                x: { grid: { display: false }, ticks: { font: SHARED_FONT, color: TICK_COLOR } },\n                y: {\n                    beginAtZero: true,\n                    title: { display: true, text: axisTitle(payload, \"\"), font: SHARED_FONT, color: TICK_COLOR },\n                    grid: { color: GRID_COLOR },\n                    ticks: {\n                        font: SHARED_FONT, color: TICK_COLOR,\n                        callback: (value) => formatAxisTick(value, payload.axisScale),\n                    },\n                },\n            },\n            // The built-in legend is replaced by a custom HTML legend rendered via renderCumulativeLegend,\n            // matching the paired chart's per-system row style.\n            plugins: {\n                legend: { display: false },\n                tooltip: FORMATTED_VALUE_TOOLTIP,\n            },\n        },\n    };\n}\n\n/**\n * Inline plugin: print each decomposition bar's pre-formatted \u0394 at the tip of the bar (the figures\n * that used to sit in the list below the chart). Reads ``dataset.valueLabels`` (display strings shaped\n * by the adapter, e.g. \"+571 kg\" / \"\u22123 g\") so the JS never reformats magnitudes. Positive bars point\n * right and label to the right of the tip, negative bars point left and label to the left; the label\n * takes the bar's own direction colour.\n */\nconst decompositionValueLabelsPlugin = {\n    id: \"decompositionValueLabels\",\n    afterDatasetsDraw(chart) {\n        const { ctx } = chart;\n        const dataset = chart.data.datasets[0];\n        const labels = dataset && dataset.valueLabels;\n        if (!labels) return;\n        const meta = chart.getDatasetMeta(0);\n        ctx.save();\n        ctx.font = `600 11px ${SHARED_FONT.family}`;\n        ctx.textBaseline = \"middle\";\n        meta.data.forEach((bar, index) => {\n            const text = labels[index];\n            if (text == null) return;\n            const positive = (dataset.data[index] || 0) >= 0;\n            ctx.fillStyle = Array.isArray(dataset.backgroundColor)\n                ? dataset.backgroundColor[index]\n                : dataset.backgroundColor;\n            ctx.textAlign = positive ? \"left\" : \"right\";\n            ctx.fillText(text, bar.x + (positive ? 4 : -4), bar.y);\n        });\n        ctx.restore();\n    },\n};\n\n/**\n * Horizontal diverging decomposition bars on a single value axis, signed and per-bar coloured, with\n * each bar's \u0394 printed at its tip (decompositionValueLabelsPlugin).\n * @param {Object} payload - {labels, datasets:[{data, backgroundColor[], valueLabels[]}]} from the adapter.\n * @returns {Object} Chart.js config.\n */\nfunction buildDecompositionChartConfig(payload) {\n    return {\n        type: \"bar\",\n        data: payload,\n        options: {\n            indexAxis: \"y\", // horizontal bars\n            locale: \"en-US\",\n            responsive: true,\n            maintainAspectRatio: true,\n            aspectRatio: 2.5,\n            scales: {\n                x: {\n                    // Headroom on both ends so the tip labels are not clipped at the chart edge.\n                    grace: \"10%\",\n                    title: {\n                        display: true, text: axisTitle(payload, \" difference (B \u2212 A)\"),\n                        font: SHARED_FONT, color: TICK_COLOR,\n                    },\n                    grid: { color: GRID_COLOR },\n                    ticks: {\n                        font: SHARED_FONT, color: TICK_COLOR,\n                        callback: (value) => formatAxisTick(value, payload.axisScale),\n                    },\n                },\n                y: { grid: { display: false }, ticks: { font: SHARED_FONT, color: TICK_COLOR } },\n            },\n            // No legend (the colour reads the direction) and no tooltip (the tip labels already\n            // print each \u0394, so a hover would only repeat them).\n            plugins: { legend: { display: false }, tooltip: { enabled: false } },\n        },\n        plugins: [decompositionValueLabelsPlugin],\n    };\n}\n\n/**\n * Render a grouped HTML legend for the paired bar chart below its canvas. Produces one row per\n * model (stack \"A\" / \"B\"), each row labelled with the real system name and showing one color swatch\n * per series (usage / manufacturing). Falls back to \"System A\" / \"System B\" when name fields are absent.\n * @param {Object} payload - The paired chart payload (includes modelAName, modelBName, datasets).\n * @param {string} canvasId - The id of the canvas the paired chart is drawn on.\n */\nfunction renderPairedLegend(payload, canvasId) {\n    const canvas = document.getElementById(canvasId);\n    if (!canvas) return;\n\n    const legendId = `${canvasId}-legend`;\n    let container = document.getElementById(legendId);\n    if (!container) {\n        container = document.createElement(\"div\");\n        container.id = legendId;\n        canvas.parentNode.insertBefore(container, canvas.nextSibling);\n    }\n    container.innerHTML = \"\";\n    container.style.cssText = \"padding: 6px 0 2px; font-size: 12px; font-family: 'Inter', system-ui, sans-serif;\";\n\n    const systemNames = { A: payload.modelAName || \"System A\", B: payload.modelBName || \"System B\" };\n\n    // Collect datasets per stack, preserving insertion order (usage then manufacturing).\n    const groups = {};\n    for (const dataset of payload.datasets) {\n        const stack = dataset.stack;\n        if (!groups[stack]) groups[stack] = [];\n        groups[stack].push(dataset);\n    }\n\n    for (const [stack, datasets] of Object.entries(groups)) {\n        const row = document.createElement(\"div\");\n        row.style.cssText = \"display: flex; align-items: center; gap: 8px; margin-bottom: 4px; flex-wrap: nowrap;\";\n\n        const nameLabel = document.createElement(\"span\");\n        nameLabel.textContent = `${systemNames[stack]}:`;\n        nameLabel.style.cssText = \"font-weight: 600; white-space: nowrap; color: #374151;\";\n        row.appendChild(nameLabel);\n\n        for (const dataset of datasets) {\n            const item = document.createElement(\"span\");\n            item.style.cssText = \"display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;\";\n\n            const swatch = document.createElement(\"span\");\n            swatch.style.cssText = `display: inline-block; width: 10px; height: 10px; border-radius: 2px; background: ${dataset.backgroundColor}; flex-shrink: 0;`;\n\n            const phase = document.createElement(\"span\");\n            // The dataset label is \"<model name> usage\" or \"<model name> manufacturing\"; take the last word.\n            phase.textContent = dataset.label.split(\" \").pop();\n            phase.style.color = \"#6b7280\";\n\n            item.appendChild(swatch);\n            item.appendChild(phase);\n            row.appendChild(item);\n        }\n\n        container.appendChild(row);\n    }\n}\n\n/**\n * Remove the HTML legend injected by renderPairedLegend for the given canvas.\n * @param {string} canvasId - The id of the paired chart canvas.\n */\nfunction destroyPairedLegend(canvasId) {\n    const el = document.getElementById(`${canvasId}-legend`);\n    if (el) el.remove();\n}\n\n/**\n * Render a grouped HTML legend for the cumulative overlay chart below its canvas. One row per\n * dataset (model A line, model B line), each with a color swatch and the model name label.\n * @param {Object} payload - The cumulative chart payload (datasets carry label + borderColor).\n * @param {string} canvasId - The id of the canvas the cumulative chart is drawn on.\n */\nfunction renderCumulativeLegend(payload, canvasId) {\n    const canvas = document.getElementById(canvasId);\n    if (!canvas) return;\n\n    const legendId = `${canvasId}-legend`;\n    let container = document.getElementById(legendId);\n    if (!container) {\n        container = document.createElement(\"div\");\n        container.id = legendId;\n        canvas.parentNode.insertBefore(container, canvas.nextSibling);\n    }\n    container.innerHTML = \"\";\n    container.style.cssText = \"padding: 6px 0 2px; font-size: 12px; font-family: 'Inter', system-ui, sans-serif;\";\n\n    for (const dataset of payload.datasets) {\n        const row = document.createElement(\"div\");\n        row.style.cssText = \"display: flex; align-items: center; gap: 8px; margin-bottom: 4px;\";\n\n        const swatch = document.createElement(\"span\");\n        // A short horizontal bar matches the line chart visual better than a square swatch.\n        swatch.style.cssText = `display: inline-block; width: 18px; height: 3px; border-radius: 2px; background: ${dataset.borderColor}; flex-shrink: 0;`;\n\n        const label = document.createElement(\"span\");\n        label.textContent = dataset.label;\n        label.style.cssText = \"font-weight: 600; color: #374151; white-space: nowrap;\";\n\n        row.appendChild(swatch);\n        row.appendChild(label);\n        container.appendChild(row);\n    }\n}\n\nconst COMPARISON_CHART_KEYS = [\"comparisonPairedChart\", \"comparisonCumulativeChart\", \"comparisonDecompositionChart\"];\n\nfunction destroyComparisonChart(canvasId) {\n    window.charts = window.charts || {};\n    if (window.charts[canvasId]) {\n        window.charts[canvasId].destroy();\n        window.charts[canvasId] = null;\n    }\n}\n\nfunction renderChart(canvasId, config) {\n    const canvas = document.getElementById(canvasId);\n    if (!canvas) return;\n    destroyComparisonChart(canvasId);\n    window.charts = window.charts || {};\n    window.charts[canvasId] = new Chart(canvas.getContext(\"2d\"), config);\n}\n\n/**\n * Destroy all three comparison charts. The comparison view is emptied on leave, so its canvases are\n * removed from the DOM; without this the Chart.js instances stay registered against the orphaned\n * canvases and leak (and re-collide on the next open). Called when the comparison view is dismissed.\n */\nfunction destroyComparisonCharts() {\n    COMPARISON_CHART_KEYS.forEach(destroyComparisonChart);\n    [\"comparisonPairedChart\", \"comparisonCumulativeChart\"].forEach((id) => {\n        const el = document.getElementById(`${id}-legend`);\n        if (el) el.remove();\n    });\n}\n\n/**\n * Read the dashboard's swapped-in payloads and (re)draw all three comparison charts. Re-entrant: the\n * Compare tab re-renders fresh on every visit, so any prior chart instances are destroyed first.\n */\nfunction drawComparisonCharts() {\n    const dashboard = document.getElementById(\"comparison-dashboard\");\n    if (!dashboard || typeof window.Chart === \"undefined\") return;\n\n    COMPARISON_CHART_KEYS.forEach(destroyComparisonChart);\n\n    const paired = JSON.parse(dashboard.dataset.pairedChart || \"null\");\n    const cumulative = JSON.parse(dashboard.dataset.cumulativeChart || \"null\");\n    const decomposition = JSON.parse(dashboard.dataset.decompositionChart || \"null\");\n\n    if (paired) {\n        renderChart(\"comparisonPairedChart\", buildPairedChartConfig(paired));\n        renderPairedLegend(paired, \"comparisonPairedChart\");\n    }\n    if (cumulative) {\n        renderChart(\"comparisonCumulativeChart\", buildCumulativeChartConfig(cumulative));\n        renderCumulativeLegend(cumulative, \"comparisonCumulativeChart\");\n    }\n    if (decomposition && decomposition.labels.length) {\n        renderChart(\"comparisonDecompositionChart\", buildDecompositionChartConfig(decomposition));\n    }\n}\n\n// CommonJS exports (like display.js): esbuild bundles this into the ESM result_charts bundle, and Jest\n// (CommonJS, no babel) can require the pure config builders directly.\nmodule.exports = {\n    buildPairedChartConfig,\n    buildCumulativeChartConfig,\n    buildDecompositionChartConfig,\n    renderPairedLegend,\n    destroyPairedLegend,\n    renderCumulativeLegend,\n    drawComparisonCharts,\n    destroyComparisonCharts,\n};\n", "// ============================================================================\n// Configuration Objects\n// ============================================================================\n\n/**\n * Style configuration for legend elements\n */\nexport const LEGEND_STYLES = {\n    container: {\n        display: \"flex\",\n        flexDirection: \"row\",\n        flexWrap: \"wrap\",\n        gap: \"12px\",\n        marginTop: \"24px\",\n        marginBottom: \"24px\",\n        paddingLeft: \"0px\",\n        paddingRight: \"0px\",\n        fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n    },\n    sectionsContainer: {\n        display: \"flex\",\n        flexDirection: \"row\",\n        flexWrap: \"wrap\",\n        gap: \"20px\",\n        alignItems: \"flex-start\",\n    },\n    section: {\n        display: \"flex\",\n        flexDirection: \"column\",\n        gap: \"10px\",\n        flex: \"1 1 calc(50% - 10px)\",\n        minWidth: \"300px\",\n        padding: \"12px\",\n        borderRadius: \"8px\",\n        backgroundColor: \"#ffffffff\",\n        border: \"1px solid rgba(248, 249, 250, 1)\",\n    },\n    categoryLabel: {\n        fontWeight: \"600\",\n        fontSize: \"12px\",\n        textTransform: \"uppercase\",\n        letterSpacing: \"0.5px\",\n        color: \"#495057\",\n        marginBottom: \"4px\",\n    },\n    itemsContainer: {\n        display: \"flex\",\n        flexDirection: \"row\",\n        gap: \"6px\",\n        flexWrap: \"wrap\",\n    },\n    capsule: {\n        base: `\n            display: inline-flex;\n            align-items: center;\n            justify-content: space-between;\n            padding: 5px 10px;\n            border-radius: 12px;\n            border-width: 1.5px;\n            border-style: solid;\n            font-size: 12px;\n            font-weight: 500;\n            cursor: pointer;\n            transition: all 0.15s ease;\n            white-space: nowrap;\n            gap: 6px;\n        `,\n        active: {\n            backgroundColor: (color) => color,\n            color: \"#ffffff\",\n            boxShadow: \"0 1px 2px rgba(0,0,0,0.1)\",\n            opacity: \"1\",\n        },\n        hidden: {\n            backgroundColor: \"transparent\",\n            boxShadow: \"none\",\n            opacity: \"0.4\",\n        },\n        hover: {\n            transform: \"translateY(-1px)\",\n            boxShadow: \"0 2px 4px rgba(0,0,0,0.15)\",\n        },\n    },\n    onlyButton: {\n        base: `\n            display: inline-flex;\n            align-items: center;\n            justify-content: center;\n            padding: 2px 6px;\n            min-width: 32px;\n            border-radius: 4px;\n            background-color: rgba(255, 255, 255, 0.2);\n            color: currentColor;\n            font-size: 9px;\n            font-weight: 600;\n            cursor: pointer;\n            transition: all 0.15s ease;\n            opacity: 0;\n            text-transform: uppercase;\n            letter-spacing: 0.02em;\n            border: none;\n        `,\n        hover: {\n            backgroundColor: \"rgba(255, 255, 255, 0.3)\",\n            opacity: \"1\",\n        },\n    },\n};\n\n/**\n * Categories for splitting legend items\n */\nexport const LEGEND_CATEGORIES = {\n    MANUFACTURING: { key: \"manufacturing\", title: \"Manufacturing\" },\n    USAGE: { key: \"usage\", title: \"Use\" },\n};\n\n/**\n * Font configuration used across charts\n */\nexport const CHART_FONT = {\n    family: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n    size: 12,\n};\n\n/**\n * Color palette for chart elements\n */\nexport const CHART_COLORS = {\n    gridLine: \"rgba(0, 0, 0, 0.05)\",\n    tickLabel: \"#6b7280\",\n    tooltipBackground: \"rgba(0, 0, 0, 0.85)\",\n};\n\n/**\n * Base Chart.js options configuration\n */\nexport const RESULT_CHART_OPTIONS = {\n    locale: \"en-US\",\n    responsive: true,\n    maintainAspectRatio: true,\n    aspectRatio: 2,\n    scales: {\n        x: {\n            offset: true,\n            stacked: true,\n            type: \"time\",\n            time: {\n                tooltipFormat: \"yyyy\",\n                unit: \"year\",\n            },\n            title: { display: false },\n            grid: {\n                display: true,\n                color: CHART_COLORS.gridLine,\n                drawBorder: false,\n            },\n            ticks: {\n                font: CHART_FONT,\n                color: CHART_COLORS.tickLabel,\n            },\n        },\n        y: {\n            stacked: true,\n            title: { display: false },\n            beginAtZero: true,\n            grid: {\n                color: CHART_COLORS.gridLine,\n                drawBorder: false,\n            },\n            ticks: {\n                font: CHART_FONT,\n                color: CHART_COLORS.tickLabel,\n            },\n        },\n    },\n    plugins: {\n        legend: { display: false }, // Use custom legend\n        title: { display: false },\n        // Tooltip configuration imported from tooltip.js\n        tooltip: null, // Will be set dynamically from TOOLTIP_CONFIG\n    },\n};\n\n/**\n * Hardware type configurations with colors and labels\n */\nexport const HARDWARE_TYPE_CONFIG = {\n    Servers_and_storage_energy: {\n        label: \"Servers and storage usage\",\n        backgroundColor: \"#80E5DE\",\n    },\n    ExternalAPIs_energy: {\n        label: \"External APIs usage\",\n        backgroundColor: \"#70CFC9\",\n    },\n    Edge_devices_energy: {\n        label: \"Edge devices and storage usage\",\n        backgroundColor: \"#5CB6B1\",\n        isEdge: true,\n    },\n    Devices_energy: {\n        label: \"Devices usage\",\n        backgroundColor: \"#429693\",\n    },\n    Network_energy: {\n        label: \"Network usage\",\n        backgroundColor: \"#006B6B\",\n    },\n    Servers_and_storage_manufacturing: {\n        label: \"Servers and storage manufacturing\",\n        backgroundColor: \"#9DC4E6\",\n    },\n    ExternalAPIs_manufacturing: {\n        label: \"External APIs manufacturing\",\n        backgroundColor: \"#85AFD8\",\n    },\n    Edge_devices_manufacturing: {\n        label: \"Edge devices and storage manufacturing\",\n        backgroundColor: \"#6595C8\",\n        isEdge: true,\n    },\n    Devices_manufacturing: {\n        label: \"Devices manufacturing\",\n        backgroundColor: \"#2E75B6\",\n    },\n};\n\n/**\n * Chart type specific configurations\n */\nexport const CHART_TYPE_CONFIG = {\n    line: {\n        borderWidth: 2,\n        fill: true,\n        tension: 0.4, // Smooth curves\n    },\n    bar: {\n        borderSkipped: false,\n    },\n};\n\n/**\n * Temporal granularity time unit mappings\n */\nexport const TEMPORAL_UNIT_CONFIG = {\n    month: {\n        unit: \"month\",\n        tooltipFormat: \"MMM yyyy\",\n    },\n    year: {\n        unit: \"year\",\n        tooltipFormat: \"yyyy\",\n    },\n};\n", "// ============================================================================\n// Legend Plugin Utilities & Plugin\n// ============================================================================\n\nimport { LEGEND_STYLES, LEGEND_CATEGORIES } from \"./config.js\";\nimport { filterEdgeAwareItems } from \"./legend_utils.js\";\n\n/**\n * Apply styles from config object to an element\n * @param {HTMLElement} element - Element to style\n * @param {Object} styleConfig - Style configuration object\n */\nexport function applyStyles(element, styleConfig) {\n    Object.entries(styleConfig).forEach(([property, value]) => {\n        element.style[property] = value;\n    });\n}\n\n/**\n * Update a legend capsule's visual state based on hidden status\n * @param {HTMLButtonElement} capsule - The capsule button element\n * @param {boolean} isHidden - Whether the item is hidden\n * @param {string} fillStyle - The color of the item\n */\nfunction updateCapsuleVisualState(capsule, isHidden, fillStyle) {\n    const styles = isHidden ? LEGEND_STYLES.capsule.hidden : LEGEND_STYLES.capsule.active;\n\n    capsule.setAttribute(\"aria-pressed\", !isHidden);\n    capsule.style.borderColor = fillStyle;\n    capsule.style.backgroundColor = isHidden ? \"transparent\" : fillStyle;\n    capsule.style.color = isHidden ? fillStyle : styles.color;\n    capsule.style.boxShadow = styles.boxShadow;\n    capsule.style.opacity = styles.opacity;\n}\n\n/**\n * Show only one specific dataset and hide all others\n * @param {Chart} chart - Chart.js instance\n * @param {number} targetIndex - Dataset index to show\n * @param {HTMLElement} legendContainer - Legend container element\n */\nfunction showOnlyDataset(chart, targetIndex, legendContainer) {\n    chart.data.datasets.forEach((dataset, index) => {\n        const meta = chart.getDatasetMeta(index);\n        meta.hidden = index !== targetIndex;\n\n        // Update capsule visual state\n        const capsule = legendContainer.querySelector(`[data-dataset-index=\"${index}\"]`);\n        if (capsule) {\n            updateCapsuleVisualState(capsule, meta.hidden, dataset.backgroundColor);\n        }\n    });\n    chart.update();\n    updateAllOnlyButtons(chart, legendContainer);\n}\n\n/**\n * Show all datasets\n * @param {Chart} chart - Chart.js instance\n * @param {HTMLElement} legendContainer - Legend container element\n */\nfunction showAllDatasets(chart, legendContainer) {\n    chart.data.datasets.forEach((dataset, index) => {\n        const meta = chart.getDatasetMeta(index);\n        meta.hidden = false;\n\n        // Update capsule visual state\n        const capsule = legendContainer.querySelector(`[data-dataset-index=\"${index}\"]`);\n        if (capsule) {\n            updateCapsuleVisualState(capsule, false, dataset.backgroundColor);\n        }\n    });\n\n    chart.update();\n    updateAllOnlyButtons(chart, legendContainer);\n}\n\n/**\n * Count how many datasets are currently visible\n * @param {Chart} chart - Chart.js instance\n * @returns {number} Number of visible datasets\n */\nfunction countVisibleDatasets(chart) {\n    return chart.data.datasets.filter((_, index) => {\n        const meta = chart.getDatasetMeta(index);\n        return !meta.hidden;\n    }).length;\n}\n\n/**\n * Update all \"only\" buttons to show \"only\" or \"all\" based on current state\n * @param {Chart} chart - Chart.js instance\n * @param {HTMLElement} legendContainer - Legend container element\n */\nfunction updateAllOnlyButtons(chart, legendContainer) {\n    const visibleCount = countVisibleDatasets(chart);\n    const shouldShowAll = visibleCount === 1;\n\n    legendContainer.querySelectorAll(\"[data-dataset-index]\").forEach((capsule) => {\n        const onlyBtn = capsule.querySelector(\"button\");\n        if (onlyBtn) {\n            onlyBtn.textContent = shouldShowAll ? \"all\" : \"only\";\n            onlyBtn.setAttribute(\"title\", shouldShowAll ? \"Show all datasets\" : \"Show only this dataset\");\n        }\n    });\n}\n\n/**\n * Create a legend capsule button for a chart item\n * @param {Object} item - Legend item from Chart.js\n * @param {Chart} chart - Chart.js instance\n * @param {HTMLElement} legendContainer - Legend container element\n * @returns {HTMLButtonElement} Capsule button element\n */\nexport function createLegendCapsule(item, chart, legendContainer) {\n    const capsule = document.createElement(\"div\");\n    capsule.style.cssText = LEGEND_STYLES.capsule.base;\n    capsule.setAttribute(\"data-dataset-index\", item.datasetIndex);\n\n    // Label span - use full text\n    const labelSpan = document.createElement(\"span\");\n    labelSpan.textContent = item.text;\n    labelSpan.style.flex = \"1\";\n\n    // \"Only\" button\n    const onlyBtn = document.createElement(\"button\");\n    onlyBtn.textContent = \"only\";\n    onlyBtn.setAttribute(\"type\", \"button\");\n    onlyBtn.style.cssText = LEGEND_STYLES.onlyButton.base;\n    onlyBtn.setAttribute(\"title\", \"Show only this dataset\");\n\n    capsule.appendChild(labelSpan);\n    capsule.appendChild(onlyBtn);\n\n    // Set initial visual state\n    updateCapsuleVisualState(capsule, item.hidden, item.fillStyle);\n\n    // Hover effect on capsule\n    capsule.addEventListener(\"mouseenter\", () => {\n        const meta = chart.getDatasetMeta(item.datasetIndex);\n        if (!meta.hidden) {\n            capsule.style.transform = \"translateY(-1px)\";\n            capsule.style.boxShadow = \"0 2px 4px rgba(0,0,0,0.15)\";\n        }\n        // Show \"only\" button on hover\n        onlyBtn.style.opacity = \"1\";\n        onlyBtn.style.backgroundColor = \"rgba(255, 255, 255, 0.3)\";\n    });\n\n    capsule.addEventListener(\"mouseleave\", () => {\n        const meta = chart.getDatasetMeta(item.datasetIndex);\n        capsule.style.transform = \"translateY(0)\";\n        capsule.style.boxShadow = meta.hidden ? \"none\" : \"0 1px 2px rgba(0,0,0,0.1)\";\n        // Hide \"only\" button when not hovering\n        onlyBtn.style.opacity = \"0\";\n    });\n\n    // Click on label: Toggle this dataset\n    labelSpan.style.cursor = \"pointer\";\n    labelSpan.addEventListener(\"click\", (e) => {\n        e.stopPropagation();\n        const meta = chart.getDatasetMeta(item.datasetIndex);\n        meta.hidden = !meta.hidden;\n        updateCapsuleVisualState(capsule, meta.hidden, item.fillStyle);\n        chart.update();\n        updateAllOnlyButtons(chart, legendContainer);\n    });\n\n    // Click on \"only/all\" button\n    onlyBtn.addEventListener(\"click\", (e) => {\n        e.stopPropagation();\n        const visibleCount = countVisibleDatasets(chart);\n\n        if (visibleCount === 1) {\n            // If only one is visible, clicking \"all\" shows everything\n            showAllDatasets(chart, legendContainer);\n        } else {\n            // Otherwise, clicking \"only\" shows only this dataset\n            showOnlyDataset(chart, item.datasetIndex, legendContainer);\n        }\n    });\n\n    onlyBtn.addEventListener(\"mouseenter\", () => {\n        onlyBtn.style.backgroundColor = \"rgba(255, 255, 255, 0.4)\";\n    });\n\n    onlyBtn.addEventListener(\"mouseleave\", () => {\n        onlyBtn.style.backgroundColor = \"rgba(255, 255, 255, 0.3)\";\n    });\n\n    return capsule;\n}\n\n/**\n * Create a compact legend section with inline title and items\n * @param {string} title - Section title\n * @param {string} categoryKey - Category key\n * @param {Array} items - Legend items for this section\n * @param {Chart} chart - Chart.js instance\n * @param {HTMLElement} legendContainer - Legend container element\n * @returns {HTMLDivElement} Section element\n */\nexport function createLegendSection(title, categoryKey, items, chart, legendContainer) {\n    const section = document.createElement(\"div\");\n    applyStyles(section, LEGEND_STYLES.section);\n    section.setAttribute(\"data-category\", categoryKey);\n\n    // Category label\n    const label = document.createElement(\"div\");\n    label.textContent = title;\n    applyStyles(label, LEGEND_STYLES.categoryLabel);\n    section.appendChild(label);\n\n    const itemsContainer = document.createElement(\"div\");\n    applyStyles(itemsContainer, LEGEND_STYLES.itemsContainer);\n\n    items.forEach((item) => {\n        itemsContainer.appendChild(createLegendCapsule(item, chart, legendContainer));\n    });\n\n    section.appendChild(itemsContainer);\n    return section;\n}\n\n/**\n * Get or create legend container for a chart\n * Place it inside the canvas's parent div (the content-result-chart container)\n * @param {Chart} chart - Chart.js instance\n * @returns {HTMLElement|null} Legend container element\n */\nexport function getLegendContainer(chart) {\n    const legendId = `${chart.canvas.id}-legend`;\n    let container = document.getElementById(legendId);\n\n    if (!container) {\n        container = document.createElement(\"div\");\n        container.id = legendId;\n\n        // Insert legend inside the canvas parent container (after the canvas)\n        chart.canvas.parentNode.appendChild(container);\n    }\n\n    return container;\n}\n\n/**\n * Filter legend items by category\n * @param {Array} items - Legend items to filter\n * @param {string} categoryKey - Category key to filter by\n * @returns {Array} Filtered items\n */\nexport function filterItemsByCategory(items, categoryKey) {\n    return items.filter((item) => item.text.toLowerCase().includes(categoryKey));\n}\n\n/**\n * Custom legend plugin to create capsule-style split legend\n */\nexport const splitCapsuleLegendPlugin = {\n    id: \"splitCapsuleLegend\",\n    afterUpdate(chart) {\n        const { legend } = chart;\n        if (!legend?.legendItems) return;\n\n        const legendContainer = getLegendContainer(chart);\n        if (!legendContainer) return;\n\n        // Only rebuild legend if it's empty or explicitly marked for rebuild\n        const needsRebuild = legendContainer.children.length === 0 || chart._legendNeedsRebuild === true;\n\n        if (!needsRebuild) return;\n\n        chart._legendNeedsRebuild = false;\n\n        // Clear and style container\n        legendContainer.innerHTML = \"\";\n        applyStyles(legendContainer, LEGEND_STYLES.container);\n\n        // Create sections container\n        const sectionsContainer = document.createElement(\"div\");\n        applyStyles(sectionsContainer, LEGEND_STYLES.sectionsContainer);\n\n        // Hide edge-device items when edge modeling is not active (the toggle state is read\n        // from the body class set by edge_modeling_toggle.js before charts are rendered).\n        const edgeModelingOn = document.body.classList.contains(\"edge-modeling-on\");\n        const visibleItems = filterEdgeAwareItems(legend.legendItems, chart.data.datasets, edgeModelingOn);\n\n        // Split and render legend items by category\n        const usageItems = filterItemsByCategory(visibleItems, LEGEND_CATEGORIES.USAGE.key).reverse();\n        const manufacturingItems = filterItemsByCategory(visibleItems, LEGEND_CATEGORIES.MANUFACTURING.key).reverse();\n\n        if (manufacturingItems.length > 0) {\n            sectionsContainer.appendChild(\n                createLegendSection(\n                    LEGEND_CATEGORIES.MANUFACTURING.title,\n                    LEGEND_CATEGORIES.MANUFACTURING.key,\n                    manufacturingItems,\n                    chart,\n                    legendContainer\n                )\n            );\n        }\n\n        if (usageItems.length > 0) {\n            sectionsContainer.appendChild(\n                createLegendSection(\n                    LEGEND_CATEGORIES.USAGE.title,\n                    LEGEND_CATEGORIES.USAGE.key,\n                    usageItems,\n                    chart,\n                    legendContainer\n                )\n            );\n        }\n\n        legendContainer.appendChild(sectionsContainer);\n    },\n};\n", "/**\n * Tooltip Configuration and Transforms for Result Charts\n * Handles tooltip appearance, item ordering, and section grouping\n */\n\nimport { CHART_FONT, CHART_COLORS } from \"./config.js\";\nimport { formatEmissionsQuantity } from \"./display.js\";\n\n/**\n * Categorize and sort tooltip items into manufacturing and usage groups\n * @param {Array} tooltipItems - Array of Chart.js tooltip items\n * @returns {Object} Object with sorted manufacturing and usage arrays\n */\nfunction categorizeAndSortTooltipItems(tooltipItems) {\n    const manufacturing = [];\n    const usage = [];\n\n    tooltipItems.forEach((item) => {\n        if (item.dataset.label.includes(\"manufacturing\")) {\n            manufacturing.push(item);\n        } else if (item.dataset.label.includes(\"usage\")) {\n            usage.push(item);\n        }\n    });\n\n    // Reverse both arrays to show items in reverse order\n    manufacturing.reverse();\n    usage.reverse();\n\n    return { manufacturing, usage };\n}\n\n/**\n * Calculate total for a category\n * @param {Array} items - Array of tooltip items\n * @returns {number} Sum of all values\n */\nfunction calculateTotal(items) {\n    return items.reduce((sum, item) => sum + (item.parsed.y || 0), 0);\n}\n\n/**\n * Custom tooltip external function that renders HTML with sections\n */\nexport function customTooltipHandler(context) {\n    const unit = window.emissions?.display_unit || \"t\";\n    // Tooltip Element\n    let tooltipEl = document.getElementById(\"chartjs-tooltip\");\n\n    // Create element on first render\n    if (!tooltipEl) {\n        tooltipEl = document.createElement(\"div\");\n        tooltipEl.id = \"chartjs-tooltip\";\n        tooltipEl.innerHTML = \"<table></table>\";\n        document.body.appendChild(tooltipEl);\n    }\n\n    // Hide if no tooltip\n    const tooltipModel = context.tooltip;\n    if (tooltipModel.opacity === 0) {\n        tooltipEl.style.opacity = 0;\n        return;\n    }\n\n    // Set Text\n    if (tooltipModel.body) {\n        const titleLines = tooltipModel.title || [];\n        const { manufacturing, usage } = categorizeAndSortTooltipItems(tooltipModel.dataPoints);\n\n        let innerHtml = \"<thead>\";\n        titleLines.forEach((title) => {\n            innerHtml += \"<tr><th>\" + title + \"</th></tr>\";\n        });\n        innerHtml += \"</thead><tbody>\";\n\n        // Add MANUFACTURING section\n        if (manufacturing.length > 0) {\n            const manufacturingTotal = calculateTotal(manufacturing);\n            innerHtml +=\n                '<tr><td class=\"section-header\">MANUFACTURING: <span class=\"section-total\">' +\n                `${formatEmissionsQuantity(manufacturingTotal, unit)}</span></td></tr>`;\n            manufacturing.forEach((item) => {\n                const colors = item.dataset.backgroundColor;\n                const label = item.dataset.label;\n\n                innerHtml += \"<tr><td>\";\n                innerHtml += '<span class=\"tooltip-color-box\" style=\"background:' + colors + '\"></span>';\n                innerHtml += `${label}: ${formatEmissionsQuantity(item.parsed.y, unit)}`;\n                innerHtml += \"</td></tr>\";\n            });\n        }\n\n        // Add USAGE section\n        if (usage.length > 0) {\n            if (manufacturing.length > 0) {\n                innerHtml += '<tr><td class=\"section-spacer\"></td></tr>';\n            }\n            const usageTotal = calculateTotal(usage);\n            innerHtml +=\n                '<tr><td class=\"section-header\">USAGE: <span class=\"section-total\">' +\n                `${formatEmissionsQuantity(usageTotal, unit)}</span></td></tr>`;\n            usage.forEach((item) => {\n                const colors = item.dataset.backgroundColor;\n                const label = item.dataset.label;\n\n                innerHtml += \"<tr><td>\";\n                innerHtml += '<span class=\"tooltip-color-box\" style=\"background:' + colors + '\"></span>';\n                innerHtml += `${label}: ${formatEmissionsQuantity(item.parsed.y, unit)}`;\n                innerHtml += \"</td></tr>\";\n            });\n        }\n\n        // Add total if both categories exist\n        if (manufacturing.length > 0 && usage.length > 0) {\n            const manufacturingTotal = calculateTotal(manufacturing);\n            const usageTotal = calculateTotal(usage);\n            const grandTotal = manufacturingTotal + usageTotal;\n\n            innerHtml += '<tr><td class=\"section-spacer\"></td></tr>';\n            innerHtml += `<tr><td class=\"total-row\">Total: ${formatEmissionsQuantity(grandTotal, unit)}</td></tr>`;\n        }\n\n        innerHtml += \"</tbody>\";\n\n        const tableRoot = tooltipEl.querySelector(\"table\");\n        tableRoot.innerHTML = innerHtml;\n    }\n\n    const position = context.chart.canvas.getBoundingClientRect();\n\n    // Display, position, and set styles for font\n    tooltipEl.style.opacity = 1;\n    tooltipEl.style.position = \"absolute\";\n    tooltipEl.style.pointerEvents = \"none\";\n    tooltipEl.style.backgroundColor = CHART_COLORS.tooltipBackground;\n    tooltipEl.style.borderRadius = \"8px\";\n    tooltipEl.style.color = \"#fff\";\n    tooltipEl.style.fontFamily = CHART_FONT.family;\n    tooltipEl.style.fontSize = CHART_FONT.size + \"px\";\n    tooltipEl.style.zIndex = \"1000\";\n    tooltipEl.style.font = tooltipModel.options.bodyFont.string;\n    tooltipEl.style.padding = tooltipModel.options.padding + \"px \" + tooltipModel.options.padding + \"px\";\n\n    // Calculate initial position\n    let left = position.left + window.pageXOffset + tooltipModel.caretX;\n    let top = position.top + window.pageYOffset + tooltipModel.caretY;\n\n    // Get tooltip dimensions (need to briefly show it to measure)\n    tooltipEl.style.left = left + \"px\";\n    tooltipEl.style.top = top + \"px\";\n    const tooltipRect = tooltipEl.getBoundingClientRect();\n\n    // Adjust horizontal position if tooltip goes off-screen\n    const viewportWidth = window.innerWidth;\n    if (left + tooltipRect.width > viewportWidth) {\n        // Position to the left of the cursor instead\n        left = position.left + window.pageXOffset + tooltipModel.caretX - tooltipRect.width - 10;\n    }\n    // Make sure it doesn't go off the left edge\n    if (left < 0) {\n        left = 10;\n    }\n\n    // Adjust vertical position if tooltip goes off-screen\n    const viewportHeight = window.innerHeight;\n    if (top + tooltipRect.height > viewportHeight + window.pageYOffset) {\n        // Position above the cursor instead\n        top = position.top + window.pageYOffset + tooltipModel.caretY - tooltipRect.height - 10;\n    }\n    // Make sure it doesn't go off the top edge\n    if (top < window.pageYOffset) {\n        top = window.pageYOffset + 10;\n    }\n\n    // Apply final position\n    tooltipEl.style.left = left + \"px\";\n    tooltipEl.style.top = top + \"px\";\n}\n\n/**\n * Complete tooltip configuration object with external custom handler\n */\nexport const TOOLTIP_CONFIG = {\n    enabled: false, // Disable default tooltip\n    external: customTooltipHandler,\n    mode: \"index\",\n    intersect: false,\n};\n\n/**\n * Add tooltip styles to document head\n */\nexport function injectTooltipStyles() {\n    if (document.getElementById(\"chartjs-tooltip-styles\")) {\n        return; // Already injected\n    }\n\n    const style = document.createElement(\"style\");\n    style.id = \"chartjs-tooltip-styles\";\n    style.innerHTML = `\n        #chartjs-tooltip {\n            opacity: 0;\n            transition: opacity 0.15s ease;\n        }\n        \n        #chartjs-tooltip table {\n            margin: 0;\n            border-spacing: 0;\n        }\n        \n        #chartjs-tooltip thead tr th {\n            font-weight: 600;\n            font-size: 14px;\n            margin-bottom: 8px;\n            padding-bottom: 8px;\n            border-bottom: 1px solid rgba(255, 255, 255, 0.2);\n        }\n        \n        #chartjs-tooltip tbody tr td {\n            padding: 4px 0;\n            font-size: 12px;\n        }\n        \n        #chartjs-tooltip .section-header {\n            font-weight: 600;\n            font-size: 11px;\n            text-transform: uppercase;\n            letter-spacing: 0.5px;\n            color: rgba(255, 255, 255, 0.7);\n            padding-top: 4px;\n            padding-bottom: 2px;\n        }\n        \n        #chartjs-tooltip .section-total {\n            font-weight: 700;\n            font-size: 12px;\n            color: rgba(255, 255, 255, 0.95);\n            text-transform: none;\n            letter-spacing: normal;\n        }\n        \n        #chartjs-tooltip .section-spacer {\n            height: 8px;\n        }\n        \n        #chartjs-tooltip .total-row {\n            font-weight: 600;\n            padding-top: 4px;\n            border-top: 1px solid rgba(255, 255, 255, 0.2);\n        }\n        \n        #chartjs-tooltip .tooltip-color-box {\n            display: inline-block;\n            width: 10px;\n            height: 10px;\n            margin-right: 6px;\n            border-radius: 2px;\n        }\n    `;\n    document.head.appendChild(style);\n}\n", "// ============================================================================\n// Chart Creation & Management\n// ============================================================================\n\nimport { HARDWARE_TYPE_CONFIG, CHART_TYPE_CONFIG, TEMPORAL_UNIT_CONFIG, RESULT_CHART_OPTIONS } from \"./config.js\";\nimport { splitCapsuleLegendPlugin } from \"./legend.js\";\nimport { TOOLTIP_CONFIG, injectTooltipStyles } from \"./tooltip.js\";\n\n/**\n * Show loading spinner and hide chart content\n */\nexport function displayLoaderResult() {\n    document.querySelectorAll(\".spinner-result-chart\").forEach((loader) => {\n        loader.classList.remove(\"d-none\");\n    });\n    document.querySelectorAll(\".content-result-chart\").forEach((chart) => {\n        chart.classList.add(\"d-none\");\n    });\n}\n\n/**\n * Prepare dataset configuration for a hardware type\n * @param {string} hardwareType - Hardware type key\n * @param {Array} chartValues - Data values for this hardware type\n * @param {string} chartType - Chart type ('line' or 'bar')\n * @returns {Object} Dataset configuration\n */\nexport function createDatasetConfig(hardwareType, chartValues, chartType) {\n    const config = { ...HARDWARE_TYPE_CONFIG[hardwareType] };\n    const typeConfig = CHART_TYPE_CONFIG[chartType] || {};\n\n    return {\n        ...config,\n        ...typeConfig,\n        data: chartValues,\n    };\n}\n\n/**\n * Build chart data from emissions data\n * @param {string} chartType - Chart type ('line' or 'bar')\n * @param {string} granularity - Temporal granularity ('month' or 'year')\n * @returns {Object} Chart.js data object\n */\nexport function buildChartData(chartType, granularity) {\n    const datasets = [];\n\n    if (!window.emissions.dates.length) {\n        return { labels: [], datasets };\n    }\n\n    for (const hardwareType of Object.keys(window.emissions.values)) {\n        let values = Object.values(\n            sumDailyValuesByDisplayGranularity(\n                window.emissions.dates,\n                window.emissions.values[hardwareType],\n                granularity\n            )\n        );\n\n        // Apply cumulative sum for line charts\n        if (chartType === \"line\") {\n            values = cumulativeSumFromArray(values);\n        }\n\n        datasets.push(createDatasetConfig(hardwareType, values, chartType));\n    }\n\n    const labels = generateTimeIndexLabels(window.emissions.dates[0], granularity, datasets[0]?.data.length || 0);\n\n    return { labels, datasets };\n}\n\n/**\n * Configure chart options based on temporal granularity\n * @param {string} granularity - Temporal granularity ('month' or 'year')\n * @returns {Object} Chart.js options object\n */\nexport function configureChartOptions(granularity) {\n    const options = JSON.parse(JSON.stringify(RESULT_CHART_OPTIONS)); // Deep clone\n    const timeConfig = TEMPORAL_UNIT_CONFIG[granularity] || TEMPORAL_UNIT_CONFIG.year;\n\n    options.scales.x.time.unit = timeConfig.unit;\n    options.scales.x.time.tooltipFormat = timeConfig.tooltipFormat;\n\n    // Apply tooltip configuration\n    options.plugins.tooltip = TOOLTIP_CONFIG;\n\n    return options;\n}\n\n/**\n * Get or create legend container next to canvas\n * @param {HTMLCanvasElement} canvas - Canvas element\n * @param {string} chartType - Chart type identifier\n * @returns {HTMLElement} Legend container\n */\nexport function ensureLegendContainer(canvas, chartType) {\n    const legendId = `${chartType}Chart-legend`;\n    let container = document.getElementById(legendId);\n\n    if (!container) {\n        container = document.createElement(\"div\");\n        container.id = legendId;\n        canvas.parentNode.insertBefore(container, canvas.nextSibling);\n    } else {\n        container.innerHTML = \"\"; // Clear existing content\n    }\n\n    return container;\n}\n\n/**\n * Destroy existing chart instance if it exists\n * @param {string} chartType - Chart type identifier\n */\nexport function destroyExistingChart(chartType) {\n    const chartKey = `${chartType}Chart`;\n    if (window.charts?.[chartKey]) {\n        window.charts[chartKey].destroy();\n        window.charts[chartKey] = null;\n    }\n}\n\n/**\n * Create and render a result chart\n * @param {string} chartType - Chart type ('line' or 'bar')\n * @param {string} granularity - Temporal granularity ('month' or 'year')\n */\nexport function drawResultChart(chartType, granularity) {\n    destroyExistingChart(chartType);\n\n    const canvas = document.getElementById(`${chartType}Chart`);\n    if (!canvas) return;\n\n    ensureLegendContainer(canvas, chartType);\n\n    const chartData = buildChartData(chartType, granularity);\n    const chartOptions = configureChartOptions(granularity);\n\n    const chart = new Chart(canvas.getContext(\"2d\"), {\n        type: chartType,\n        data: chartData,\n        options: chartOptions,\n        plugins: [splitCapsuleLegendPlugin],\n    });\n\n    // Mark that legend needs initial build\n    chart._legendNeedsRebuild = true;\n\n    // Store chart instance\n    window.charts = window.charts || {};\n    window.charts[`${chartType}Chart`] = chart;\n}\n\n/**\n * Draw bar chart with current temporal granularity from UI\n */\nexport function drawBarResultChart() {\n    const granularitySelect = document.getElementById(\"results_temporal_granularity\");\n    const granularity = granularitySelect?.value || \"year\";\n    drawResultChart(\"bar\", granularity);\n}\n\n/**\n * Initialize charts when results are ready\n */\nexport function initializeResultCharts() {\n    // Inject tooltip styles once on initialization\n    injectTooltipStyles();\n\n    drawResultChart(\"line\", \"month\");\n    drawBarResultChart();\n}\n", "// ============================================================================\n// Result Charts - Main Entry Point\n// ============================================================================\n\nimport { drawBarResultChart, displayLoaderResult, initializeResultCharts } from \"./chart.js\";\nimport { drawComparisonCharts, destroyComparisonCharts } from \"./comparison_charts.js\";\n\n// ============================================================================\n// Global Exports for HTML Event Handlers\n// ============================================================================\n\n/**\n * Handle temporal granularity change\n * Updates the chart title and redraws the chart\n */\nfunction handleTemporalGranularityChange() {\n    const select = document.getElementById(\"results_temporal_granularity\");\n    const title = document.getElementById(\"barChartTitle\");\n\n    if (select && title) {\n        const value = select.value;\n        const capitalized = value.charAt(0).toUpperCase() + value.slice(1);\n        title.textContent = `${capitalized}ly CO2 emissions`;\n    }\n\n    drawBarResultChart();\n}\n\n// Expose functions to global scope for inline event handlers and other scripts\nwindow.drawBarResultChart = drawBarResultChart;\nwindow.displayLoaderResult = displayLoaderResult;\nwindow.handleTemporalGranularityChange = handleTemporalGranularityChange;\n// The Compare dashboard (HTMX-swapped into the resident #comparison-view) drives its own draw from\n// this; dismissing the comparison view destroys the charts (model_comparison.js) so they don't leak.\nwindow.drawComparisonCharts = drawComparisonCharts;\nwindow.destroyComparisonCharts = destroyComparisonCharts;\n\n// ============================================================================\n// Event Listeners\n// ============================================================================\n\n/**\n * Initialize charts when results are ready\n */\ndocument.body.addEventListener(\"triggerResultRendering\", () => {\n    initializeResultCharts();\n});\n"],
  "mappings": "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",
  "names": ["require_legend_utils", "__commonJSMin", "exports", "module", "filterEdgeAwareItems", "legendItems", "datasets", "edgeModelingOn", "item", "require_display", "__commonJSMin", "exports", "module", "UNIT_FAMILIES", "normalizeUnit", "unit", "getUnitFamily", "normalizedUnit", "family", "convertValue", "value", "fromUnit", "toUnit", "normalizedFrom", "normalizedTo", "conversionToKg", "bestDisplayUnit", "representative", "idx", "candidateUnit", "roundToSigFigs", "sigFigs", "scale", "formatDisplayNumber", "humanReadableUnit", "formatQuantityForDisplay", "displayUnit", "convertedValue", "roundedValue", "formatEmissionsQuantity", "formattedQuantity", "require_comparison_charts", "__commonJSMin", "exports", "module", "SHARED_FONT", "GRID_COLOR", "TICK_COLOR", "FORMATTED_VALUE_TOOLTIP", "context", "labels", "display", "formatAxisTick", "value", "scale", "axisTitle", "payload", "suffix", "buildPairedChartConfig", "datasets", "dataset", "buildCumulativeChartConfig", "index", "decompositionValueLabelsPlugin", "chart", "ctx", "meta", "bar", "text", "positive", "buildDecompositionChartConfig", "renderPairedLegend", "canvasId", "canvas", "legendId", "container", "systemNames", "groups", "stack", "row", "nameLabel", "item", "swatch", "phase", "destroyPairedLegend", "el", "renderCumulativeLegend", "label", "COMPARISON_CHART_KEYS", "destroyComparisonChart", "renderChart", "config", "destroyComparisonCharts", "id", "drawComparisonCharts", "dashboard", "paired", "cumulative", "decomposition", "LEGEND_STYLES", "color", "LEGEND_CATEGORIES", "CHART_FONT", "CHART_COLORS", "RESULT_CHART_OPTIONS", "HARDWARE_TYPE_CONFIG", "CHART_TYPE_CONFIG", "TEMPORAL_UNIT_CONFIG", "import_legend_utils", "applyStyles", "element", "styleConfig", "property", "value", "updateCapsuleVisualState", "capsule", "isHidden", "fillStyle", "styles", "LEGEND_STYLES", "showOnlyDataset", "chart", "targetIndex", "legendContainer", "dataset", "index", "meta", "updateAllOnlyButtons", "showAllDatasets", "countVisibleDatasets", "_", "shouldShowAll", "onlyBtn", "createLegendCapsule", "item", "labelSpan", "e", "createLegendSection", "title", "categoryKey", "items", "section", "label", "itemsContainer", "getLegendContainer", "legendId", "container", "filterItemsByCategory", "splitCapsuleLegendPlugin", "legend", "sectionsContainer", "edgeModelingOn", "visibleItems", "usageItems", "LEGEND_CATEGORIES", "manufacturingItems", "import_display", "categorizeAndSortTooltipItems", "tooltipItems", "manufacturing", "usage", "item", "calculateTotal", "items", "sum", "customTooltipHandler", "context", "unit", "tooltipEl", "tooltipModel", "titleLines", "innerHtml", "title", "manufacturingTotal", "colors", "label", "usageTotal", "grandTotal", "tableRoot", "position", "CHART_COLORS", "CHART_FONT", "left", "top", "tooltipRect", "viewportWidth", "viewportHeight", "TOOLTIP_CONFIG", "injectTooltipStyles", "style", "displayLoaderResult", "loader", "chart", "createDatasetConfig", "hardwareType", "chartValues", "chartType", "config", "HARDWARE_TYPE_CONFIG", "typeConfig", "CHART_TYPE_CONFIG", "buildChartData", "granularity", "datasets", "values", "configureChartOptions", "options", "RESULT_CHART_OPTIONS", "timeConfig", "TEMPORAL_UNIT_CONFIG", "TOOLTIP_CONFIG", "ensureLegendContainer", "canvas", "legendId", "container", "destroyExistingChart", "chartKey", "drawResultChart", "chartData", "chartOptions", "splitCapsuleLegendPlugin", "drawBarResultChart", "initializeResultCharts", "injectTooltipStyles", "import_comparison_charts", "handleTemporalGranularityChange", "select", "title", "value", "capitalized", "drawBarResultChart", "displayLoaderResult", "initializeResultCharts"]
}
