@kenz1117/dsh-ui-usage-billing 0.9.5 → 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -24,7 +24,7 @@ window.__ModuleLoader__.load({
24
24
  }
25
25
  //#endregion
26
26
  //#region \0dsh-css:/Users/ken/deepseek-harness/packages/client/ui-usage-billing/src/client/UsageBilling.module.css.mjs
27
- const css = ".VWh0dG_railButton{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);width:36px;height:36px;color:var(--dsw-alias-label-secondary);cursor:pointer;border-radius:8px;flex:none;justify-content:center;align-items:center;padding:0;transition:border-color .16s,color .16s;display:flex}.VWh0dG_railButton:hover,.VWh0dG_railButton:focus-visible{border-color:var(--dsw-static-blue-500);color:var(--dsw-static-blue-500);outline:none}.VWh0dG_railButton svg{stroke-width:2px;width:18px;height:18px}.VWh0dG_trigger{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);width:100%;min-width:0;color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;border-radius:12px;align-items:center;gap:10px;padding:9px 12px;transition:border-color .16s,background-color .16s;display:flex;position:relative;overflow:hidden}.VWh0dG_trigger:hover,.VWh0dG_trigger:focus-visible{border-color:var(--dsw-static-blue-500);outline:none}.VWh0dG_triggerIcon{background:linear-gradient(135deg, var(--dsw-static-blue-500), var(--dsw-static-blue-400));width:30px;height:30px;color:var(--dsw-static-neutral-bluish-00);box-shadow:0 2px 8px -2px color-mix(in srgb, var(--dsw-static-blue-500) 55%, transparent);border-radius:10px;flex:none;justify-content:center;align-items:center;display:inline-flex}.VWh0dG_triggerIcon svg{stroke-width:2px;width:16px;height:16px}.VWh0dG_triggerBody{flex-direction:column;flex:1;gap:1px;min-width:0;display:flex}.VWh0dG_triggerRow{align-items:baseline;gap:5px;min-width:0;display:inline-flex}.VWh0dG_triggerAmount{color:var(--dsw-alias-label-primary);letter-spacing:-.02em;font-variant-numeric:tabular-nums;white-space:nowrap;font-size:16px;font-weight:700;line-height:20px}.VWh0dG_triggerSub{color:var(--dsw-alias-label-tertiary);white-space:nowrap;text-overflow:ellipsis;font-size:10px;line-height:14px;overflow:hidden}.VWh0dG_triggerMeta{color:var(--dsw-alias-label-tertiary);white-space:nowrap;letter-spacing:.02em;text-transform:uppercase;font-size:9.5px;font-weight:600;line-height:12px}.VWh0dG_triggerSpark{flex:none;align-items:flex-end;gap:2px;height:20px;display:flex}.VWh0dG_triggerSparkBar,.VWh0dG_triggerSparkHot{background:var(--dsw-static-blue-500);opacity:.6;border-radius:1px 1px 0 0;width:3px}.VWh0dG_triggerSparkHot{opacity:1}.VWh0dG_triggerWrap{flex:auto;width:100%;min-width:0;display:block;position:relative}.VWh0dG_triggerPop{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);box-shadow:var(--dsw-shadow-lv2);opacity:0;pointer-events:none;z-index:10;border-radius:10px;flex-direction:column;gap:6px;padding:12px 14px;transition:opacity .16s,transform .16s;display:flex;position:absolute;bottom:calc(100% + 8px);left:0;right:0;transform:translateY(4px)}.VWh0dG_triggerWrap:hover .VWh0dG_triggerPop,.VWh0dG_triggerWrap:focus-within .VWh0dG_triggerPop{opacity:1;transform:translateY(0)}.VWh0dG_triggerPopRow{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.VWh0dG_triggerPopLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.VWh0dG_triggerPopValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;font-size:13px;font-weight:600;line-height:18px}.VWh0dG_triggerPopBars{border-top:1px solid var(--dsw-alias-border-l1);align-items:flex-end;gap:4px;height:22px;margin-top:4px;padding-top:8px;display:flex}.VWh0dG_triggerPopBar{background:var(--dsw-static-blue-500);border-radius:2px;flex:1;transition:height .2s}.VWh0dG_dashboardModal{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);width:min(760px,100vw - 48px);max-height:min(760px,88vh);box-shadow:var(--dsw-shadow-lv3);animation:.18s ease-out VWh0dG_dashboardIn}@keyframes VWh0dG_dashboardIn{0%{opacity:0;transform:translateY(8px)scale(.98)}to{opacity:1;transform:none}}div[role=presentation]:has(>.dsh-billing-modal)>div[aria-hidden=true]:first-child{backdrop-filter:blur(8px)saturate(1.25)}.VWh0dG_dashboard{flex-direction:column;width:100%;max-height:min(760px,88vh);display:flex}.VWh0dG_dashboardHead{border-bottom:1px solid var(--dsw-alias-border-l1);justify-content:space-between;align-items:flex-start;gap:12px;padding:20px 24px 14px;display:flex}.VWh0dG_dashboardTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:17px;font-weight:600;line-height:24px}.VWh0dG_dashboardSubtitle{color:var(--dsw-alias-label-caption);margin:3px 0 0;font-size:12px;line-height:17px}.VWh0dG_closeButton{width:30px;height:30px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px;flex:none;justify-content:center;align-items:center;transition:background-color .14s;display:inline-flex}.VWh0dG_closeButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.VWh0dG_closeButton svg{stroke-width:2px;width:16px;height:16px}.VWh0dG_dashboardBody{flex-direction:column;gap:14px;padding:16px 24px 24px;display:flex;overflow-y:auto}.VWh0dG_tabNav{border-bottom:1px solid var(--dsw-alias-border-l1);align-items:center;gap:4px;padding:10px 24px;display:flex}.VWh0dG_tabButton{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:999px;padding:5px 14px;font-size:12.5px;font-weight:500;line-height:18px;transition:background-color .16s,color .16s,box-shadow .16s}.VWh0dG_tabButton:hover,.VWh0dG_tabButton:focus-visible{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover);outline:none}.VWh0dG_tabButtonActive,.VWh0dG_tabButtonActive:hover,.VWh0dG_tabButtonActive:focus-visible{background:var(--dsw-static-blue-500);color:var(--dsw-static-neutral-bluish-00);font-weight:600}.VWh0dG_tabPanel{flex-direction:column;gap:14px;animation:.14s ease-out VWh0dG_tabPanelIn;display:flex}@keyframes VWh0dG_tabPanelIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}.VWh0dG_hero{border:1px solid var(--dsw-alias-border-l1);background:linear-gradient(180deg, var(--dsw-alias-bg-layer-2), var(--dsw-alias-bg-layer-1));box-shadow:inset 0 1px 0 color-mix(in srgb, var(--dsw-static-neutral-bluish-00) 30%, transparent);border-radius:16px;flex-direction:column;gap:18px;padding:22px 24px;display:flex;position:relative;overflow:hidden}.VWh0dG_heroTop{justify-content:space-between;align-items:center;gap:24px;display:flex}.VWh0dG_heroMain{flex-direction:column;gap:2px;min-width:0;display:flex}.VWh0dG_heroLabel{color:var(--dsw-alias-label-tertiary);text-transform:uppercase;letter-spacing:.08em;white-space:nowrap;font-size:11px;line-height:16px}.VWh0dG_heroReadout{align-items:baseline;gap:4px;display:flex}.VWh0dG_heroCurrency{letter-spacing:-.01em;color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;font-size:20px;font-weight:600;line-height:30px}.VWh0dG_heroValue{letter-spacing:-.03em;font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--dsw-alias-label-primary);font-size:56px;font-weight:700;line-height:64px}.VWh0dG_heroMeta{color:var(--dsw-alias-label-caption);white-space:nowrap;margin-top:4px;font-size:12px;line-height:17px}.VWh0dG_heroGauge{flex:none;width:96px;height:96px;position:relative}.VWh0dG_heroGaugeSvg{width:100%;height:100%;display:block;transform:rotate(-90deg)}.VWh0dG_heroGaugeTrack{fill:none;stroke:var(--dsw-alias-bg-module-platform);stroke-width:9px}.VWh0dG_heroGaugeArc{fill:none;stroke:var(--dsw-static-blue-500);stroke-width:9px;stroke-linecap:round;transition:stroke-dasharray .26s}.VWh0dG_heroGaugeArcOver{stroke:var(--dsw-static-red-500)}.VWh0dG_heroGaugeCenter{flex-direction:column;justify-content:center;align-items:center;gap:1px;display:flex;position:absolute;inset:0}.VWh0dG_heroGaugePct{letter-spacing:-.02em;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary);font-size:18px;font-weight:700;line-height:22px}.VWh0dG_heroGaugePctOver{color:var(--dsw-static-red-500)}.VWh0dG_heroGaugeLabel{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:14px}.VWh0dG_heroSide{border-top:1px solid var(--dsw-alias-border-l1);align-items:stretch;padding-top:14px;display:flex}.VWh0dG_heroSideItem{flex-direction:column;flex:1;gap:3px;min-width:0;padding-left:16px;display:flex}.VWh0dG_heroSideItem:first-child{padding-left:0}.VWh0dG_heroSideLabel{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:11px;line-height:15px}.VWh0dG_heroSideValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;letter-spacing:-.01em;white-space:nowrap;align-items:baseline;gap:6px;font-size:18px;font-weight:600;line-height:24px;display:inline-flex}.VWh0dG_heroSideSpacer{flex:1;display:block}.VWh0dG_delta{align-items:center;gap:2px;margin-left:4px;font-size:11px;font-weight:600;line-height:17px;display:inline-flex}.VWh0dG_deltaUp{color:var(--dsw-static-green-500)}.VWh0dG_deltaDown{color:var(--dsw-static-red-500)}.VWh0dG_kpiGrid{grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;display:grid}.VWh0dG_kpiTile{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:14px;flex-direction:column;gap:3px;padding:14px 15px;transition:border-color .16s;display:flex;position:relative;overflow:hidden}.VWh0dG_kpiTile:hover{border-color:var(--dsw-alias-border-l2)}.VWh0dG_kpiLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:15px}.VWh0dG_kpiValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;letter-spacing:-.01em;font-size:22px;font-weight:600;line-height:28px}.VWh0dG_kpiGreen{color:var(--dsw-static-green-500)}.VWh0dG_kpiDetail{color:var(--dsw-alias-label-caption);white-space:nowrap;text-overflow:ellipsis;font-size:11px;line-height:15px;overflow:hidden}.VWh0dG_panel{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:16px;flex-direction:column;gap:10px;padding:16px 18px;transition:border-color .16s;display:flex}.VWh0dG_panelHead{justify-content:space-between;align-items:baseline;gap:10px;display:flex}.VWh0dG_panelTitle{letter-spacing:-.005em;color:var(--dsw-alias-label-primary);margin:0;font-size:14px;font-weight:600;line-height:20px}.VWh0dG_panelHint{color:var(--dsw-alias-label-caption);white-space:nowrap;font-size:11px;line-height:16px}.VWh0dG_pricingTip{color:var(--dsw-alias-label-caption);margin:0 0 2px;font-size:11px;line-height:16px}.VWh0dG_rangeToggle{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:8px;gap:2px;padding:2px;display:inline-flex}.VWh0dG_rangeButton{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:2px 8px;font-size:11px;line-height:16px;transition:background-color .14s,color .14s}.VWh0dG_rangeButtonActive{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);font-weight:600}.VWh0dG_exportBar{justify-content:flex-end;align-items:center;gap:8px;display:flex}.VWh0dG_exportLabel{color:var(--dsw-alias-label-caption);font-size:11px;line-height:16px}.VWh0dG_exportButton{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);cursor:pointer;border-radius:999px;padding:4px 12px;font-size:11.5px;line-height:16px;transition:border-color .16s,color .16s,background-color .16s}.VWh0dG_exportButton:hover,.VWh0dG_exportButton:focus-visible{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);outline:none}.VWh0dG_shareTrack{background:var(--dsw-alias-bg-module-platform);border-radius:999px;height:10px;display:flex;overflow:hidden}.VWh0dG_shareSeg{height:100%;transition:width .2s}.VWh0dG_shareSegPeak{background:var(--dsw-static-blue-500)}.VWh0dG_shareSegOff{background:color-mix(in srgb, var(--dsw-static-blue-500) 25%, var(--dsw-alias-bg-module-platform))}.VWh0dG_shareSegUser{background:var(--dsw-static-blue-500)}.VWh0dG_shareSegAssistant{background:var(--dsw-static-green-500)}.VWh0dG_shareSegTool{background:var(--dsw-static-amber-500)}.VWh0dG_shareLegend{align-items:center;gap:16px;display:flex}.VWh0dG_shareItem{color:var(--dsw-alias-label-secondary);align-items:baseline;gap:6px;font-size:12px;line-height:17px;display:inline-flex}.VWh0dG_bucketCost{align-items:baseline;gap:3px;display:inline-flex}.VWh0dG_bucketOfficial{color:var(--dsw-static-blue-500);font-weight:600}.VWh0dG_bucketSep{color:var(--dsw-alias-label-dimmed)}.VWh0dG_bucketThird{color:var(--dsw-alias-label-secondary)}.VWh0dG_bucketSummary{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;display:grid}.VWh0dG_bucketStat{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:12px;flex-direction:column;gap:4px;padding:12px 14px;display:flex}.VWh0dG_bucketStatLabel{color:var(--dsw-alias-label-tertiary);text-transform:uppercase;letter-spacing:.05em;font-size:11px;line-height:15px}.VWh0dG_bucketStatValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;letter-spacing:-.01em;font-size:20px;font-weight:700;line-height:26px}.VWh0dG_bucketStatSub{color:var(--dsw-alias-label-caption);font-variant-numeric:tabular-nums;font-size:11px;line-height:16px}.VWh0dG_shareDot{border-radius:50%;flex:none;align-self:center;width:8px;height:8px}.VWh0dG_shareValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;font-weight:600}.VWh0dG_budget{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:14px;flex-direction:column;gap:8px;padding:12px 16px;display:flex}.VWh0dG_budgetHead{justify-content:space-between;align-items:baseline;gap:10px;display:flex}.VWh0dG_budgetLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:17px}.VWh0dG_budgetValue{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:12px;line-height:17px}.VWh0dG_budgetControls{align-items:center;gap:8px;min-width:0;display:inline-flex}.VWh0dG_budgetInputWrap{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:6px;align-items:center;gap:2px;padding:2px 6px;display:inline-flex}.VWh0dG_budgetInputWrap:focus-within{border-color:var(--dsw-alias-border-l3)}.VWh0dG_budgetUnit{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.VWh0dG_budgetInput{width:64px;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;text-align:right;background:0 0;border:none;padding:0;font-size:12px;line-height:16px}.VWh0dG_budgetInput:focus-visible{outline:none}.VWh0dG_switch{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);cursor:pointer;border-radius:999px;flex:none;width:30px;height:17px;padding:0;transition:background-color .16s,border-color .16s;position:relative}.VWh0dG_switchOn{border-color:var(--dsw-alias-border-l1);background:var(--dsw-alias-label-primary)}.VWh0dG_switchKnob{background:var(--dsw-static-neutral-bluish-00);border-radius:50%;width:11px;height:11px;transition:transform .16s;position:absolute;top:2px;left:2px}.VWh0dG_switchOn .VWh0dG_switchKnob{transform:translate(13px)}.VWh0dG_budgetTrack{background:var(--dsw-alias-bg-module-platform);border-radius:999px;height:6px;overflow:hidden}.VWh0dG_budgetFill{background:var(--dsw-static-blue-500);border-radius:999px;height:100%;transition:width .2s}.VWh0dG_budgetFillWarn{background:var(--dsw-static-amber-500)}.VWh0dG_budgetFillOver{background:var(--dsw-static-red-500);animation:1.6s ease-in-out infinite VWh0dG_budgetOverPulse}@keyframes VWh0dG_budgetOverPulse{50%{opacity:.55}}.VWh0dG_chartWrap{width:100%;position:relative}.VWh0dG_chartSvg{width:100%;height:auto;display:block}.VWh0dG_chartEmpty{height:140px;color:var(--dsw-alias-label-caption);justify-content:center;align-items:center;font-size:13px;display:flex}.VWh0dG_emptyRow{text-align:center;color:var(--dsw-alias-label-caption);padding:28px 0;font-size:13px}.VWh0dG_chartGrid{stroke:var(--dsw-alias-border-l1);stroke-width:1px}.VWh0dG_chartAxisLabel{fill:var(--dsw-alias-label-tertiary);font-size:10px}.VWh0dG_chartBar{fill:var(--dsw-static-blue-500);opacity:.7}.VWh0dG_chartBar:hover{opacity:1}.VWh0dG_chartStack{stroke:var(--dsw-alias-bg-layer-1);stroke-width:.75px}.VWh0dG_chartStack:hover{opacity:.9}.VWh0dG_chartLine{stroke:var(--dsw-static-blue-500);stroke-width:2px;stroke-linecap:round;stroke-linejoin:round}.VWh0dG_chartCrosshair{stroke:var(--dsw-alias-label-dimmed);stroke-width:1px;stroke-dasharray:3 3}.VWh0dG_chartDot{fill:var(--dsw-static-neutral-bluish-00);stroke:var(--dsw-static-blue-500);stroke-width:2px}.VWh0dG_chartTooltip{pointer-events:none;z-index:2;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);box-shadow:none;white-space:nowrap;border-radius:8px;padding:8px 10px;position:absolute;transform:translate(-50%,calc(-100% - 10px))}.VWh0dG_chartTooltipDate{color:var(--dsw-alias-label-primary);margin-bottom:3px;font-size:11px;font-weight:600}.VWh0dG_chartTooltipRow{color:var(--dsw-alias-label-secondary);align-items:center;gap:5px;font-size:11px;line-height:17px;display:flex}.VWh0dG_chartTooltipRow strong{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;font-weight:600}.VWh0dG_chartLegendLine{background:var(--dsw-static-blue-500);border-radius:2px;width:10px;height:3px;display:inline-block}.VWh0dG_chartLegendBar{background:var(--dsw-static-blue-500);opacity:.5;border-radius:2px;width:7px;height:7px;display:inline-block}.VWh0dG_chartTooltipSwatch{border-radius:3px;flex:none;width:8px;height:8px;display:inline-block}.VWh0dG_chartLegend{color:var(--dsw-alias-label-tertiary);justify-content:flex-end;gap:14px;margin-top:2px;font-size:11px;display:flex}.VWh0dG_chartLegend span{align-items:center;gap:5px;display:inline-flex}.VWh0dG_tableScroll{border:1px solid var(--dsw-alias-border-l1);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:12px;overflow:auto}.VWh0dG_modelTable,.VWh0dG_pricingTable{border-collapse:collapse;width:100%;font-size:12.5px}.VWh0dG_modelTable th,.VWh0dG_modelTable td,.VWh0dG_pricingTable th,.VWh0dG_pricingTable td{border-bottom:1px solid var(--dsw-alias-border-l1);text-align:left;white-space:nowrap;padding:9px 12px}.VWh0dG_modelTable tbody tr:last-child td,.VWh0dG_pricingTable tbody tr:last-child td{border-bottom:0}.VWh0dG_modelTable thead th,.VWh0dG_pricingTable thead th{color:var(--dsw-alias-label-tertiary);text-transform:uppercase;letter-spacing:.05em;background:0 0;font-size:11px;font-weight:600}.VWh0dG_modelTable tbody tr,.VWh0dG_pricingTable tbody tr{transition:background-color .12s}.VWh0dG_modelTable tbody tr:hover,.VWh0dG_pricingTable tbody tr:hover{background:0 0}.VWh0dG_numCol{text-align:right;font-variant-numeric:tabular-nums}.VWh0dG_costCol{color:var(--dsw-alias-label-primary);font-weight:600}.VWh0dG_na{color:var(--dsw-alias-label-dimmed)}.VWh0dG_modelCell{align-items:center;gap:8px;display:inline-flex}.VWh0dG_modelDot{border-radius:50%;flex:none;width:9px;height:9px}.VWh0dG_modelName{color:var(--dsw-alias-label-primary);font-weight:500;line-height:16px;display:block}.VWh0dG_modelProvider{color:var(--dsw-alias-label-caption);font-size:10.5px;line-height:14px;display:block}.VWh0dG_pricingToggle{cursor:pointer;text-align:left;background:0 0;border:none;justify-content:space-between;align-items:center;gap:10px;width:100%;padding:0;display:flex}.VWh0dG_pricingToggle:hover .VWh0dG_panelTitle,.VWh0dG_pricingToggle:focus-visible .VWh0dG_panelTitle{color:var(--dsw-alias-label-primary)}.VWh0dG_rateBadge{vertical-align:1px;white-space:nowrap;border-radius:999px;align-items:center;margin-left:6px;padding:1px 6px;font-size:10px;font-weight:500;line-height:14px;display:inline-flex}.VWh0dG_rateBadgeLive{color:var(--dsw-static-green-500);background:var(--dsw-alias-bg-layer-2)}.VWh0dG_rateBadgeBuiltin{color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2)}.VWh0dG_pricingToggleText{align-items:baseline;gap:10px;min-width:0;display:flex}.VWh0dG_pricingChevron{width:16px;height:16px;color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.VWh0dG_pricingChevronOpen{transform:rotate(180deg)}.VWh0dG_bandPrice{align-items:baseline;gap:6px;display:inline-flex}.VWh0dG_bandPriceOff{color:var(--dsw-alias-label-caption)}.VWh0dG_bandPriceOff:before{content:\"/\";color:var(--dsw-alias-label-dimmed);margin-right:4px}.VWh0dG_bandTag{color:var(--dsw-alias-label-secondary);flex-direction:column;gap:1px;font-size:10.5px;line-height:14px;display:inline-flex}.VWh0dG_bandTagOff{color:var(--dsw-static-green-500);font-weight:600}.VWh0dG_bandTag>span:first-child{color:var(--dsw-alias-label-primary);font-weight:500}.VWh0dG_flatTag{color:var(--dsw-alias-label-caption);font-size:10.5px;line-height:14px}.VWh0dG_healthDot{border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.VWh0dG_healthOk{background:var(--dsw-static-green-500)}.VWh0dG_healthBad{background:var(--dsw-static-red-500)}.VWh0dG_healthIdle{background:var(--dsw-static-neutral-bluish-400)}.VWh0dG_dashboardRight{align-items:center;gap:8px;min-width:0;display:flex}.VWh0dG_healthBadge{white-space:nowrap;border-radius:999px;align-items:center;gap:6px;padding:3px 9px;font-size:11px;line-height:16px;display:inline-flex}.VWh0dG_healthBadgeOk{color:var(--dsw-static-green-500);background:var(--dsw-alias-bg-layer-2)}.VWh0dG_healthBadgeBad{color:var(--dsw-static-red-500);background:var(--dsw-alias-bg-layer-2)}.VWh0dG_planTag{color:var(--dsw-static-green-500);background:var(--dsw-alias-bg-layer-2);border-radius:999px;align-items:center;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px;display:inline-flex}.VWh0dG_uncataloguedTag{vertical-align:1px;color:var(--dsw-static-amber-500);background:var(--dsw-alias-bg-layer-2);border-radius:999px;margin-left:6px;padding:0 6px;font-size:10px;font-weight:600;line-height:16px;display:inline-block}.VWh0dG_estimatedTag{vertical-align:1px;color:var(--dsw-static-blue-500);background:var(--dsw-alias-bg-layer-2);border-radius:999px;margin-left:6px;padding:0 6px;font-size:10px;font-weight:600;line-height:16px;display:inline-block}.VWh0dG_liveCostBar{color:var(--dsw-static-neutral-400);font-variant-numeric:tabular-nums;align-items:center;gap:6px;font-size:11px;line-height:16px;display:inline-flex}.VWh0dG_liveCostItem{white-space:nowrap}.VWh0dG_liveCostSep{color:var(--dsw-static-neutral-300)}.VWh0dG_liveTierPeak{color:var(--dsw-static-blue-500);font-weight:600}.VWh0dG_liveTierOff{color:var(--dsw-static-green-500);font-weight:600}.VWh0dG_liveQuotaWarn{color:var(--dsw-static-amber-500);font-weight:600}.VWh0dG_liveQuotaCrit{color:var(--dsw-static-red-500);font-weight:600}.VWh0dG_balanceCell{flex-direction:column;align-items:flex-end;gap:2px;display:inline-flex}.VWh0dG_balanceDays{color:var(--dsw-alias-label-caption);white-space:nowrap;font-size:10.5px;line-height:14px}.VWh0dG_balanceDaysLow{color:var(--dsw-static-red-500);font-weight:600}body[data-zine-mode] .VWh0dG_trigger,body[data-zine-mode] .VWh0dG_triggerPop,body[data-zine-mode] .VWh0dG_railButton{display:none}body[data-zine-mode] .VWh0dG_dashboardHead{background:#000;border-bottom:2px solid #e8ff00}body[data-zine-mode] .VWh0dG_headTitleRow{align-items:center;gap:8px;margin-top:4px;display:flex}body[data-zine-mode] .VWh0dG_dashboardTitle{color:#e8ff00;letter-spacing:.04em;text-transform:uppercase;text-shadow:0 0 8px #e8ff0066;font-weight:900}body[data-zine-mode] .VWh0dG_dashboardSubtitle{color:#c9d98a;letter-spacing:.08em;text-transform:uppercase;font-size:10px}body[data-zine-mode] .VWh0dG_closeButton{color:#0a0a05;background:#ff2d95;border:1.5px solid #ff2d95;border-radius:0;box-shadow:0 0 10px #ff2d9573}body[data-zine-mode] .VWh0dG_hero{background:#000;border:2.5px solid #e8ff00;border-radius:0;position:relative;box-shadow:0 0 0 1px #0009,0 0 24px #e8ff002e}body[data-zine-mode] .VWh0dG_heroLabel{color:#c9d98a;letter-spacing:.12em;text-transform:uppercase;font-size:10px;font-weight:900}body[data-zine-mode] .VWh0dG_heroValue{color:#e8ff00;letter-spacing:-.02em;text-shadow:0 0 12px #e8ff0073;-webkit-text-fill-color:#e8ff00;background:0 0;font-size:38px;font-weight:900}body[data-zine-mode] .VWh0dG_heroMeta{color:#c9d98a;letter-spacing:.06em;text-transform:uppercase;font-size:10.5px}body[data-zine-mode] .VWh0dG_heroSideLabel{color:#c9d98a;letter-spacing:.1em;text-transform:uppercase;font-size:10px;font-weight:900}body[data-zine-mode] .VWh0dG_heroSideValue{color:#e8ff00;text-shadow:0 0 6px #e8ff0059}body[data-zine-mode] .VWh0dG_delta{font-weight:900}body[data-zine-mode] .VWh0dG_deltaUp{color:#ff2d95}body[data-zine-mode] .VWh0dG_deltaDown{color:#c9d98a}body[data-zine-mode] .VWh0dG_tabNav{background:#000;border-bottom:2px solid #e8ff00}body[data-zine-mode] .VWh0dG_tabButton{color:#c9d98a;letter-spacing:.08em;text-transform:uppercase;border-radius:0;font-size:10.5px;font-weight:900}body[data-zine-mode] .VWh0dG_tabButton:hover,body[data-zine-mode] .VWh0dG_tabButton:focus-visible{color:#e8ff00;background:#e8ff001f}body[data-zine-mode] .VWh0dG_tabButtonActive,body[data-zine-mode] .VWh0dG_tabButtonActive:hover,body[data-zine-mode] .VWh0dG_tabButtonActive:focus-visible{color:#0a0a05;background:#e8ff00;box-shadow:0 0 10px #e8ff0073}body[data-zine-mode] .VWh0dG_panel{background:#000;border:2px solid #e8ff00;border-radius:0}body[data-zine-mode] .VWh0dG_trendPanel{position:relative}body[data-zine-mode] .VWh0dG_panelTitle{color:#e8ff00;letter-spacing:.06em;text-transform:uppercase;text-shadow:0 0 6px #e8ff0066;font-weight:900}body[data-zine-mode] .VWh0dG_panelHint{color:#c9d98a;letter-spacing:.08em;text-transform:uppercase;font-size:10px;font-weight:900}body[data-zine-mode] .VWh0dG_modelTableScroll{background:#000;border:1.5px solid #e8ff0080;border-radius:0}.VWh0dG_currencyToggle{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:6px;align-items:center;gap:2px;margin-right:8px;padding:2px;display:inline-flex}.VWh0dG_currencyButton{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:4px;padding:4px 7px;font-size:11px;font-weight:700;line-height:1}.VWh0dG_currencyButtonActive{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}.VWh0dG_subscriptionGrid{grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:10px;margin-top:10px;display:grid}.VWh0dG_subscriptionCard{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:10px;padding:12px 14px}.VWh0dG_subscriptionHead{flex-wrap:wrap;align-items:baseline;gap:6px;margin-bottom:8px;display:flex}.VWh0dG_subscriptionName{font-size:13px;font-weight:700}.VWh0dG_subscriptionPlan{color:var(--dsw-alias-label-secondary);font-size:11px}.VWh0dG_subscriptionPlan[data-kind=code],.VWh0dG_subscriptionPlan[data-kind=token]{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-3);border-radius:999px;padding:1px 8px;font-weight:500}.VWh0dG_subscriptionTier{color:var(--dsw-alias-label-secondary);margin-left:6px}.VWh0dG_subscriptionAuto{color:var(--dsw-static-blue-500);background:color-mix(in srgb, var(--dsw-static-blue-500) 14%, var(--dsw-alias-bg-layer-2));border-radius:999px;margin-left:6px;padding:1px 6px;font-size:10px}.VWh0dG_subscriptionStatus{color:var(--dsw-alias-label-secondary);margin-bottom:6px;font-size:11px}.VWh0dG_subscriptionWindow{align-items:center;gap:8px;margin-top:6px;font-size:11px;display:flex}.VWh0dG_subscriptionWindowLabel{color:var(--dsw-alias-label-secondary);flex:0 0 44px}.VWh0dG_subscriptionTrack{background:var(--dsw-alias-bg-layer-3);border-radius:3px;flex:1;height:5px;overflow:hidden}.VWh0dG_subscriptionFill{background:var(--dsw-static-blue-500);border-radius:3px;height:100%;transition:width .2s;display:block}.VWh0dG_subscriptionFillWarn{background:var(--dsw-static-amber-500)}.VWh0dG_subscriptionFillOver{background:var(--dsw-static-red-500)}.VWh0dG_subscriptionPct{text-align:right;font-variant-numeric:tabular-nums;flex:none;min-width:52px}.VWh0dG_subscriptionExhausted{color:var(--dsw-static-red-500);min-width:52px;font-weight:600}.VWh0dG_subscriptionReset{color:var(--dsw-alias-label-secondary);flex:none}.VWh0dG_providerGroupList{flex-direction:column;gap:10px;display:flex}.VWh0dG_providerGroup{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:12px;padding:12px 14px}.VWh0dG_providerGroupHead{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.VWh0dG_providerGroupTitle{align-items:center;gap:7px;min-width:0;display:inline-flex}.VWh0dG_providerGroupName{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:18px}.VWh0dG_providerGroupMeta{flex:none;align-items:center;gap:10px;display:inline-flex}.VWh0dG_providerGroupBadge{color:var(--dsw-static-green-500);background:var(--dsw-alias-bg-layer-2);border-radius:999px;align-items:center;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px;display:inline-flex}.VWh0dG_providerGroupBalance{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;white-space:nowrap;align-items:baseline;gap:6px;font-size:12px;line-height:17px;display:inline-flex}.VWh0dG_providerGroupBalanceLabel{color:var(--dsw-alias-label-caption);font-size:11px;line-height:17px}.VWh0dG_roundsFlagBadge{color:var(--dsw-static-neutral-bluish-00);background:var(--dsw-static-red-500);border-radius:999px;margin-left:8px;padding:1px 7px;font-size:10px;font-weight:800}.VWh0dG_rounds{margin-top:10px}.VWh0dG_roundsBars{align-items:flex-end;gap:3px;height:124px;padding:16px 2px 0;display:flex;overflow-x:auto}.VWh0dG_roundsBarCol{border-radius:5px 5px 0 0;flex-direction:column;flex:1 0 28px;justify-content:flex-end;align-items:stretch;height:100%;display:flex;position:relative}.VWh0dG_roundsBarColPeak{background:color-mix(in srgb, var(--dsw-static-amber-500) 16%, transparent)}.VWh0dG_roundsBarColOff{background:var(--dsw-alias-bg-module-platform)}.VWh0dG_roundsBarLabel{text-align:center;color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;max-width:100%;font-size:9px;line-height:1.2;position:absolute;bottom:0;left:0;right:0;overflow:hidden;transform:translateY(-100%)}.VWh0dG_roundsBarWrap{flex:1;align-items:flex-end;min-height:0;display:flex}.VWh0dG_roundsBar{background:var(--dsw-static-blue-500);border-radius:2px 2px 0 0;width:100%;min-height:2px;position:relative}.VWh0dG_roundsBarFlagged{background:var(--dsw-static-red-500);border-radius:2px 2px 0 0;width:100%;min-height:2px;position:relative}.VWh0dG_roundsFlagMark{background:var(--dsw-static-red-500);border-radius:50%;width:7px;height:7px;position:absolute;top:-3px;right:-3px}.VWh0dG_roundsAxis{color:var(--dsw-alias-label-secondary);justify-content:space-between;margin-top:6px;font-size:10px;display:flex}.VWh0dG_roundsEmpty{color:var(--dsw-alias-label-secondary);margin-top:10px;font-size:12px}.VWh0dG_heatmap{margin-top:10px}.VWh0dG_heatmapGrid{grid-template-columns:repeat(7,minmax(0,1fr));gap:8px;display:grid}.VWh0dG_heatmapCellEmpty{background:var(--dsw-alias-bg-layer-1);height:30px;color:var(--dsw-alias-label-dimmed);font-variant-numeric:tabular-nums;border-radius:8px;justify-content:center;align-items:center;font-size:11px;display:flex}.VWh0dG_heatmapCell{font-variant-numeric:tabular-nums;cursor:pointer;border:0;border-radius:8px;justify-content:center;align-items:center;height:30px;padding:0;font-size:11px;display:flex}.VWh0dG_heatmapCell[data-level=\"0\"],.VWh0dG_heatmapCell[data-level=\"1\"],.VWh0dG_heatmapCell[data-level=\"2\"]{color:var(--dsw-alias-label-primary)}.VWh0dG_heatmapCell[data-level=\"3\"],.VWh0dG_heatmapCell[data-level=\"4\"]{color:var(--dsw-static-neutral-bluish-00)}.VWh0dG_heatmapFooter{color:var(--dsw-alias-label-secondary);align-items:center;gap:8px;margin-top:10px;font-size:10px;display:flex}.VWh0dG_heatmapLegend{gap:3px;display:inline-flex}.VWh0dG_heatmapLegend i{border-radius:4px;width:14px;height:14px;display:block}.VWh0dG_heatmapHover{font-variant-numeric:tabular-nums;margin-left:auto}.VWh0dG_heatmapYearScroll{padding-bottom:2px;overflow-x:auto}.VWh0dG_heatmapYearGrid{grid-template-rows:repeat(7,11px);grid-auto-flow:column;gap:3px;min-width:max-content;display:grid}.VWh0dG_heatmapYearCell{cursor:pointer;border:0;border-radius:2px;width:11px;height:11px;padding:0}.VWh0dG_pluginInfo{flex-direction:column;gap:8px;margin-top:10px;display:flex}.VWh0dG_pluginInfoRow{align-items:baseline;gap:12px;font-size:12px;display:flex}.VWh0dG_pluginInfoLabel{color:var(--dsw-alias-label-secondary);flex:0 0 72px}.VWh0dG_pluginInfoValue{color:var(--dsw-alias-label-primary);word-break:break-all}.VWh0dG_pluginInfoLink{color:var(--dsw-static-blue-500);word-break:break-all;text-decoration:none}.VWh0dG_pluginInfoLink:hover{text-decoration:underline}@media (width<=640px){.VWh0dG_kpiGrid{grid-template-columns:repeat(2,minmax(0,1fr))}.VWh0dG_hero{gap:14px}.VWh0dG_heroTop{flex-direction:column;align-items:flex-start;gap:12px}.VWh0dG_heroGauge{width:72px;height:72px}.VWh0dG_heroSide{gap:12px}.VWh0dG_heroSideSpacer{display:none}}.VWh0dG_peakAlert{z-index:2000;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:12px;align-items:center;gap:12px;min-width:300px;max-width:460px;padding:10px 12px;animation:.2s VWh0dG_peakAlertIn;display:flex;position:fixed;box-shadow:0 4px 16px #00000014}.VWh0dG_peakAlertCorner{bottom:18px;right:18px}.VWh0dG_peakAlertCenter{top:20%;left:50%;transform:translate(-50%)}.VWh0dG_peakAlertTag{letter-spacing:.01em;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-3);white-space:nowrap;border-radius:999px;flex:none;align-items:center;gap:6px;padding:3px 9px;font-size:11px;font-weight:650;display:inline-flex}.VWh0dG_peakAlertTag:before{content:\"\";background:currentColor;border-radius:50%;width:6px;height:6px}.VWh0dG_peakAlertPeak .VWh0dG_peakAlertTag{color:var(--dsw-static-amber-500)}.VWh0dG_peakAlertOff .VWh0dG_peakAlertTag{color:var(--dsw-static-blue-500)}.VWh0dG_peakAlertCountdown{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary);flex:none;font-size:18px;font-weight:700;line-height:1}.VWh0dG_peakAlertText{min-width:0;color:var(--dsw-alias-label-secondary);flex:1;font-size:12px;line-height:18px}.VWh0dG_peakAlertClose{width:20px;height:20px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;justify-content:center;align-items:center;font-size:15px;line-height:1;transition:background-color .14s,color .14s;display:inline-flex}.VWh0dG_peakAlertClose:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}@keyframes VWh0dG_peakAlertIn{0%{opacity:0}to{opacity:1}}.VWh0dG_peakAlertPanel{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:16px;flex-direction:column;gap:10px;padding:14px 16px;display:flex}.VWh0dG_peakAlertPanelHead{justify-content:space-between;align-items:center;gap:10px;display:flex}.VWh0dG_peakAlertPanelLabel{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600}.VWh0dG_peakAlertPanelBody{flex-wrap:wrap;align-items:center;gap:12px 16px;display:flex}.VWh0dG_peakAlertField{color:var(--dsw-alias-label-secondary);align-items:center;gap:8px;font-size:12px;display:inline-flex}.VWh0dG_peakAlertNum{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);width:56px;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;border-radius:6px;padding:4px 6px}.VWh0dG_peakAlertSelect{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);border-radius:6px;padding:4px 6px;font-size:12px}.VWh0dG_peakAlertCheck{color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;font-size:12px;display:inline-flex}.VWh0dG_peakAlertPreview{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;padding:5px 10px;font-size:12px}.VWh0dG_peakAlertPreview:hover{background:var(--dsw-alias-bg-layer-3)}.VWh0dG_settingsHead{flex-direction:column;gap:4px;margin-bottom:2px;display:flex}.VWh0dG_settingsTitle{letter-spacing:-.005em;color:var(--dsw-alias-label-primary);margin:0;font-size:15px;font-weight:650;line-height:22px}.VWh0dG_settingsHint{color:var(--dsw-alias-label-caption);margin:0;font-size:11px;line-height:16px}.VWh0dG_budgetHint,.VWh0dG_peakAlertHint{color:var(--dsw-alias-label-caption);margin:6px 0 0;font-size:11px;line-height:16px}";
27
+ const css = ".VWh0dG_railButton{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);width:36px;height:36px;color:var(--dsw-alias-label-secondary);cursor:pointer;border-radius:8px;flex:none;justify-content:center;align-items:center;padding:0;transition:border-color .16s,color .16s;display:flex}.VWh0dG_railButton:hover,.VWh0dG_railButton:focus-visible{border-color:var(--dsw-static-blue-500);color:var(--dsw-static-blue-500);outline:none}.VWh0dG_railButton svg{stroke-width:2px;width:18px;height:18px}.VWh0dG_trigger{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);width:100%;min-width:0;color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;border-radius:12px;align-items:center;gap:10px;padding:9px 12px;transition:border-color .16s,background-color .16s;display:flex;position:relative;overflow:hidden}.VWh0dG_trigger:hover,.VWh0dG_trigger:focus-visible{border-color:var(--dsw-static-blue-500);outline:none}.VWh0dG_triggerIcon{background:linear-gradient(135deg, var(--dsw-static-blue-500), var(--dsw-static-blue-400));width:30px;height:30px;color:var(--dsw-static-neutral-bluish-00);box-shadow:0 2px 8px -2px color-mix(in srgb, var(--dsw-static-blue-500) 55%, transparent);border-radius:10px;flex:none;justify-content:center;align-items:center;display:inline-flex}.VWh0dG_triggerIcon svg{stroke-width:2px;width:16px;height:16px}.VWh0dG_triggerBody{flex-direction:column;flex:1;gap:1px;min-width:0;display:flex}.VWh0dG_triggerRow{align-items:baseline;gap:5px;min-width:0;display:inline-flex}.VWh0dG_triggerAmount{color:var(--dsw-alias-label-primary);letter-spacing:-.02em;font-variant-numeric:tabular-nums;white-space:nowrap;font-size:16px;font-weight:700;line-height:20px}.VWh0dG_triggerSub{color:var(--dsw-alias-label-tertiary);white-space:nowrap;text-overflow:ellipsis;font-size:10px;line-height:14px;overflow:hidden}.VWh0dG_triggerMeta{color:var(--dsw-alias-label-tertiary);white-space:nowrap;letter-spacing:.02em;text-transform:uppercase;font-size:9.5px;font-weight:600;line-height:12px}.VWh0dG_triggerSpark{flex:none;align-items:flex-end;gap:2px;height:20px;display:flex}.VWh0dG_triggerSparkBar,.VWh0dG_triggerSparkHot{background:var(--dsw-static-blue-500);opacity:.6;border-radius:1px 1px 0 0;width:3px}.VWh0dG_triggerSparkHot{opacity:1}.VWh0dG_triggerWrap{flex:auto;width:100%;min-width:0;display:block;position:relative}.VWh0dG_triggerPop{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);box-shadow:var(--dsw-shadow-lv2);opacity:0;pointer-events:none;z-index:10;border-radius:10px;flex-direction:column;gap:6px;padding:12px 14px;transition:opacity .16s,transform .16s;display:flex;position:absolute;bottom:calc(100% + 8px);left:0;right:0;transform:translateY(4px)}.VWh0dG_triggerWrap:hover .VWh0dG_triggerPop,.VWh0dG_triggerWrap:focus-within .VWh0dG_triggerPop{opacity:1;transform:translateY(0)}.VWh0dG_triggerPopRow{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.VWh0dG_triggerPopLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.VWh0dG_triggerPopValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;font-size:13px;font-weight:600;line-height:18px}.VWh0dG_triggerPopBars{border-top:1px solid var(--dsw-alias-border-l1);align-items:flex-end;gap:4px;height:22px;margin-top:4px;padding-top:8px;display:flex}.VWh0dG_triggerPopBar{background:var(--dsw-static-blue-500);border-radius:2px;flex:1;transition:height .2s}.VWh0dG_dashboardModal{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);width:min(760px,100vw - 48px);max-height:min(760px,88vh);box-shadow:var(--dsw-shadow-lv3);animation:.18s ease-out VWh0dG_dashboardIn}@keyframes VWh0dG_dashboardIn{0%{opacity:0;transform:translateY(8px)scale(.98)}to{opacity:1;transform:none}}div[role=presentation]:has(>.dsh-billing-modal)>div[aria-hidden=true]:first-child{backdrop-filter:blur(8px)saturate(1.25)}.VWh0dG_dashboard{flex-direction:column;width:100%;max-height:min(760px,88vh);display:flex}.VWh0dG_dashboardHead{border-bottom:1px solid var(--dsw-alias-border-l1);justify-content:space-between;align-items:flex-start;gap:12px;padding:20px 24px 14px;display:flex}.VWh0dG_dashboardTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:17px;font-weight:600;line-height:24px}.VWh0dG_dashboardSubtitle{color:var(--dsw-alias-label-caption);margin:3px 0 0;font-size:12px;line-height:17px}.VWh0dG_closeButton{width:30px;height:30px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px;flex:none;justify-content:center;align-items:center;transition:background-color .14s;display:inline-flex}.VWh0dG_closeButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.VWh0dG_closeButton svg{stroke-width:2px;width:16px;height:16px}.VWh0dG_dashboardBody{flex-direction:column;gap:14px;padding:16px 24px 24px;display:flex;overflow-y:auto}.VWh0dG_tabNav{border-bottom:1px solid var(--dsw-alias-border-l1);align-items:center;gap:4px;padding:10px 24px;display:flex}.VWh0dG_tabButton{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:999px;padding:5px 14px;font-size:12.5px;font-weight:500;line-height:18px;transition:background-color .16s,color .16s,box-shadow .16s}.VWh0dG_tabButton:hover,.VWh0dG_tabButton:focus-visible{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover);outline:none}.VWh0dG_tabButtonActive,.VWh0dG_tabButtonActive:hover,.VWh0dG_tabButtonActive:focus-visible{background:var(--dsw-static-blue-500);color:var(--dsw-static-neutral-bluish-00);font-weight:600}.VWh0dG_tabPanel{flex-direction:column;gap:14px;animation:.14s ease-out VWh0dG_tabPanelIn;display:flex}@keyframes VWh0dG_tabPanelIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}.VWh0dG_hero{border:1px solid var(--dsw-alias-border-l1);background:linear-gradient(180deg, var(--dsw-alias-bg-layer-2), var(--dsw-alias-bg-layer-1));box-shadow:inset 0 1px 0 color-mix(in srgb, var(--dsw-static-neutral-bluish-00) 30%, transparent);border-radius:16px;flex-direction:column;gap:18px;padding:22px 24px;display:flex;position:relative;overflow:hidden}.VWh0dG_heroTop{justify-content:space-between;align-items:center;gap:24px;display:flex}.VWh0dG_heroMain{flex-direction:column;gap:2px;min-width:0;display:flex}.VWh0dG_heroLabel{color:var(--dsw-alias-label-tertiary);text-transform:uppercase;letter-spacing:.08em;white-space:nowrap;font-size:11px;line-height:16px}.VWh0dG_heroReadout{align-items:baseline;gap:4px;display:flex}.VWh0dG_heroCurrency{letter-spacing:-.01em;color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;font-size:20px;font-weight:600;line-height:30px}.VWh0dG_heroValue{letter-spacing:-.03em;font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--dsw-alias-label-primary);font-size:56px;font-weight:700;line-height:64px}.VWh0dG_heroMeta{color:var(--dsw-alias-label-caption);white-space:nowrap;margin-top:4px;font-size:12px;line-height:17px}.VWh0dG_heroGauge{flex:none;width:96px;height:96px;position:relative}.VWh0dG_heroGaugeSvg{width:100%;height:100%;display:block;transform:rotate(-90deg)}.VWh0dG_heroGaugeTrack{fill:none;stroke:var(--dsw-alias-bg-module-platform);stroke-width:9px}.VWh0dG_heroGaugeArc{fill:none;stroke:var(--dsw-static-blue-500);stroke-width:9px;stroke-linecap:round;transition:stroke-dasharray .26s}.VWh0dG_heroGaugeArcOver{stroke:var(--dsw-static-red-500)}.VWh0dG_heroGaugeCenter{flex-direction:column;justify-content:center;align-items:center;gap:1px;display:flex;position:absolute;inset:0}.VWh0dG_heroGaugePct{letter-spacing:-.02em;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary);font-size:18px;font-weight:700;line-height:22px}.VWh0dG_heroGaugePctOver{color:var(--dsw-static-red-500)}.VWh0dG_heroGaugeLabel{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:14px}.VWh0dG_heroSide{border-top:1px solid var(--dsw-alias-border-l1);align-items:stretch;padding-top:14px;display:flex}.VWh0dG_heroSideItem{flex-direction:column;flex:1;gap:3px;min-width:0;padding-left:16px;display:flex}.VWh0dG_heroSideItem:first-child{padding-left:0}.VWh0dG_heroSideLabel{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:11px;line-height:15px}.VWh0dG_heroSideValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;letter-spacing:-.01em;white-space:nowrap;align-items:baseline;gap:6px;font-size:18px;font-weight:600;line-height:24px;display:inline-flex}.VWh0dG_heroSideSpacer{flex:1;display:block}.VWh0dG_delta{align-items:center;gap:2px;margin-left:4px;font-size:11px;font-weight:600;line-height:17px;display:inline-flex}.VWh0dG_deltaUp{color:var(--dsw-static-green-500)}.VWh0dG_deltaDown{color:var(--dsw-static-red-500)}.VWh0dG_kpiGrid{grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;display:grid}.VWh0dG_kpiTile{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:14px;flex-direction:column;gap:3px;padding:14px 15px;transition:border-color .16s;display:flex;position:relative;overflow:hidden}.VWh0dG_kpiTile:hover{border-color:var(--dsw-alias-border-l2)}.VWh0dG_kpiLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:15px}.VWh0dG_kpiValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;letter-spacing:-.01em;font-size:22px;font-weight:600;line-height:28px}.VWh0dG_kpiGreen{color:var(--dsw-static-green-500)}.VWh0dG_kpiDetail{color:var(--dsw-alias-label-caption);white-space:nowrap;text-overflow:ellipsis;font-size:11px;line-height:15px;overflow:hidden}.VWh0dG_panel{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:16px;flex-direction:column;gap:10px;padding:16px 18px;transition:border-color .16s;display:flex}.VWh0dG_panelHead{justify-content:space-between;align-items:baseline;gap:10px;display:flex}.VWh0dG_panelTitle{letter-spacing:-.005em;color:var(--dsw-alias-label-primary);margin:0;font-size:14px;font-weight:600;line-height:20px}.VWh0dG_panelHint{color:var(--dsw-alias-label-caption);white-space:nowrap;font-size:11px;line-height:16px}.VWh0dG_pricingTip{color:var(--dsw-alias-label-caption);margin:0 0 2px;font-size:11px;line-height:16px}.VWh0dG_rangeToggle{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:8px;gap:2px;padding:2px;display:inline-flex}.VWh0dG_rangeButton{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:2px 8px;font-size:11px;line-height:16px;transition:background-color .14s,color .14s}.VWh0dG_rangeButtonActive{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);font-weight:600}.VWh0dG_exportBar{justify-content:flex-end;align-items:center;gap:8px;display:flex}.VWh0dG_exportLabel{color:var(--dsw-alias-label-caption);font-size:11px;line-height:16px}.VWh0dG_exportButton{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);cursor:pointer;border-radius:999px;padding:4px 12px;font-size:11.5px;line-height:16px;transition:border-color .16s,color .16s,background-color .16s}.VWh0dG_exportButton:hover,.VWh0dG_exportButton:focus-visible{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);outline:none}.VWh0dG_shareTrack{background:var(--dsw-alias-bg-module-platform);border-radius:999px;height:10px;display:flex;overflow:hidden}.VWh0dG_shareSeg{height:100%;transition:width .2s}.VWh0dG_shareSegPeak{background:var(--dsw-static-blue-500)}.VWh0dG_shareSegOff{background:color-mix(in srgb, var(--dsw-static-blue-500) 25%, var(--dsw-alias-bg-module-platform))}.VWh0dG_shareSegUser{background:var(--dsw-static-blue-500)}.VWh0dG_shareSegAssistant{background:var(--dsw-static-green-500)}.VWh0dG_shareSegTool{background:var(--dsw-static-amber-500)}.VWh0dG_shareLegend{align-items:center;gap:16px;display:flex}.VWh0dG_shareItem{color:var(--dsw-alias-label-secondary);align-items:baseline;gap:6px;font-size:12px;line-height:17px;display:inline-flex}.VWh0dG_bucketCost{align-items:baseline;gap:3px;display:inline-flex}.VWh0dG_bucketOfficial{color:var(--dsw-static-blue-500);font-weight:600}.VWh0dG_bucketSep{color:var(--dsw-alias-label-dimmed)}.VWh0dG_bucketThird{color:var(--dsw-alias-label-secondary)}.VWh0dG_bucketSummary{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;display:grid}.VWh0dG_bucketStat{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:12px;flex-direction:column;gap:4px;padding:12px 14px;display:flex}.VWh0dG_bucketStatLabel{color:var(--dsw-alias-label-tertiary);text-transform:uppercase;letter-spacing:.05em;font-size:11px;line-height:15px}.VWh0dG_bucketStatValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;letter-spacing:-.01em;font-size:20px;font-weight:700;line-height:26px}.VWh0dG_bucketStatSub{color:var(--dsw-alias-label-caption);font-variant-numeric:tabular-nums;font-size:11px;line-height:16px}.VWh0dG_shareDot{border-radius:50%;flex:none;align-self:center;width:8px;height:8px}.VWh0dG_shareValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;font-weight:600}.VWh0dG_budget{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:14px;flex-direction:column;gap:8px;padding:12px 16px;display:flex}.VWh0dG_budgetHead{justify-content:space-between;align-items:baseline;gap:10px;display:flex}.VWh0dG_budgetLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:17px}.VWh0dG_budgetValue{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:12px;line-height:17px}.VWh0dG_budgetControls{align-items:center;gap:8px;min-width:0;display:inline-flex}.VWh0dG_budgetInputWrap{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:6px;align-items:center;gap:2px;padding:2px 6px;display:inline-flex}.VWh0dG_budgetInputWrap:focus-within{border-color:var(--dsw-alias-border-l3)}.VWh0dG_budgetUnit{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.VWh0dG_budgetInput{width:64px;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;text-align:right;background:0 0;border:none;padding:0;font-size:12px;line-height:16px}.VWh0dG_budgetInput:focus-visible{outline:none}.VWh0dG_switch{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);cursor:pointer;border-radius:999px;flex:none;width:30px;height:17px;padding:0;transition:background-color .16s,border-color .16s;position:relative}.VWh0dG_switchOn{border-color:var(--dsw-alias-border-l1);background:var(--dsw-alias-label-primary)}.VWh0dG_switchKnob{background:var(--dsw-static-neutral-bluish-00);border-radius:50%;width:11px;height:11px;transition:transform .16s;position:absolute;top:2px;left:2px}.VWh0dG_switchOn .VWh0dG_switchKnob{transform:translate(13px)}.VWh0dG_budgetTrack{background:var(--dsw-alias-bg-module-platform);border-radius:999px;height:6px;overflow:hidden}.VWh0dG_budgetFill{background:var(--dsw-static-blue-500);border-radius:999px;height:100%;transition:width .2s}.VWh0dG_budgetFillWarn{background:var(--dsw-static-amber-500)}.VWh0dG_budgetFillOver{background:var(--dsw-static-red-500);animation:1.6s ease-in-out infinite VWh0dG_budgetOverPulse}@keyframes VWh0dG_budgetOverPulse{50%{opacity:.55}}.VWh0dG_chartWrap{width:100%;position:relative}.VWh0dG_chartSvg{width:100%;height:auto;display:block}.VWh0dG_chartEmpty{height:140px;color:var(--dsw-alias-label-caption);justify-content:center;align-items:center;font-size:13px;display:flex}.VWh0dG_emptyRow{text-align:center;color:var(--dsw-alias-label-caption);padding:28px 0;font-size:13px}.VWh0dG_chartGrid{stroke:var(--dsw-alias-border-l1);stroke-width:1px}.VWh0dG_chartAxisLabel{fill:var(--dsw-alias-label-tertiary);font-size:10px}.VWh0dG_chartBar{fill:var(--dsw-static-blue-500);opacity:.7}.VWh0dG_chartBar:hover{opacity:1}.VWh0dG_chartStack{stroke:var(--dsw-alias-bg-layer-1);stroke-width:.75px}.VWh0dG_chartStack:hover{opacity:.9}.VWh0dG_chartLine{stroke:var(--dsw-static-blue-500);stroke-width:2px;stroke-linecap:round;stroke-linejoin:round}.VWh0dG_chartCrosshair{stroke:var(--dsw-alias-label-dimmed);stroke-width:1px;stroke-dasharray:3 3}.VWh0dG_chartDot{fill:var(--dsw-static-neutral-bluish-00);stroke:var(--dsw-static-blue-500);stroke-width:2px}.VWh0dG_chartTooltip{pointer-events:none;z-index:2;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);box-shadow:none;white-space:nowrap;border-radius:8px;padding:8px 10px;position:absolute;transform:translate(-50%,calc(-100% - 10px))}.VWh0dG_chartTooltipDate{color:var(--dsw-alias-label-primary);margin-bottom:3px;font-size:11px;font-weight:600}.VWh0dG_chartTooltipRow{color:var(--dsw-alias-label-secondary);align-items:center;gap:5px;font-size:11px;line-height:17px;display:flex}.VWh0dG_chartTooltipRow strong{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;font-weight:600}.VWh0dG_chartLegendLine{background:var(--dsw-static-blue-500);border-radius:2px;width:10px;height:3px;display:inline-block}.VWh0dG_chartLegendBar{background:var(--dsw-static-blue-500);opacity:.5;border-radius:2px;width:7px;height:7px;display:inline-block}.VWh0dG_chartTooltipSwatch{border-radius:3px;flex:none;width:8px;height:8px;display:inline-block}.VWh0dG_chartLegend{color:var(--dsw-alias-label-tertiary);justify-content:flex-end;gap:14px;margin-top:2px;font-size:11px;display:flex}.VWh0dG_chartLegend span{align-items:center;gap:5px;display:inline-flex}.VWh0dG_tableScroll{border:1px solid var(--dsw-alias-border-l1);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:12px;overflow:auto}.VWh0dG_modelTable,.VWh0dG_pricingTable{border-collapse:collapse;width:100%;font-size:12.5px}.VWh0dG_modelTable th,.VWh0dG_modelTable td,.VWh0dG_pricingTable th,.VWh0dG_pricingTable td{border-bottom:1px solid var(--dsw-alias-border-l1);text-align:left;white-space:nowrap;padding:9px 12px}.VWh0dG_modelTable tbody tr:last-child td,.VWh0dG_pricingTable tbody tr:last-child td{border-bottom:0}.VWh0dG_modelTable thead th,.VWh0dG_pricingTable thead th{color:var(--dsw-alias-label-tertiary);text-transform:uppercase;letter-spacing:.05em;background:0 0;font-size:11px;font-weight:600}.VWh0dG_modelTable tbody tr,.VWh0dG_pricingTable tbody tr{transition:background-color .12s}.VWh0dG_modelTable tbody tr:hover,.VWh0dG_pricingTable tbody tr:hover{background:0 0}.VWh0dG_numCol{text-align:right;font-variant-numeric:tabular-nums}.VWh0dG_costCol{color:var(--dsw-alias-label-primary);font-weight:600}.VWh0dG_na{color:var(--dsw-alias-label-dimmed)}.VWh0dG_modelCell{align-items:center;gap:8px;display:inline-flex}.VWh0dG_modelDot{border-radius:50%;flex:none;width:9px;height:9px}.VWh0dG_modelName{color:var(--dsw-alias-label-primary);font-weight:500;line-height:16px;display:block}.VWh0dG_modelProvider{color:var(--dsw-alias-label-caption);font-size:10.5px;line-height:14px;display:block}.VWh0dG_pricingToggle{cursor:pointer;text-align:left;background:0 0;border:none;justify-content:space-between;align-items:center;gap:10px;width:100%;padding:0;display:flex}.VWh0dG_pricingToggle:hover .VWh0dG_panelTitle,.VWh0dG_pricingToggle:focus-visible .VWh0dG_panelTitle{color:var(--dsw-alias-label-primary)}.VWh0dG_rateBadge{vertical-align:1px;white-space:nowrap;border-radius:999px;align-items:center;margin-left:6px;padding:1px 6px;font-size:10px;font-weight:500;line-height:14px;display:inline-flex}.VWh0dG_rateBadgeLive{color:var(--dsw-static-green-500);background:var(--dsw-alias-bg-layer-2)}.VWh0dG_rateBadgeBuiltin{color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2)}.VWh0dG_pricingToggleText{align-items:baseline;gap:10px;min-width:0;display:flex}.VWh0dG_pricingChevron{width:16px;height:16px;color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.VWh0dG_pricingChevronOpen{transform:rotate(180deg)}.VWh0dG_bandPrice{align-items:baseline;gap:6px;display:inline-flex}.VWh0dG_bandPriceOff{color:var(--dsw-alias-label-caption)}.VWh0dG_bandPriceOff:before{content:\"/\";color:var(--dsw-alias-label-dimmed);margin-right:4px}.VWh0dG_bandTag{color:var(--dsw-alias-label-secondary);flex-direction:column;gap:1px;font-size:10.5px;line-height:14px;display:inline-flex}.VWh0dG_bandTagOff{color:var(--dsw-static-green-500);font-weight:600}.VWh0dG_bandTag>span:first-child{color:var(--dsw-alias-label-primary);font-weight:500}.VWh0dG_flatTag{color:var(--dsw-alias-label-caption);font-size:10.5px;line-height:14px}.VWh0dG_healthDot{border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.VWh0dG_healthOk{background:var(--dsw-static-green-500)}.VWh0dG_healthBad{background:var(--dsw-static-red-500)}.VWh0dG_healthIdle{background:var(--dsw-static-neutral-bluish-400)}.VWh0dG_dashboardRight{align-items:center;gap:8px;min-width:0;display:flex}.VWh0dG_healthBadge{white-space:nowrap;border-radius:999px;align-items:center;gap:6px;padding:3px 9px;font-size:11px;line-height:16px;display:inline-flex}.VWh0dG_healthBadgeOk{color:var(--dsw-static-green-500);background:var(--dsw-alias-bg-layer-2)}.VWh0dG_healthBadgeBad{color:var(--dsw-static-red-500);background:var(--dsw-alias-bg-layer-2)}.VWh0dG_planTag{color:var(--dsw-static-green-500);background:var(--dsw-alias-bg-layer-2);border-radius:999px;align-items:center;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px;display:inline-flex}.VWh0dG_uncataloguedTag{vertical-align:1px;color:var(--dsw-static-amber-500);background:var(--dsw-alias-bg-layer-2);border-radius:999px;margin-left:6px;padding:0 6px;font-size:10px;font-weight:600;line-height:16px;display:inline-block}.VWh0dG_estimatedTag{vertical-align:1px;color:var(--dsw-static-blue-500);background:var(--dsw-alias-bg-layer-2);border-radius:999px;margin-left:6px;padding:0 6px;font-size:10px;font-weight:600;line-height:16px;display:inline-block}.VWh0dG_liveCostBar{color:var(--dsw-static-neutral-400);font-variant-numeric:tabular-nums;align-items:center;gap:6px;font-size:11px;line-height:16px;display:inline-flex}.VWh0dG_liveCostItem{white-space:nowrap}.VWh0dG_liveCostSep{color:var(--dsw-static-neutral-300)}.VWh0dG_liveTierPeak{color:var(--dsw-static-blue-500);font-weight:600}.VWh0dG_liveTierOff{color:var(--dsw-static-green-500);font-weight:600}.VWh0dG_liveQuotaWarn{color:var(--dsw-static-amber-500);font-weight:600}.VWh0dG_liveQuotaCrit{color:var(--dsw-static-red-500);font-weight:600}.VWh0dG_balanceCell{flex-direction:column;align-items:flex-end;gap:2px;display:inline-flex}.VWh0dG_balanceDays{color:var(--dsw-alias-label-caption);white-space:nowrap;font-size:10.5px;line-height:14px}.VWh0dG_balanceDaysLow{color:var(--dsw-static-red-500);font-weight:600}body[data-zine-mode] .VWh0dG_trigger,body[data-zine-mode] .VWh0dG_triggerPop,body[data-zine-mode] .VWh0dG_railButton{display:none}body[data-zine-mode] .VWh0dG_dashboardHead{background:#000;border-bottom:2px solid #e8ff00}body[data-zine-mode] .VWh0dG_headTitleRow{align-items:center;gap:8px;margin-top:4px;display:flex}body[data-zine-mode] .VWh0dG_dashboardTitle{color:#e8ff00;letter-spacing:.04em;text-transform:uppercase;text-shadow:0 0 8px #e8ff0066;font-weight:900}body[data-zine-mode] .VWh0dG_dashboardSubtitle{color:#c9d98a;letter-spacing:.08em;text-transform:uppercase;font-size:10px}body[data-zine-mode] .VWh0dG_closeButton{color:#0a0a05;background:#ff2d95;border:1.5px solid #ff2d95;border-radius:0;box-shadow:0 0 10px #ff2d9573}body[data-zine-mode] .VWh0dG_hero{background:#000;border:2.5px solid #e8ff00;border-radius:0;position:relative;box-shadow:0 0 0 1px #0009,0 0 24px #e8ff002e}body[data-zine-mode] .VWh0dG_heroLabel{color:#c9d98a;letter-spacing:.12em;text-transform:uppercase;font-size:10px;font-weight:900}body[data-zine-mode] .VWh0dG_heroValue{color:#e8ff00;letter-spacing:-.02em;text-shadow:0 0 12px #e8ff0073;-webkit-text-fill-color:#e8ff00;background:0 0;font-size:38px;font-weight:900}body[data-zine-mode] .VWh0dG_heroMeta{color:#c9d98a;letter-spacing:.06em;text-transform:uppercase;font-size:10.5px}body[data-zine-mode] .VWh0dG_heroSideLabel{color:#c9d98a;letter-spacing:.1em;text-transform:uppercase;font-size:10px;font-weight:900}body[data-zine-mode] .VWh0dG_heroSideValue{color:#e8ff00;text-shadow:0 0 6px #e8ff0059}body[data-zine-mode] .VWh0dG_delta{font-weight:900}body[data-zine-mode] .VWh0dG_deltaUp{color:#ff2d95}body[data-zine-mode] .VWh0dG_deltaDown{color:#c9d98a}body[data-zine-mode] .VWh0dG_tabNav{background:#000;border-bottom:2px solid #e8ff00}body[data-zine-mode] .VWh0dG_tabButton{color:#c9d98a;letter-spacing:.08em;text-transform:uppercase;border-radius:0;font-size:10.5px;font-weight:900}body[data-zine-mode] .VWh0dG_tabButton:hover,body[data-zine-mode] .VWh0dG_tabButton:focus-visible{color:#e8ff00;background:#e8ff001f}body[data-zine-mode] .VWh0dG_tabButtonActive,body[data-zine-mode] .VWh0dG_tabButtonActive:hover,body[data-zine-mode] .VWh0dG_tabButtonActive:focus-visible{color:#0a0a05;background:#e8ff00;box-shadow:0 0 10px #e8ff0073}body[data-zine-mode] .VWh0dG_panel{background:#000;border:2px solid #e8ff00;border-radius:0}body[data-zine-mode] .VWh0dG_trendPanel{position:relative}body[data-zine-mode] .VWh0dG_panelTitle{color:#e8ff00;letter-spacing:.06em;text-transform:uppercase;text-shadow:0 0 6px #e8ff0066;font-weight:900}body[data-zine-mode] .VWh0dG_panelHint{color:#c9d98a;letter-spacing:.08em;text-transform:uppercase;font-size:10px;font-weight:900}body[data-zine-mode] .VWh0dG_modelTableScroll{background:#000;border:1.5px solid #e8ff0080;border-radius:0}.VWh0dG_currencyToggle{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:6px;align-items:center;gap:2px;margin-right:8px;padding:2px;display:inline-flex}.VWh0dG_currencyButton{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:4px;padding:4px 7px;font-size:11px;font-weight:700;line-height:1}.VWh0dG_currencyButtonActive{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}.VWh0dG_subscriptionGrid{grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:10px;margin-top:10px;display:grid}.VWh0dG_subscriptionCard{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:10px;padding:12px 14px}.VWh0dG_subscriptionHead{flex-wrap:wrap;align-items:baseline;gap:6px;margin-bottom:8px;display:flex}.VWh0dG_subscriptionName{font-size:13px;font-weight:700}.VWh0dG_subscriptionPlan{color:var(--dsw-alias-label-secondary);font-size:11px}.VWh0dG_subscriptionPlan[data-kind=code],.VWh0dG_subscriptionPlan[data-kind=token]{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-3);border-radius:999px;padding:1px 8px;font-weight:500}.VWh0dG_subscriptionTier{color:var(--dsw-alias-label-secondary);margin-left:6px}.VWh0dG_subscriptionAuto{color:var(--dsw-static-blue-500);background:color-mix(in srgb, var(--dsw-static-blue-500) 14%, var(--dsw-alias-bg-layer-2));border-radius:999px;margin-left:6px;padding:1px 6px;font-size:10px}.VWh0dG_subscriptionStatus{color:var(--dsw-alias-label-secondary);margin-bottom:6px;font-size:11px}.VWh0dG_subscriptionWindow{align-items:center;gap:8px;margin-top:6px;font-size:11px;display:flex}.VWh0dG_subscriptionWindowLabel{color:var(--dsw-alias-label-secondary);flex:0 0 44px}.VWh0dG_subscriptionTrack{background:var(--dsw-alias-bg-layer-3);border-radius:3px;flex:1;height:5px;overflow:hidden}.VWh0dG_subscriptionFill{background:var(--dsw-static-blue-500);border-radius:3px;height:100%;transition:width .2s;display:block}.VWh0dG_subscriptionFillWarn{background:var(--dsw-static-amber-500)}.VWh0dG_subscriptionFillOver{background:var(--dsw-static-red-500)}.VWh0dG_subscriptionPct{text-align:right;font-variant-numeric:tabular-nums;flex:none;min-width:52px}.VWh0dG_subscriptionExhausted{color:var(--dsw-static-red-500);min-width:52px;font-weight:600}.VWh0dG_subscriptionReset{color:var(--dsw-alias-label-secondary);flex:none}.VWh0dG_providerGroupList{flex-direction:column;gap:10px;display:flex}.VWh0dG_providerGroup{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:12px;padding:12px 14px}.VWh0dG_providerGroupHead{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.VWh0dG_providerGroupTitle{align-items:center;gap:7px;min-width:0;display:inline-flex}.VWh0dG_providerGroupName{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:18px}.VWh0dG_providerGroupMeta{flex:none;align-items:center;gap:10px;display:inline-flex}.VWh0dG_providerGroupBadge{color:var(--dsw-static-green-500);background:var(--dsw-alias-bg-layer-2);border-radius:999px;align-items:center;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px;display:inline-flex}.VWh0dG_providerGroupBalance{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;white-space:nowrap;align-items:baseline;gap:6px;font-size:12px;line-height:17px;display:inline-flex}.VWh0dG_providerGroupBalanceLabel{color:var(--dsw-alias-label-caption);font-size:11px;line-height:17px}.VWh0dG_roundsFlagBadge{color:var(--dsw-static-neutral-bluish-00);background:var(--dsw-static-red-500);border-radius:999px;margin-left:8px;padding:1px 7px;font-size:10px;font-weight:800}.VWh0dG_rounds{margin-top:10px}.VWh0dG_roundsBars{align-items:flex-end;gap:3px;height:124px;padding:16px 2px 0;display:flex;overflow-x:auto}.VWh0dG_roundsBarCol{border-radius:5px 5px 0 0;flex-direction:column;flex:1 0 28px;justify-content:flex-end;align-items:stretch;height:100%;display:flex;position:relative}.VWh0dG_roundsBarColPeak{background:color-mix(in srgb, var(--dsw-static-amber-500) 16%, transparent)}.VWh0dG_roundsBarColOff{background:var(--dsw-alias-bg-module-platform)}.VWh0dG_roundsBarLabel{text-align:center;color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;max-width:100%;font-size:9px;line-height:1.2;position:absolute;bottom:0;left:0;right:0;overflow:hidden;transform:translateY(-100%)}.VWh0dG_roundsBarWrap{flex:1;align-items:flex-end;min-height:0;display:flex}.VWh0dG_roundsBar{background:var(--dsw-static-blue-500);border-radius:2px 2px 0 0;width:100%;min-height:2px;position:relative}.VWh0dG_roundsBarFlagged{background:var(--dsw-static-red-500);border-radius:2px 2px 0 0;width:100%;min-height:2px;position:relative}.VWh0dG_roundsFlagMark{background:var(--dsw-static-red-500);border-radius:50%;width:7px;height:7px;position:absolute;top:-3px;right:-3px}.VWh0dG_roundsAxis{color:var(--dsw-alias-label-secondary);justify-content:space-between;margin-top:6px;font-size:10px;display:flex}.VWh0dG_roundsEmpty{color:var(--dsw-alias-label-secondary);margin-top:10px;font-size:12px}.VWh0dG_heatmap{margin-top:10px}.VWh0dG_heatmapGrid{grid-template-columns:repeat(7,minmax(0,1fr));gap:8px;display:grid}.VWh0dG_heatmapCellEmpty{background:var(--dsw-alias-bg-layer-1);height:30px;color:var(--dsw-alias-label-dimmed);font-variant-numeric:tabular-nums;border-radius:8px;justify-content:center;align-items:center;font-size:11px;display:flex}.VWh0dG_heatmapCell{font-variant-numeric:tabular-nums;cursor:pointer;border:0;border-radius:8px;justify-content:center;align-items:center;height:30px;padding:0;font-size:11px;display:flex}.VWh0dG_heatmapCell[data-level=\"0\"],.VWh0dG_heatmapCell[data-level=\"1\"],.VWh0dG_heatmapCell[data-level=\"2\"]{color:var(--dsw-alias-label-primary)}.VWh0dG_heatmapCell[data-level=\"3\"],.VWh0dG_heatmapCell[data-level=\"4\"]{color:var(--dsw-static-neutral-bluish-00)}.VWh0dG_heatmapFooter{color:var(--dsw-alias-label-secondary);align-items:center;gap:8px;margin-top:10px;font-size:10px;display:flex}.VWh0dG_heatmapLegend{gap:3px;display:inline-flex}.VWh0dG_heatmapLegend i{border-radius:4px;width:14px;height:14px;display:block}.VWh0dG_heatmapHover{font-variant-numeric:tabular-nums;margin-left:auto}.VWh0dG_heatmapYearScroll{padding-bottom:2px;overflow-x:auto}.VWh0dG_heatmapYearGrid{grid-template-rows:repeat(7,11px);grid-auto-flow:column;gap:3px;min-width:max-content;display:grid}.VWh0dG_heatmapYearCell{cursor:pointer;border:0;border-radius:2px;width:11px;height:11px;padding:0}.VWh0dG_pluginInfo{flex-direction:column;gap:8px;margin-top:10px;display:flex}.VWh0dG_pluginInfoRow{align-items:baseline;gap:12px;font-size:12px;display:flex}.VWh0dG_pluginInfoLabel{color:var(--dsw-alias-label-secondary);flex:0 0 72px}.VWh0dG_pluginInfoValue{color:var(--dsw-alias-label-primary);word-break:break-all}.VWh0dG_pluginInfoLink{color:var(--dsw-static-blue-500);word-break:break-all;text-decoration:none}.VWh0dG_pluginInfoLink:hover{text-decoration:underline}.VWh0dG_tokenPanel{flex-direction:column;gap:14px;display:flex}.VWh0dG_tokenModelBar{background:var(--dsw-alias-bg-layer-2);border-radius:999px;height:8px;overflow:hidden}.VWh0dG_tokenModelParts{height:100%;display:flex}.VWh0dG_tokenModelPartIn{background:var(--dsw-static-blue-500)}.VWh0dG_tokenModelPartOut{background:var(--dsw-static-amber-500)}.VWh0dG_tokenModelShareRow{align-items:center;gap:6px;display:inline-flex}@media (width<=640px){.VWh0dG_kpiGrid{grid-template-columns:repeat(2,minmax(0,1fr))}.VWh0dG_hero{gap:14px}.VWh0dG_heroTop{flex-direction:column;align-items:flex-start;gap:12px}.VWh0dG_heroGauge{width:72px;height:72px}.VWh0dG_heroSide{gap:12px}.VWh0dG_heroSideSpacer{display:none}}.VWh0dG_peakAlert{z-index:2000;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:12px;align-items:center;gap:12px;min-width:300px;max-width:460px;padding:10px 12px;animation:.2s VWh0dG_peakAlertIn;display:flex;position:fixed;box-shadow:0 4px 16px #00000014}.VWh0dG_peakAlertCorner{bottom:18px;right:18px}.VWh0dG_peakAlertCenter{top:20%;left:50%;transform:translate(-50%)}.VWh0dG_peakAlertTag{letter-spacing:.01em;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-3);white-space:nowrap;border-radius:999px;flex:none;align-items:center;gap:6px;padding:3px 9px;font-size:11px;font-weight:650;display:inline-flex}.VWh0dG_peakAlertTag:before{content:\"\";background:currentColor;border-radius:50%;width:6px;height:6px}.VWh0dG_peakAlertPeak .VWh0dG_peakAlertTag{color:var(--dsw-static-amber-500)}.VWh0dG_peakAlertOff .VWh0dG_peakAlertTag{color:var(--dsw-static-blue-500)}.VWh0dG_peakAlertCountdown{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary);flex:none;font-size:18px;font-weight:700;line-height:1}.VWh0dG_peakAlertText{min-width:0;color:var(--dsw-alias-label-secondary);flex:1;font-size:12px;line-height:18px}.VWh0dG_peakAlertClose{width:20px;height:20px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;justify-content:center;align-items:center;font-size:15px;line-height:1;transition:background-color .14s,color .14s;display:inline-flex}.VWh0dG_peakAlertClose:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}@keyframes VWh0dG_peakAlertIn{0%{opacity:0}to{opacity:1}}.VWh0dG_peakAlertPanel{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:16px;flex-direction:column;gap:10px;padding:14px 16px;display:flex}.VWh0dG_peakAlertPanelHead{justify-content:space-between;align-items:center;gap:10px;display:flex}.VWh0dG_peakAlertPanelLabel{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600}.VWh0dG_peakAlertPanelBody{flex-wrap:wrap;align-items:center;gap:12px 16px;display:flex}.VWh0dG_peakAlertField{color:var(--dsw-alias-label-secondary);align-items:center;gap:8px;font-size:12px;display:inline-flex}.VWh0dG_peakAlertNum{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);width:56px;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;border-radius:6px;padding:4px 6px}.VWh0dG_peakAlertSelect{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);border-radius:6px;padding:4px 6px;font-size:12px}.VWh0dG_peakAlertCheck{color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;font-size:12px;display:inline-flex}.VWh0dG_peakAlertPreview{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;padding:5px 10px;font-size:12px}.VWh0dG_peakAlertPreview:hover{background:var(--dsw-alias-bg-layer-3)}.VWh0dG_settingsHead{flex-direction:column;gap:4px;margin-bottom:2px;display:flex}.VWh0dG_settingsTitle{letter-spacing:-.005em;color:var(--dsw-alias-label-primary);margin:0;font-size:15px;font-weight:650;line-height:22px}.VWh0dG_settingsHint{color:var(--dsw-alias-label-caption);margin:0;font-size:11px;line-height:16px}.VWh0dG_budgetHint,.VWh0dG_peakAlertHint{color:var(--dsw-alias-label-caption);margin:6px 0 0;font-size:11px;line-height:16px}";
28
28
  const tagId = "@kenz1117/dsh-ui-usage-billing/UsageBilling.module.css";
29
29
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
30
30
  const tag = document.createElement("style");
@@ -34,260 +34,266 @@ window.__ModuleLoader__.load({
34
34
  document.head.appendChild(tag);
35
35
  }
36
36
  var UsageBilling_module_css_default = {
37
- "currencyButton": "VWh0dG_currencyButton",
38
- "providerGroupList": "VWh0dG_providerGroupList",
39
- "pricingChevron": "VWh0dG_pricingChevron",
40
- "peakAlertOff": "VWh0dG_peakAlertOff",
41
- "chartLegend": "VWh0dG_chartLegend",
42
- "closeButton": "VWh0dG_closeButton",
43
- "subscriptionAuto": "VWh0dG_subscriptionAuto",
44
- "shareDot": "VWh0dG_shareDot",
45
- "budgetValue": "VWh0dG_budgetValue",
46
- "subscriptionName": "VWh0dG_subscriptionName",
47
- "roundsAxis": "VWh0dG_roundsAxis",
48
- "chartLine": "VWh0dG_chartLine",
49
- "rangeToggle": "VWh0dG_rangeToggle",
50
- "deltaUp": "VWh0dG_deltaUp",
51
- "healthBad": "VWh0dG_healthBad",
52
- "numCol": "VWh0dG_numCol",
53
- "heroSideItem": "VWh0dG_heroSideItem",
54
- "triggerSpark": "VWh0dG_triggerSpark",
55
- "chartTooltipDate": "VWh0dG_chartTooltipDate",
56
- "bucketSep": "VWh0dG_bucketSep",
57
- "deltaDown": "VWh0dG_deltaDown",
58
- "budgetFill": "VWh0dG_budgetFill",
59
- "healthDot": "VWh0dG_healthDot",
60
- "uncataloguedTag": "VWh0dG_uncataloguedTag",
61
- "subscriptionTier": "VWh0dG_subscriptionTier",
62
- "heroCurrency": "VWh0dG_heroCurrency",
63
- "roundsBars": "VWh0dG_roundsBars",
64
- "budget": "VWh0dG_budget",
65
- "chartTooltip": "VWh0dG_chartTooltip",
66
- "chartTooltipRow": "VWh0dG_chartTooltipRow",
67
- "bucketCost": "VWh0dG_bucketCost",
68
- "flatTag": "VWh0dG_flatTag",
69
- "heatmapHover": "VWh0dG_heatmapHover",
70
- "budgetHint": "VWh0dG_budgetHint",
71
- "chartLegendBar": "VWh0dG_chartLegendBar",
72
- "heroGaugeTrack": "VWh0dG_heroGaugeTrack",
73
- "triggerSub": "VWh0dG_triggerSub",
74
- "triggerPop": "VWh0dG_triggerPop",
75
- "triggerMeta": "VWh0dG_triggerMeta",
76
- "heroSideSpacer": "VWh0dG_heroSideSpacer",
77
- "tabPanelIn": "VWh0dG_tabPanelIn",
78
- "settingsTitle": "VWh0dG_settingsTitle",
79
- "kpiValue": "VWh0dG_kpiValue",
80
- "switch": "VWh0dG_switch",
81
- "bandTagOff": "VWh0dG_bandTagOff",
82
- "subscriptionPct": "VWh0dG_subscriptionPct",
83
- "budgetHead": "VWh0dG_budgetHead",
84
37
  "heroMeta": "VWh0dG_heroMeta",
85
- "dashboard": "VWh0dG_dashboard",
86
- "pluginInfoLink": "VWh0dG_pluginInfoLink",
87
- "roundsFlagMark": "VWh0dG_roundsFlagMark",
88
- "chartLegendLine": "VWh0dG_chartLegendLine",
89
- "chartTooltipSwatch": "VWh0dG_chartTooltipSwatch",
90
- "pricingTable": "VWh0dG_pricingTable",
91
- "bandTag": "VWh0dG_bandTag",
92
- "liveCostItem": "VWh0dG_liveCostItem",
93
38
  "kpiDetail": "VWh0dG_kpiDetail",
94
- "estimatedTag": "VWh0dG_estimatedTag",
95
- "chartAxisLabel": "VWh0dG_chartAxisLabel",
96
- "heroGaugeArc": "VWh0dG_heroGaugeArc",
97
- "modelTable": "VWh0dG_modelTable",
98
- "heroTop": "VWh0dG_heroTop",
99
- "rateBadgeLive": "VWh0dG_rateBadgeLive",
100
- "pluginInfoValue": "VWh0dG_pluginInfoValue",
101
- "peakAlertNum": "VWh0dG_peakAlertNum",
102
- "budgetControls": "VWh0dG_budgetControls",
103
- "pluginInfo": "VWh0dG_pluginInfo",
104
- "modelCell": "VWh0dG_modelCell",
105
- "bucketStat": "VWh0dG_bucketStat",
106
- "subscriptionHead": "VWh0dG_subscriptionHead",
39
+ "closeButton": "VWh0dG_closeButton",
107
40
  "kpiGrid": "VWh0dG_kpiGrid",
108
- "dashboardBody": "VWh0dG_dashboardBody",
109
- "providerGroupBalanceLabel": "VWh0dG_providerGroupBalanceLabel",
110
- "costCol": "VWh0dG_costCol",
41
+ "tokenModelPartIn": "VWh0dG_tokenModelPartIn",
42
+ "kpiLabel": "VWh0dG_kpiLabel",
43
+ "triggerBody": "VWh0dG_triggerBody",
44
+ "roundsBarCol": "VWh0dG_roundsBarCol",
45
+ "peakAlertClose": "VWh0dG_peakAlertClose",
46
+ "peakAlertSelect": "VWh0dG_peakAlertSelect",
47
+ "providerGroupList": "VWh0dG_providerGroupList",
48
+ "providerGroupBalance": "VWh0dG_providerGroupBalance",
49
+ "heroGaugeSvg": "VWh0dG_heroGaugeSvg",
50
+ "peakAlertCenter": "VWh0dG_peakAlertCenter",
111
51
  "triggerSparkHot": "VWh0dG_triggerSparkHot",
112
- "heroGaugeCenter": "VWh0dG_heroGaugeCenter",
113
- "modelDot": "VWh0dG_modelDot",
114
- "peakAlertIn": "VWh0dG_peakAlertIn",
115
- "bucketStatValue": "VWh0dG_bucketStatValue",
116
- "heroGauge": "VWh0dG_heroGauge",
117
- "triggerPopValue": "VWh0dG_triggerPopValue",
118
- "shareSegTool": "VWh0dG_shareSegTool",
119
- "triggerPopLabel": "VWh0dG_triggerPopLabel",
120
- "exportBar": "VWh0dG_exportBar",
121
- "dashboardHead": "VWh0dG_dashboardHead",
122
- "dashboardRight": "VWh0dG_dashboardRight",
123
- "liveQuotaWarn": "VWh0dG_liveQuotaWarn",
124
- "pricingTip": "VWh0dG_pricingTip",
125
- "dashboardModal": "VWh0dG_dashboardModal",
126
- "heatmapYearCell": "VWh0dG_heatmapYearCell",
127
- "shareSegOff": "VWh0dG_shareSegOff",
128
52
  "budgetFillOver": "VWh0dG_budgetFillOver",
53
+ "subscriptionCard": "VWh0dG_subscriptionCard",
54
+ "subscriptionPlan": "VWh0dG_subscriptionPlan",
55
+ "triggerPopValue": "VWh0dG_triggerPopValue",
56
+ "shareSegPeak": "VWh0dG_shareSegPeak",
57
+ "balanceCell": "VWh0dG_balanceCell",
58
+ "settingsTitle": "VWh0dG_settingsTitle",
59
+ "modelCell": "VWh0dG_modelCell",
60
+ "bucketStatSub": "VWh0dG_bucketStatSub",
61
+ "peakAlertPanel": "VWh0dG_peakAlertPanel",
62
+ "triggerPop": "VWh0dG_triggerPop",
63
+ "chartWrap": "VWh0dG_chartWrap",
64
+ "subscriptionWindowLabel": "VWh0dG_subscriptionWindowLabel",
65
+ "rateBadge": "VWh0dG_rateBadge",
66
+ "bucketStatLabel": "VWh0dG_bucketStatLabel",
67
+ "dashboardBody": "VWh0dG_dashboardBody",
68
+ "flatTag": "VWh0dG_flatTag",
69
+ "subscriptionTrack": "VWh0dG_subscriptionTrack",
70
+ "railButton": "VWh0dG_railButton",
71
+ "bucketSummary": "VWh0dG_bucketSummary",
72
+ "heatmapLegend": "VWh0dG_heatmapLegend",
129
73
  "rateBadgeBuiltin": "VWh0dG_rateBadgeBuiltin",
74
+ "heatmapCellEmpty": "VWh0dG_heatmapCellEmpty",
75
+ "peakAlertPreview": "VWh0dG_peakAlertPreview",
76
+ "healthIdle": "VWh0dG_healthIdle",
77
+ "subscriptionPct": "VWh0dG_subscriptionPct",
78
+ "modelDot": "VWh0dG_modelDot",
130
79
  "providerGroupTitle": "VWh0dG_providerGroupTitle",
131
- "peakAlertPeak": "VWh0dG_peakAlertPeak",
132
- "liveTierPeak": "VWh0dG_liveTierPeak",
133
- "budgetInputWrap": "VWh0dG_budgetInputWrap",
134
- "shareValue": "VWh0dG_shareValue",
135
- "heatmapGrid": "VWh0dG_heatmapGrid",
136
- "hero": "VWh0dG_hero",
137
- "budgetFillWarn": "VWh0dG_budgetFillWarn",
138
- "switchOn": "VWh0dG_switchOn",
139
- "emptyRow": "VWh0dG_emptyRow",
140
- "rateBadge": "VWh0dG_rateBadge",
141
- "triggerSparkBar": "VWh0dG_triggerSparkBar",
142
- "rounds": "VWh0dG_rounds",
143
- "balanceDays": "VWh0dG_balanceDays",
144
- "peakAlertField": "VWh0dG_peakAlertField",
145
- "providerGroupBalance": "VWh0dG_providerGroupBalance",
146
- "peakAlertPanel": "VWh0dG_peakAlertPanel",
80
+ "rangeButton": "VWh0dG_rangeButton",
81
+ "heatmapYearScroll": "VWh0dG_heatmapYearScroll",
82
+ "bucketSep": "VWh0dG_bucketSep",
83
+ "tokenModelParts": "VWh0dG_tokenModelParts",
84
+ "heroSideLabel": "VWh0dG_heroSideLabel",
85
+ "peakAlertCountdown": "VWh0dG_peakAlertCountdown",
86
+ "subscriptionHead": "VWh0dG_subscriptionHead",
87
+ "pluginInfoValue": "VWh0dG_pluginInfoValue",
88
+ "chartLegendLine": "VWh0dG_chartLegendLine",
89
+ "bucketCost": "VWh0dG_bucketCost",
90
+ "roundsBarColOff": "VWh0dG_roundsBarColOff",
91
+ "deltaUp": "VWh0dG_deltaUp",
92
+ "budgetControls": "VWh0dG_budgetControls",
93
+ "exportButton": "VWh0dG_exportButton",
94
+ "shareDot": "VWh0dG_shareDot",
95
+ "peakAlertPanelLabel": "VWh0dG_peakAlertPanelLabel",
96
+ "pluginInfo": "VWh0dG_pluginInfo",
97
+ "tokenModelShareRow": "VWh0dG_tokenModelShareRow",
98
+ "pricingChevronOpen": "VWh0dG_pricingChevronOpen",
147
99
  "peakAlertCheck": "VWh0dG_peakAlertCheck",
148
- "heatmapCellEmpty": "VWh0dG_heatmapCellEmpty",
149
100
  "peakAlertHint": "VWh0dG_peakAlertHint",
150
- "bandPrice": "VWh0dG_bandPrice",
151
- "bucketThird": "VWh0dG_bucketThird",
101
+ "balanceDays": "VWh0dG_balanceDays",
102
+ "trigger": "VWh0dG_trigger",
103
+ "kpiValue": "VWh0dG_kpiValue",
152
104
  "delta": "VWh0dG_delta",
153
- "chartStack": "VWh0dG_chartStack",
154
- "pricingToggle": "VWh0dG_pricingToggle",
105
+ "chartBar": "VWh0dG_chartBar",
106
+ "healthDot": "VWh0dG_healthDot",
107
+ "bucketStatValue": "VWh0dG_bucketStatValue",
108
+ "shareSegAssistant": "VWh0dG_shareSegAssistant",
109
+ "currencyButtonActive": "VWh0dG_currencyButtonActive",
110
+ "dashboard": "VWh0dG_dashboard",
111
+ "budgetInputWrap": "VWh0dG_budgetInputWrap",
112
+ "liveTierOff": "VWh0dG_liveTierOff",
113
+ "pricingToggleText": "VWh0dG_pricingToggleText",
114
+ "peakAlertField": "VWh0dG_peakAlertField",
115
+ "costCol": "VWh0dG_costCol",
116
+ "chartDot": "VWh0dG_chartDot",
117
+ "heroValue": "VWh0dG_heroValue",
155
118
  "subscriptionFillWarn": "VWh0dG_subscriptionFillWarn",
156
- "heatmap": "VWh0dG_heatmap",
157
- "chartSvg": "VWh0dG_chartSvg",
158
- "roundsBarLabel": "VWh0dG_roundsBarLabel",
159
- "planTag": "VWh0dG_planTag",
160
- "providerGroup": "VWh0dG_providerGroup",
119
+ "triggerAmount": "VWh0dG_triggerAmount",
120
+ "bucketThird": "VWh0dG_bucketThird",
161
121
  "bandPriceOff": "VWh0dG_bandPriceOff",
162
- "tabPanel": "VWh0dG_tabPanel",
163
- "budgetTrack": "VWh0dG_budgetTrack",
164
- "shareSeg": "VWh0dG_shareSeg",
165
- "kpiTile": "VWh0dG_kpiTile",
166
- "triggerIcon": "VWh0dG_triggerIcon",
167
- "heroGaugePctOver": "VWh0dG_heroGaugePctOver",
168
- "trigger": "VWh0dG_trigger",
169
- "budgetOverPulse": "VWh0dG_budgetOverPulse",
170
- "peakAlertSelect": "VWh0dG_peakAlertSelect",
171
- "budgetUnit": "VWh0dG_budgetUnit",
172
- "subscriptionTrack": "VWh0dG_subscriptionTrack",
173
- "pricingToggleText": "VWh0dG_pricingToggleText",
174
- "roundsEmpty": "VWh0dG_roundsEmpty",
175
- "settingsHead": "VWh0dG_settingsHead",
176
- "subscriptionWindowLabel": "VWh0dG_subscriptionWindowLabel",
177
- "dashboardSubtitle": "VWh0dG_dashboardSubtitle",
178
- "shareSegUser": "VWh0dG_shareSegUser",
179
- "peakAlertPanelLabel": "VWh0dG_peakAlertPanelLabel",
180
- "panelTitle": "VWh0dG_panelTitle",
181
- "providerGroupBadge": "VWh0dG_providerGroupBadge",
182
- "peakAlertPanelHead": "VWh0dG_peakAlertPanelHead",
183
- "settingsHint": "VWh0dG_settingsHint",
184
- "heatmapYearGrid": "VWh0dG_heatmapYearGrid",
185
- "bucketStatSub": "VWh0dG_bucketStatSub",
186
- "shareSegPeak": "VWh0dG_shareSegPeak",
187
- "rangeButtonActive": "VWh0dG_rangeButtonActive",
122
+ "subscriptionExhausted": "VWh0dG_subscriptionExhausted",
123
+ "roundsFlagBadge": "VWh0dG_roundsFlagBadge",
124
+ "dashboardModal": "VWh0dG_dashboardModal",
125
+ "providerGroupHead": "VWh0dG_providerGroupHead",
126
+ "bandTag": "VWh0dG_bandTag",
127
+ "heroTop": "VWh0dG_heroTop",
128
+ "triggerPopRow": "VWh0dG_triggerPopRow",
129
+ "na": "VWh0dG_na",
130
+ "liveCostSep": "VWh0dG_liveCostSep",
188
131
  "bucketOfficial": "VWh0dG_bucketOfficial",
189
- "chartWrap": "VWh0dG_chartWrap",
190
- "healthBadgeBad": "VWh0dG_healthBadgeBad",
191
- "panelHint": "VWh0dG_panelHint",
192
- "subscriptionWindow": "VWh0dG_subscriptionWindow",
193
- "heatmapYearScroll": "VWh0dG_heatmapYearScroll",
194
- "shareLegend": "VWh0dG_shareLegend",
195
- "kpiGreen": "VWh0dG_kpiGreen",
132
+ "pricingChevron": "VWh0dG_pricingChevron",
133
+ "shareValue": "VWh0dG_shareValue",
134
+ "chartSvg": "VWh0dG_chartSvg",
135
+ "balanceDaysLow": "VWh0dG_balanceDaysLow",
196
136
  "dashboardTitle": "VWh0dG_dashboardTitle",
197
- "liveTierOff": "VWh0dG_liveTierOff",
198
- "subscriptionFill": "VWh0dG_subscriptionFill",
199
- "healthIdle": "VWh0dG_healthIdle",
200
- "heroGaugeLabel": "VWh0dG_heroGaugeLabel",
201
- "peakAlertPanelBody": "VWh0dG_peakAlertPanelBody",
202
- "triggerRow": "VWh0dG_triggerRow",
203
- "healthBadgeOk": "VWh0dG_healthBadgeOk",
204
- "peakAlertCountdown": "VWh0dG_peakAlertCountdown",
205
- "chartBar": "VWh0dG_chartBar",
206
- "triggerPopBars": "VWh0dG_triggerPopBars",
207
- "providerGroupHead": "VWh0dG_providerGroupHead",
208
- "budgetInput": "VWh0dG_budgetInput",
209
- "triggerAmount": "VWh0dG_triggerAmount",
210
- "heroSideValue": "VWh0dG_heroSideValue",
211
- "bucketSummary": "VWh0dG_bucketSummary",
212
- "currencyButtonActive": "VWh0dG_currencyButtonActive",
213
- "healthBadge": "VWh0dG_healthBadge",
214
- "rangeButton": "VWh0dG_rangeButton",
215
- "subscriptionExhausted": "VWh0dG_subscriptionExhausted",
216
- "dashboardIn": "VWh0dG_dashboardIn",
217
- "subscriptionFillOver": "VWh0dG_subscriptionFillOver",
218
- "heatmapFooter": "VWh0dG_heatmapFooter",
219
- "balanceCell": "VWh0dG_balanceCell",
220
- "heroGaugeArcOver": "VWh0dG_heroGaugeArcOver",
221
- "pricingChevronOpen": "VWh0dG_pricingChevronOpen",
222
- "tabNav": "VWh0dG_tabNav",
223
- "heroSideLabel": "VWh0dG_heroSideLabel",
224
- "tableScroll": "VWh0dG_tableScroll",
225
- "heatmapLegend": "VWh0dG_heatmapLegend",
226
- "headTitleRow": "VWh0dG_headTitleRow",
227
- "subscriptionPlan": "VWh0dG_subscriptionPlan",
228
- "roundsBar": "VWh0dG_roundsBar",
137
+ "rangeButtonActive": "VWh0dG_rangeButtonActive",
229
138
  "roundsBarFlagged": "VWh0dG_roundsBarFlagged",
230
- "railButton": "VWh0dG_railButton",
231
139
  "triggerPopBar": "VWh0dG_triggerPopBar",
140
+ "providerGroupBadge": "VWh0dG_providerGroupBadge",
141
+ "chartTooltipDate": "VWh0dG_chartTooltipDate",
232
142
  "panel": "VWh0dG_panel",
143
+ "roundsEmpty": "VWh0dG_roundsEmpty",
144
+ "tableScroll": "VWh0dG_tableScroll",
145
+ "triggerPopBars": "VWh0dG_triggerPopBars",
146
+ "heroCurrency": "VWh0dG_heroCurrency",
147
+ "heatmapCell": "VWh0dG_heatmapCell",
148
+ "peakAlertTag": "VWh0dG_peakAlertTag",
149
+ "chartLegendBar": "VWh0dG_chartLegendBar",
150
+ "chartCrosshair": "VWh0dG_chartCrosshair",
151
+ "heroSide": "VWh0dG_heroSide",
152
+ "exportLabel": "VWh0dG_exportLabel",
153
+ "chartLine": "VWh0dG_chartLine",
154
+ "heroGaugePctOver": "VWh0dG_heroGaugePctOver",
155
+ "heroGaugePct": "VWh0dG_heroGaugePct",
156
+ "heroSideSpacer": "VWh0dG_heroSideSpacer",
157
+ "modelProvider": "VWh0dG_modelProvider",
158
+ "tokenPanel": "VWh0dG_tokenPanel",
159
+ "peakAlertPeak": "VWh0dG_peakAlertPeak",
160
+ "pricingTable": "VWh0dG_pricingTable",
161
+ "kpiTile": "VWh0dG_kpiTile",
162
+ "heroMain": "VWh0dG_heroMain",
163
+ "roundsBarWrap": "VWh0dG_roundsBarWrap",
164
+ "heroGaugeLabel": "VWh0dG_heroGaugeLabel",
165
+ "exportBar": "VWh0dG_exportBar",
166
+ "liveQuotaCrit": "VWh0dG_liveQuotaCrit",
167
+ "heroGaugeCenter": "VWh0dG_heroGaugeCenter",
168
+ "shareLegend": "VWh0dG_shareLegend",
169
+ "chartStack": "VWh0dG_chartStack",
170
+ "budgetOverPulse": "VWh0dG_budgetOverPulse",
171
+ "chartLegend": "VWh0dG_chartLegend",
172
+ "dashboardSubtitle": "VWh0dG_dashboardSubtitle",
173
+ "currencyButton": "VWh0dG_currencyButton",
174
+ "roundsFlagMark": "VWh0dG_roundsFlagMark",
175
+ "modelName": "VWh0dG_modelName",
176
+ "triggerSub": "VWh0dG_triggerSub",
177
+ "emptyRow": "VWh0dG_emptyRow",
178
+ "triggerPopLabel": "VWh0dG_triggerPopLabel",
179
+ "bandPrice": "VWh0dG_bandPrice",
180
+ "peakAlertPanelBody": "VWh0dG_peakAlertPanelBody",
181
+ "heroReadout": "VWh0dG_heroReadout",
182
+ "tabNav": "VWh0dG_tabNav",
183
+ "peakAlertPanelHead": "VWh0dG_peakAlertPanelHead",
184
+ "healthBad": "VWh0dG_healthBad",
185
+ "tokenModelPartOut": "VWh0dG_tokenModelPartOut",
186
+ "bucketStat": "VWh0dG_bucketStat",
187
+ "budgetValue": "VWh0dG_budgetValue",
188
+ "roundsBarLabel": "VWh0dG_roundsBarLabel",
189
+ "heroSideItem": "VWh0dG_heroSideItem",
190
+ "chartTooltipSwatch": "VWh0dG_chartTooltipSwatch",
191
+ "rounds": "VWh0dG_rounds",
192
+ "deltaDown": "VWh0dG_deltaDown",
193
+ "pluginInfoLabel": "VWh0dG_pluginInfoLabel",
194
+ "liveCostBar": "VWh0dG_liveCostBar",
195
+ "budgetHead": "VWh0dG_budgetHead",
196
+ "healthBadge": "VWh0dG_healthBadge",
233
197
  "switchKnob": "VWh0dG_switchKnob",
234
- "healthOk": "VWh0dG_healthOk",
235
- "liveCostSep": "VWh0dG_liveCostSep",
236
- "subscriptionStatus": "VWh0dG_subscriptionStatus",
237
- "triggerWrap": "VWh0dG_triggerWrap",
198
+ "chartGrid": "VWh0dG_chartGrid",
199
+ "heroGauge": "VWh0dG_heroGauge",
238
200
  "budgetLabel": "VWh0dG_budgetLabel",
239
- "chartDot": "VWh0dG_chartDot",
240
- "roundsBarColPeak": "VWh0dG_roundsBarColPeak",
241
- "heroLabel": "VWh0dG_heroLabel",
242
- "triggerPopRow": "VWh0dG_triggerPopRow",
201
+ "chartTooltipRow": "VWh0dG_chartTooltipRow",
202
+ "providerGroupMeta": "VWh0dG_providerGroupMeta",
203
+ "rateBadgeLive": "VWh0dG_rateBadgeLive",
204
+ "rangeToggle": "VWh0dG_rangeToggle",
205
+ "heatmap": "VWh0dG_heatmap",
206
+ "heroGaugeArcOver": "VWh0dG_heroGaugeArcOver",
207
+ "subscriptionAuto": "VWh0dG_subscriptionAuto",
208
+ "subscriptionWindow": "VWh0dG_subscriptionWindow",
209
+ "heatmapGrid": "VWh0dG_heatmapGrid",
210
+ "subscriptionName": "VWh0dG_subscriptionName",
211
+ "triggerMeta": "VWh0dG_triggerMeta",
212
+ "healthBadgeOk": "VWh0dG_healthBadgeOk",
213
+ "trendPanel": "VWh0dG_trendPanel",
214
+ "budget": "VWh0dG_budget",
215
+ "panelHint": "VWh0dG_panelHint",
216
+ "triggerSparkBar": "VWh0dG_triggerSparkBar",
217
+ "roundsAxis": "VWh0dG_roundsAxis",
218
+ "chartTooltip": "VWh0dG_chartTooltip",
219
+ "peakAlertIn": "VWh0dG_peakAlertIn",
220
+ "kpiGreen": "VWh0dG_kpiGreen",
221
+ "planTag": "VWh0dG_planTag",
222
+ "peakAlertOff": "VWh0dG_peakAlertOff",
223
+ "heroGaugeTrack": "VWh0dG_heroGaugeTrack",
224
+ "shareSegUser": "VWh0dG_shareSegUser",
225
+ "healthBadgeBad": "VWh0dG_healthBadgeBad",
226
+ "panelTitle": "VWh0dG_panelTitle",
227
+ "shareSegOff": "VWh0dG_shareSegOff",
228
+ "estimatedTag": "VWh0dG_estimatedTag",
243
229
  "tabButton": "VWh0dG_tabButton",
244
- "kpiLabel": "VWh0dG_kpiLabel",
245
- "na": "VWh0dG_na",
246
- "modelTableScroll": "VWh0dG_modelTableScroll",
247
- "peakAlertClose": "VWh0dG_peakAlertClose",
248
- "tabButtonActive": "VWh0dG_tabButtonActive",
249
- "roundsFlagBadge": "VWh0dG_roundsFlagBadge",
250
- "pluginInfoLabel": "VWh0dG_pluginInfoLabel",
251
- "exportButton": "VWh0dG_exportButton",
252
- "peakAlertTag": "VWh0dG_peakAlertTag",
253
- "panelHead": "VWh0dG_panelHead",
230
+ "subscriptionFillOver": "VWh0dG_subscriptionFillOver",
231
+ "heatmapHover": "VWh0dG_heatmapHover",
232
+ "switch": "VWh0dG_switch",
233
+ "triggerWrap": "VWh0dG_triggerWrap",
234
+ "settingsHead": "VWh0dG_settingsHead",
235
+ "budgetHint": "VWh0dG_budgetHint",
236
+ "subscriptionFill": "VWh0dG_subscriptionFill",
237
+ "dashboardHead": "VWh0dG_dashboardHead",
238
+ "uncataloguedTag": "VWh0dG_uncataloguedTag",
239
+ "pluginInfoRow": "VWh0dG_pluginInfoRow",
240
+ "pricingTip": "VWh0dG_pricingTip",
241
+ "chartEmpty": "VWh0dG_chartEmpty",
242
+ "bandTagOff": "VWh0dG_bandTagOff",
243
+ "providerGroupName": "VWh0dG_providerGroupName",
254
244
  "subscriptionReset": "VWh0dG_subscriptionReset",
255
- "shareItem": "VWh0dG_shareItem",
245
+ "peakAlertCorner": "VWh0dG_peakAlertCorner",
246
+ "subscriptionStatus": "VWh0dG_subscriptionStatus",
256
247
  "shareTrack": "VWh0dG_shareTrack",
257
- "roundsBarCol": "VWh0dG_roundsBarCol",
258
- "heroGaugeSvg": "VWh0dG_heroGaugeSvg",
259
- "heroGaugePct": "VWh0dG_heroGaugePct",
260
- "liveQuotaCrit": "VWh0dG_liveQuotaCrit",
261
- "peakAlert": "VWh0dG_peakAlert",
248
+ "switchOn": "VWh0dG_switchOn",
249
+ "liveCostItem": "VWh0dG_liveCostItem",
250
+ "dashboardRight": "VWh0dG_dashboardRight",
251
+ "subscriptionTier": "VWh0dG_subscriptionTier",
252
+ "providerGroupBalanceLabel": "VWh0dG_providerGroupBalanceLabel",
253
+ "shareItem": "VWh0dG_shareItem",
254
+ "tabPanelIn": "VWh0dG_tabPanelIn",
255
+ "liveQuotaWarn": "VWh0dG_liveQuotaWarn",
256
+ "roundsBars": "VWh0dG_roundsBars",
257
+ "triggerIcon": "VWh0dG_triggerIcon",
258
+ "shareSegTool": "VWh0dG_shareSegTool",
259
+ "modelTableScroll": "VWh0dG_modelTableScroll",
260
+ "settingsHint": "VWh0dG_settingsHint",
261
+ "tabPanel": "VWh0dG_tabPanel",
262
+ "triggerRow": "VWh0dG_triggerRow",
263
+ "tokenModelBar": "VWh0dG_tokenModelBar",
264
+ "budgetFillWarn": "VWh0dG_budgetFillWarn",
265
+ "numCol": "VWh0dG_numCol",
266
+ "roundsBarColPeak": "VWh0dG_roundsBarColPeak",
267
+ "shareSeg": "VWh0dG_shareSeg",
268
+ "providerGroup": "VWh0dG_providerGroup",
269
+ "hero": "VWh0dG_hero",
270
+ "triggerSpark": "VWh0dG_triggerSpark",
271
+ "budgetUnit": "VWh0dG_budgetUnit",
272
+ "heatmapYearGrid": "VWh0dG_heatmapYearGrid",
273
+ "heatmapYearCell": "VWh0dG_heatmapYearCell",
262
274
  "peakAlertText": "VWh0dG_peakAlertText",
263
- "peakAlertPreview": "VWh0dG_peakAlertPreview",
264
- "providerGroupMeta": "VWh0dG_providerGroupMeta",
265
- "roundsBarColOff": "VWh0dG_roundsBarColOff",
266
- "balanceDaysLow": "VWh0dG_balanceDaysLow",
267
- "shareSegAssistant": "VWh0dG_shareSegAssistant",
268
- "heroSide": "VWh0dG_heroSide",
269
- "peakAlertCenter": "VWh0dG_peakAlertCenter",
270
- "subscriptionCard": "VWh0dG_subscriptionCard",
271
- "chartCrosshair": "VWh0dG_chartCrosshair",
272
- "roundsBarWrap": "VWh0dG_roundsBarWrap",
273
- "triggerBody": "VWh0dG_triggerBody",
274
- "pluginInfoRow": "VWh0dG_pluginInfoRow",
275
- "heroMain": "VWh0dG_heroMain",
276
- "modelProvider": "VWh0dG_modelProvider",
277
- "exportLabel": "VWh0dG_exportLabel",
278
- "providerGroupName": "VWh0dG_providerGroupName",
279
- "bucketStatLabel": "VWh0dG_bucketStatLabel",
280
- "chartEmpty": "VWh0dG_chartEmpty",
281
- "currencyToggle": "VWh0dG_currencyToggle",
282
- "chartGrid": "VWh0dG_chartGrid",
275
+ "tabButtonActive": "VWh0dG_tabButtonActive",
276
+ "liveTierPeak": "VWh0dG_liveTierPeak",
277
+ "pluginInfoLink": "VWh0dG_pluginInfoLink",
278
+ "peakAlertNum": "VWh0dG_peakAlertNum",
279
+ "panelHead": "VWh0dG_panelHead",
280
+ "heatmapFooter": "VWh0dG_heatmapFooter",
281
+ "healthOk": "VWh0dG_healthOk",
282
+ "budgetInput": "VWh0dG_budgetInput",
283
+ "budgetTrack": "VWh0dG_budgetTrack",
284
+ "pricingToggle": "VWh0dG_pricingToggle",
285
+ "dashboardIn": "VWh0dG_dashboardIn",
286
+ "peakAlert": "VWh0dG_peakAlert",
287
+ "budgetFill": "VWh0dG_budgetFill",
288
+ "modelTable": "VWh0dG_modelTable",
283
289
  "subscriptionGrid": "VWh0dG_subscriptionGrid",
284
- "heroValue": "VWh0dG_heroValue",
285
- "modelName": "VWh0dG_modelName",
286
- "liveCostBar": "VWh0dG_liveCostBar",
287
- "peakAlertCorner": "VWh0dG_peakAlertCorner",
288
- "trendPanel": "VWh0dG_trendPanel",
289
- "heatmapCell": "VWh0dG_heatmapCell",
290
- "heroReadout": "VWh0dG_heroReadout"
290
+ "heroSideValue": "VWh0dG_heroSideValue",
291
+ "roundsBar": "VWh0dG_roundsBar",
292
+ "chartAxisLabel": "VWh0dG_chartAxisLabel",
293
+ "heroLabel": "VWh0dG_heroLabel",
294
+ "headTitleRow": "VWh0dG_headTitleRow",
295
+ "currencyToggle": "VWh0dG_currencyToggle",
296
+ "heroGaugeArc": "VWh0dG_heroGaugeArc"
291
297
  };
292
298
  //#endregion
293
299
  //#region src/client/plan-knowledge.ts
@@ -298,7 +304,11 @@ window.__ModuleLoader__.load({
298
304
  const PLAN_KNOWLEDGE = {
299
305
  "opencode-go": {
300
306
  type: "code",
301
- subscriptionCny: 70,
307
+ subscription: {
308
+ amount: 10,
309
+ currency: "USD",
310
+ period: "month"
311
+ },
302
312
  tier: {
303
313
  amount: 10,
304
314
  currency: "USD",
@@ -308,7 +318,11 @@ window.__ModuleLoader__.load({
308
318
  },
309
319
  opencode: {
310
320
  type: "code",
311
- subscriptionCny: 70,
321
+ subscription: {
322
+ amount: 10,
323
+ currency: "USD",
324
+ period: "month"
325
+ },
312
326
  tier: {
313
327
  amount: 10,
314
328
  currency: "USD",
@@ -316,62 +330,49 @@ window.__ModuleLoader__.load({
316
330
  label: "周额度 $30"
317
331
  }
318
332
  },
319
- "kimi-coding": {
320
- type: "code",
321
- subscriptionCny: 0
322
- },
323
- "zai-coding-cn": {
324
- type: "code",
325
- subscriptionCny: 0
326
- },
327
- "zai-coding": {
328
- type: "code",
329
- subscriptionCny: 0
330
- },
331
- "qwen-token-plan": {
332
- type: "code",
333
- subscriptionCny: 0
334
- },
335
- "qwen-token-plan-cn": {
336
- type: "code",
337
- subscriptionCny: 0
338
- },
339
- "xiaomi-token-plan-ams": {
340
- type: "code",
341
- subscriptionCny: 0
342
- },
343
- "xiaomi-token-plan-cn": {
344
- type: "code",
345
- subscriptionCny: 0
346
- },
347
- "xiaomi-token-plan-sgp": {
348
- type: "code",
349
- subscriptionCny: 0
350
- },
351
- "volcengine-token-plan": {
352
- type: "code",
353
- subscriptionCny: 0
354
- },
355
- "ark-token-plan": {
356
- type: "code",
357
- subscriptionCny: 0
358
- },
359
- "doubao-token-plan": {
360
- type: "code",
361
- subscriptionCny: 0
362
- },
363
- "minimax": {
364
- type: "code",
365
- subscriptionCny: 0
366
- },
367
- "minimax-token-plan": {
368
- type: "code",
369
- subscriptionCny: 0
370
- }
333
+ "kimi-coding": { type: "code" },
334
+ "zai-coding-cn": { type: "code" },
335
+ "zai-coding": { type: "code" },
336
+ "qwen-token-plan": { type: "code" },
337
+ "qwen-token-plan-cn": { type: "code" },
338
+ "xiaomi-token-plan-ams": { type: "code" },
339
+ "xiaomi-token-plan-cn": { type: "code" },
340
+ "xiaomi-token-plan-sgp": { type: "code" },
341
+ "volcengine-token-plan": { type: "code" },
342
+ "ark-token-plan": { type: "code" },
343
+ "doubao-token-plan": { type: "code" },
344
+ "minimax": { type: "code" },
345
+ "minimax-token-plan": { type: "code" }
346
+ };
347
+ /**
348
+ * 订阅/plan provider id 变体 → PLAN_KNOWLEDGE 规范键(引用 dsh-spend 的别名归一化)。
349
+ * 部署配置的订阅 provider id 写法不一(glm/zhipu/bigmodel、ark/volcengine、
350
+ * kimi/moonshot、xiaomi…),先归一化再匹配,提升"自动识别"覆盖率。
351
+ * 注意:裸 qwen/dashscope/tongyi 等是按量 API(token 计费)而非订阅,不归一到
352
+ * 订阅键——只有显式 token-plan 后缀才由 SUBSCRIPTION_ID_RE 判定为订阅。
353
+ */
354
+ const PLAN_PROVIDER_ALIASES = {
355
+ "glm": "zai-coding-cn",
356
+ "bigmodel": "zai-coding-cn",
357
+ "zhipu": "zai-coding-cn",
358
+ "zhipuai": "zai-coding-cn",
359
+ "zai": "zai-coding",
360
+ "ark": "volcengine-token-plan",
361
+ "volcengine": "volcengine-token-plan",
362
+ "doubao": "doubao-token-plan",
363
+ "moonshot": "kimi-coding",
364
+ "kimi": "kimi-coding",
365
+ "xiaomi": "xiaomi-token-plan-cn",
366
+ "opencode": "opencode-go"
371
367
  };
368
+ /** 归一化订阅 provider id:别名命中则映射到规范键,否则原样返回。 */
369
+ function normalizePlanProvider(providerId) {
370
+ if (providerId === "") return providerId;
371
+ return PLAN_PROVIDER_ALIASES[providerId] ?? providerId;
372
+ }
372
373
  /** 自动识别的档位月费与周期额度口径(订阅卡片展示);无档位知识返回 undefined。 */
373
374
  function tierInfoOf(providerId) {
374
- const entry = PLAN_KNOWLEDGE[providerId];
375
+ const entry = PLAN_KNOWLEDGE[normalizePlanProvider(providerId)];
375
376
  return entry?.type === "code" ? entry.tier : void 0;
376
377
  }
377
378
  const FALLBACK_RATES = [
@@ -1359,9 +1360,9 @@ window.__ModuleLoader__.load({
1359
1360
  * surface stays self-contained and offline.
1360
1361
  */
1361
1362
  /** Fixed viewBox; the SVG scales to its container. */
1362
- const W$1 = 680;
1363
- const H$1 = 220;
1364
- const PAD$1 = {
1363
+ const W$2 = 680;
1364
+ const H$2 = 220;
1365
+ const PAD$2 = {
1365
1366
  top: 18,
1366
1367
  right: 40,
1367
1368
  bottom: 26,
@@ -1373,7 +1374,7 @@ window.__ModuleLoader__.load({
1373
1374
  return `${Number(month)}/${Number(day)}`;
1374
1375
  }
1375
1376
  /** Compact tick label for the calls axis: `1.2K` / `3.4M`. */
1376
- function shortNumber(value) {
1377
+ function shortNumber$1(value) {
1377
1378
  if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
1378
1379
  if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`;
1379
1380
  return String(Math.round(value));
@@ -1403,16 +1404,16 @@ window.__ModuleLoader__.load({
1403
1404
  const layout = (0, react.useMemo)(() => {
1404
1405
  const n = data.length;
1405
1406
  if (n === 0) return null;
1406
- const plotW = W$1 - PAD$1.left - PAD$1.right;
1407
- const plotH = H$1 - PAD$1.top - PAD$1.bottom;
1407
+ const plotW = W$2 - PAD$2.left - PAD$2.right;
1408
+ const plotH = H$2 - PAD$2.top - PAD$2.bottom;
1408
1409
  const inner = (i) => {
1409
- if (n === 1) return PAD$1.left + plotW / 2;
1410
- return PAD$1.left + plotW * i / (n - 1);
1410
+ if (n === 1) return PAD$2.left + plotW / 2;
1411
+ return PAD$2.left + plotW * i / (n - 1);
1411
1412
  };
1412
1413
  const maxCost = Math.max(...data.map((d) => Math.max(d.cost, Object.values(d.byModel ?? {}).reduce((sum, v) => sum + v, 0))), 1e-4);
1413
- const yCost = (value) => PAD$1.top + plotH - value / maxCost * plotH;
1414
+ const yCost = (value) => PAD$2.top + plotH - value / maxCost * plotH;
1414
1415
  const maxCalls = Math.max(...data.map((d) => d.calls), 1);
1415
- const yCalls = (value) => PAD$1.top + plotH - value / maxCalls * plotH;
1416
+ const yCalls = (value) => PAD$2.top + plotH - value / maxCalls * plotH;
1416
1417
  const groupW = plotW / n;
1417
1418
  const barW = Math.min(18, groupW * .6);
1418
1419
  return {
@@ -1481,7 +1482,7 @@ window.__ModuleLoader__.load({
1481
1482
  className: UsageBilling_module_css_default.chartWrap,
1482
1483
  children: [
1483
1484
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1484
- viewBox: `0 0 ${W$1} ${H$1}`,
1485
+ viewBox: `0 0 ${W$2} ${H$2}`,
1485
1486
  className: UsageBilling_module_css_default.chartSvg,
1486
1487
  role: "img",
1487
1488
  "aria-label": "Daily cost by model and total calls",
@@ -1490,7 +1491,7 @@ window.__ModuleLoader__.load({
1490
1491
  },
1491
1492
  onMouseMove: (e) => {
1492
1493
  const rect = e.currentTarget.getBoundingClientRect();
1493
- const ratio = ((e.clientX - rect.left) / rect.width * W$1 - PAD$1.left) / plotW;
1494
+ const ratio = ((e.clientX - rect.left) / rect.width * W$2 - PAD$2.left) / plotW;
1494
1495
  const index = Math.round(ratio * (n - 1));
1495
1496
  setHover(Math.min(Math.max(index, 0), n - 1));
1496
1497
  },
@@ -1498,13 +1499,13 @@ window.__ModuleLoader__.load({
1498
1499
  costTicks.map((value, idx) => {
1499
1500
  const y = yCost(value);
1500
1501
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("line", {
1501
- x1: PAD$1.left,
1502
- x2: W$1 - PAD$1.right,
1502
+ x1: PAD$2.left,
1503
+ x2: W$2 - PAD$2.right,
1503
1504
  y1: y,
1504
1505
  y2: y,
1505
1506
  className: UsageBilling_module_css_default.chartGrid
1506
1507
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
1507
- x: PAD$1.left - 8,
1508
+ x: PAD$2.left - 8,
1508
1509
  y: y + 3,
1509
1510
  textAnchor: "end",
1510
1511
  className: UsageBilling_module_css_default.chartAxisLabel,
@@ -1528,11 +1529,11 @@ window.__ModuleLoader__.load({
1528
1529
  callsTicks.map((value, idx) => {
1529
1530
  const y = yCalls(value);
1530
1531
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
1531
- x: W$1 - PAD$1.right + 8,
1532
+ x: W$2 - PAD$2.right + 8,
1532
1533
  y: y + 3,
1533
1534
  textAnchor: "start",
1534
1535
  className: UsageBilling_module_css_default.chartAxisLabel,
1535
- children: shortNumber(value)
1536
+ children: shortNumber$1(value)
1536
1537
  }, `calls-${idx}`);
1537
1538
  }),
1538
1539
  indices.map((i) => {
@@ -1540,7 +1541,7 @@ window.__ModuleLoader__.load({
1540
1541
  if (point === void 0) return null;
1541
1542
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
1542
1543
  x: inner(i),
1543
- y: H$1 - 6,
1544
+ y: H$2 - 6,
1544
1545
  textAnchor: "middle",
1545
1546
  className: UsageBilling_module_css_default.chartAxisLabel,
1546
1547
  children: shortDate(point.date)
@@ -1549,8 +1550,8 @@ window.__ModuleLoader__.load({
1549
1550
  hover !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("line", {
1550
1551
  x1: inner(hover),
1551
1552
  x2: inner(hover),
1552
- y1: PAD$1.top,
1553
- y2: PAD$1.top + plotH,
1553
+ y1: PAD$2.top,
1554
+ y2: PAD$2.top + plotH,
1554
1555
  className: UsageBilling_module_css_default.chartCrosshair
1555
1556
  })
1556
1557
  ]
@@ -1558,8 +1559,8 @@ window.__ModuleLoader__.load({
1558
1559
  activePoint !== void 0 && hover !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1559
1560
  className: UsageBilling_module_css_default.chartTooltip,
1560
1561
  style: {
1561
- left: `${inner(hover) / W$1 * 100}%`,
1562
- top: `${yCost(activePoint.cost) / H$1 * 100}%`
1562
+ left: `${inner(hover) / W$2 * 100}%`,
1563
+ top: `${yCost(activePoint.cost) / H$2 * 100}%`
1563
1564
  },
1564
1565
  children: [
1565
1566
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -1619,9 +1620,9 @@ window.__ModuleLoader__.load({
1619
1620
  * renders an empty state; the panel never fabricates samples.
1620
1621
  */
1621
1622
  /** Fixed viewBox for the hourly curve; the SVG scales to its container. */
1622
- const W = 680;
1623
- const H = 180;
1624
- const PAD = {
1623
+ const W$1 = 680;
1624
+ const H$1 = 180;
1625
+ const PAD$1 = {
1625
1626
  top: 14,
1626
1627
  right: 42,
1627
1628
  bottom: 22,
@@ -1673,13 +1674,13 @@ window.__ModuleLoader__.load({
1673
1674
  const points = perf === void 0 ? [] : sortHourPoints(perf.byHour);
1674
1675
  if (points.length === 0) return null;
1675
1676
  const n = points.length;
1676
- const plotW = W - PAD.left - PAD.right;
1677
- const plotH = H - PAD.top - PAD.bottom;
1678
- const inner = (i) => n === 1 ? PAD.left + plotW / 2 : PAD.left + plotW * i / (n - 1);
1677
+ const plotW = W$1 - PAD$1.left - PAD$1.right;
1678
+ const plotH = H$1 - PAD$1.top - PAD$1.bottom;
1679
+ const inner = (i) => n === 1 ? PAD$1.left + plotW / 2 : PAD$1.left + plotW * i / (n - 1);
1679
1680
  const maxTtft = Math.max(...points.map((p) => p.ttftMs), 1);
1680
1681
  const maxTps = Math.max(...points.map((p) => p.tps ?? 0), 1);
1681
- const yTtft = (v) => PAD.top + plotH - v / maxTtft * plotH;
1682
- const yTps = (v) => PAD.top + plotH - v / maxTps * plotH;
1682
+ const yTtft = (v) => PAD$1.top + plotH - v / maxTtft * plotH;
1683
+ const yTps = (v) => PAD$1.top + plotH - v / maxTps * plotH;
1683
1684
  const ttftPath = points.map((p, i) => `${i === 0 ? "M" : "L"}${inner(i)} ${yTtft(p.ttftMs)}`).join(" ");
1684
1685
  const tpsPath = points.some((p) => p.tps !== void 0) ? points.map((p, i) => `${i === 0 ? "M" : "L"}${inner(i)} ${yTps(p.tps ?? 0)}`).join(" ") : "";
1685
1686
  const step = Math.max(1, Math.ceil(n / 8));
@@ -1795,7 +1796,7 @@ window.__ModuleLoader__.load({
1795
1796
  className: UsageBilling_module_css_default.chartWrap,
1796
1797
  "data-testid": "billing-perf-hour",
1797
1798
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1798
- viewBox: `0 0 ${W} ${H}`,
1799
+ viewBox: `0 0 ${W$1} ${H$1}`,
1799
1800
  className: UsageBilling_module_css_default.chartSvg,
1800
1801
  role: "img",
1801
1802
  "aria-label": "Hourly TTFT and generation speed by model",
@@ -1803,13 +1804,13 @@ window.__ModuleLoader__.load({
1803
1804
  hourLayout.ttftTicks.map((value, idx) => {
1804
1805
  const y = hourLayout.yTtft(value);
1805
1806
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("line", {
1806
- x1: PAD.left,
1807
- x2: W - PAD.right,
1807
+ x1: PAD$1.left,
1808
+ x2: W$1 - PAD$1.right,
1808
1809
  y1: y,
1809
1810
  y2: y,
1810
1811
  className: UsageBilling_module_css_default.chartGrid
1811
1812
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
1812
- x: PAD.left - 8,
1813
+ x: PAD$1.left - 8,
1813
1814
  y: y + 3,
1814
1815
  textAnchor: "end",
1815
1816
  className: UsageBilling_module_css_default.chartAxisLabel,
@@ -1835,15 +1836,15 @@ window.__ModuleLoader__.load({
1835
1836
  if (point === void 0) return null;
1836
1837
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
1837
1838
  x: hourLayout.inner(i),
1838
- y: H - 6,
1839
+ y: H$1 - 6,
1839
1840
  textAnchor: "middle",
1840
1841
  className: UsageBilling_module_css_default.chartAxisLabel,
1841
1842
  children: shortHour(point.key)
1842
1843
  }, point.key);
1843
1844
  }),
1844
1845
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("text", {
1845
- x: W - PAD.right + 8,
1846
- y: PAD.top + 4,
1846
+ x: W$1 - PAD$1.right + 8,
1847
+ y: PAD$1.top + 4,
1847
1848
  textAnchor: "start",
1848
1849
  className: UsageBilling_module_css_default.chartAxisLabel,
1849
1850
  children: [
@@ -1939,66 +1940,564 @@ window.__ModuleLoader__.load({
1939
1940
  className: UsageBilling_module_css_default.pluginInfoLabel,
1940
1941
  children: t("billing.pluginVersion")
1941
1942
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1942
- className: UsageBilling_module_css_default.pluginInfoValue,
1943
- children: version === void 0 ? "—" : `v${version}`
1943
+ className: UsageBilling_module_css_default.pluginInfoValue,
1944
+ children: version === void 0 ? "—" : `v${version}`
1945
+ })]
1946
+ }),
1947
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1948
+ className: UsageBilling_module_css_default.pluginInfoRow,
1949
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1950
+ className: UsageBilling_module_css_default.pluginInfoLabel,
1951
+ children: t("billing.pluginAuthor")
1952
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
1953
+ className: UsageBilling_module_css_default.pluginInfoLink,
1954
+ href: `https://github.com/${PLUGIN_AUTHOR_HANDLE}`,
1955
+ target: "_blank",
1956
+ rel: "noreferrer",
1957
+ children: [
1958
+ PLUGIN_AUTHOR_NAME,
1959
+ " (",
1960
+ PLUGIN_AUTHOR_HANDLE,
1961
+ ")"
1962
+ ]
1963
+ })]
1964
+ }),
1965
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1966
+ className: UsageBilling_module_css_default.pluginInfoRow,
1967
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1968
+ className: UsageBilling_module_css_default.pluginInfoLabel,
1969
+ children: t("billing.pluginRepository")
1970
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1971
+ className: UsageBilling_module_css_default.pluginInfoLink,
1972
+ href: PLUGIN_REPOSITORY,
1973
+ target: "_blank",
1974
+ rel: "noreferrer",
1975
+ children: PLUGIN_REPOSITORY
1976
+ })]
1977
+ }),
1978
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1979
+ className: UsageBilling_module_css_default.pluginInfoRow,
1980
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1981
+ className: UsageBilling_module_css_default.pluginInfoLabel,
1982
+ children: t("billing.pluginNpm")
1983
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1984
+ className: UsageBilling_module_css_default.pluginInfoLink,
1985
+ href: PLUGIN_NPM_URL,
1986
+ target: "_blank",
1987
+ rel: "noreferrer",
1988
+ children: PLUGIN_NAME
1989
+ })]
1990
+ }),
1991
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1992
+ className: UsageBilling_module_css_default.pluginInfoRow,
1993
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1994
+ className: UsageBilling_module_css_default.pluginInfoLabel,
1995
+ children: t("billing.pluginLicense")
1996
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1997
+ className: UsageBilling_module_css_default.pluginInfoValue,
1998
+ children: "MIT"
1999
+ })]
2000
+ })
2001
+ ]
2002
+ })]
2003
+ });
2004
+ }
2005
+ //#endregion
2006
+ //#region src/client/TokenPanel.tsx
2007
+ /**
2008
+ * TokenPanel: 「Token」分区——把 token 从费用里独立出来洞察。
2009
+ * 三个板块 + 导出,全部由 `UsageStats` 的 byDay/byModel/total 派生,服务端零改动:
2010
+ * 1. 每日 Token 堆叠趋势(未命中输入 / 缓存命中 / 输出[含 reasoning]),7/30 天切换;
2011
+ * 2. 模型 Token 总量排行 + 占比;
2012
+ * 3. Token 结构 KPI(缓存命中率 / reasoning 占比 / 输入:输出比 / 峰值日)。
2013
+ */
2014
+ /** 本地时区 `YYYY-MM-DD`(与服务端 dayStamp 一致)。 */
2015
+ function localStamp(time = Date.now()) {
2016
+ const d = new Date(time);
2017
+ const p = (n) => String(n).padStart(2, "0");
2018
+ return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`;
2019
+ }
2020
+ /** 短数字刻度:`1.2M` / `3.4K`。 */
2021
+ function shortNumber(v) {
2022
+ if (v >= 1e6) return `${(v / 1e6).toFixed(1)}M`;
2023
+ if (v >= 1e3) return `${(v / 1e3).toFixed(1)}K`;
2024
+ return String(Math.round(v));
2025
+ }
2026
+ const W = 680;
2027
+ const H = 200;
2028
+ const PAD = {
2029
+ top: 14,
2030
+ right: 18,
2031
+ bottom: 22,
2032
+ left: 46
2033
+ };
2034
+ const MISS_COLOR = "var(--dsw-static-blue-500)";
2035
+ const HIT_COLOR = "var(--dsw-static-cyan-500)";
2036
+ const OUTPUT_COLOR = "var(--dsw-static-amber-500)";
2037
+ /** 导出按日 token CSV。 */
2038
+ function tokenDayCsv(days) {
2039
+ return ["date,missInput,cacheHit,output,reasoning,total", ...days.map((d) => `${d.date},${d.miss},${d.hit},${d.output},${d.reasoning},${d.miss + d.hit + d.output}`)].join("\n");
2040
+ }
2041
+ /**
2042
+ * Token 洞察面板。
2043
+ * @param props.stats - usage-stats 文档(byDay/byModel/total)。
2044
+ * @param props.trendDays - 每日 token 窗口(7/30 天)。
2045
+ * @param props.onTrendDays - 切换趋势窗口。
2046
+ */
2047
+ function TokenPanel(props) {
2048
+ const { stats, currency: _currency, trendDays, onTrendDays, t } = props;
2049
+ const { byDay, byModel, total } = stats;
2050
+ const days = (0, react.useMemo)(() => {
2051
+ const out = [];
2052
+ for (let offset = trendDays - 1; offset >= 0; offset -= 1) {
2053
+ const d = /* @__PURE__ */ new Date();
2054
+ d.setDate(d.getDate() - offset);
2055
+ const date = localStamp(d.getTime());
2056
+ const day = byDay[date];
2057
+ out.push({
2058
+ date,
2059
+ miss: day?.cacheMiss ?? 0,
2060
+ hit: day?.cacheHit ?? 0,
2061
+ output: day?.output ?? 0,
2062
+ reasoning: day?.reasoning ?? 0
2063
+ });
2064
+ }
2065
+ return out;
2066
+ }, [byDay, trendDays]);
2067
+ const models = (0, react.useMemo)(() => {
2068
+ let grand = 0;
2069
+ return Object.entries(byModel).filter(([, d]) => d.calls > 0).map(([key, d]) => {
2070
+ const totalTokens = d.input + d.output;
2071
+ grand += totalTokens;
2072
+ const hitMiss = d.cacheHit + d.cacheMiss;
2073
+ return {
2074
+ key,
2075
+ name: modelOf(key).name,
2076
+ input: d.input,
2077
+ output: d.output,
2078
+ reasoning: d.reasoning ?? 0,
2079
+ calls: d.calls,
2080
+ cacheHit: d.cacheHit,
2081
+ cacheMiss: d.cacheMiss,
2082
+ cacheHitRate: hitMiss > 0 ? d.cacheHit / hitMiss * 100 : 0,
2083
+ total: totalTokens,
2084
+ share: 0
2085
+ };
2086
+ }).sort((a, b) => b.total - a.total).map((r) => ({
2087
+ ...r,
2088
+ share: grand > 0 ? r.total / grand : 0
2089
+ }));
2090
+ }, [byModel]);
2091
+ const kpis = (0, react.useMemo)(() => {
2092
+ const hit = total.cacheHit ?? 0;
2093
+ const miss = total.cacheMiss ?? 0;
2094
+ const input = total.input ?? 0;
2095
+ const output = total.output ?? 0;
2096
+ const reasoning = total.reasoning ?? 0;
2097
+ const hitMiss = hit + miss;
2098
+ const cacheHitRate = hitMiss > 0 ? hit / hitMiss * 100 : 0;
2099
+ const reasoningPct = output > 0 ? reasoning / output * 100 : 0;
2100
+ const io = output > 0 ? input / output : 0;
2101
+ let peak;
2102
+ for (const d of days) {
2103
+ const t2 = d.miss + d.hit + d.output;
2104
+ if (peak === void 0 || t2 > peak.miss + peak.hit + peak.output) peak = d;
2105
+ }
2106
+ return {
2107
+ cacheHitRate,
2108
+ reasoningPct,
2109
+ io,
2110
+ peak,
2111
+ hit,
2112
+ miss,
2113
+ input,
2114
+ output,
2115
+ reasoning
2116
+ };
2117
+ }, [total, days]);
2118
+ const chart = (0, react.useMemo)(() => {
2119
+ const n = days.length;
2120
+ if (n === 0) return null;
2121
+ const plotW = W - PAD.left - PAD.right;
2122
+ const plotH = H - PAD.top - PAD.bottom;
2123
+ const max = Math.max(...days.map((d) => d.miss + d.hit + d.output), 1);
2124
+ const y = (v) => PAD.top + plotH - v / max * plotH;
2125
+ const groupW = plotW / n;
2126
+ const barW = Math.min(20, groupW * .6);
2127
+ const inner = (i) => n === 1 ? PAD.left + plotW / 2 : PAD.left + plotW * i / (n - 1);
2128
+ const step = Math.max(1, Math.ceil(n / 8));
2129
+ const indices = [];
2130
+ for (let i = 0; i < n; i += step) indices.push(i);
2131
+ if (n > 0 && indices[indices.length - 1] !== n - 1) indices.push(n - 1);
2132
+ return {
2133
+ n,
2134
+ plotW,
2135
+ plotH,
2136
+ max,
2137
+ y,
2138
+ barW,
2139
+ inner,
2140
+ indices
2141
+ };
2142
+ }, [days]);
2143
+ const exportTokenCsv = () => {
2144
+ const blob = new Blob([tokenDayCsv(days)], { type: "text/csv" });
2145
+ const a = document.createElement("a");
2146
+ a.href = URL.createObjectURL(blob);
2147
+ a.download = `token-daily-${localStamp()}.csv`;
2148
+ a.click();
2149
+ URL.revokeObjectURL(a.href);
2150
+ };
2151
+ const exportTokenJson = () => {
2152
+ const blob = new Blob([JSON.stringify({
2153
+ days,
2154
+ models,
2155
+ total
2156
+ }, null, 2)], { type: "application/json" });
2157
+ const a = document.createElement("a");
2158
+ a.href = URL.createObjectURL(blob);
2159
+ a.download = `token-${localStamp()}.json`;
2160
+ a.click();
2161
+ URL.revokeObjectURL(a.href);
2162
+ };
2163
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2164
+ className: UsageBilling_module_css_default.tokenPanel,
2165
+ "data-testid": "billing-token-panel",
2166
+ children: [
2167
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2168
+ className: UsageBilling_module_css_default.exportBar,
2169
+ role: "group",
2170
+ "aria-label": t("billing.tokenExport"),
2171
+ children: [
2172
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2173
+ className: UsageBilling_module_css_default.exportLabel,
2174
+ children: t("billing.export")
2175
+ }),
2176
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2177
+ type: "button",
2178
+ className: UsageBilling_module_css_default.exportButton,
2179
+ "data-testid": "billing-token-export-csv",
2180
+ onClick: exportTokenCsv,
2181
+ children: t("billing.tokenExportCsv")
2182
+ }),
2183
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2184
+ type: "button",
2185
+ className: UsageBilling_module_css_default.exportButton,
2186
+ "data-testid": "billing-token-export-json",
2187
+ onClick: exportTokenJson,
2188
+ children: t("billing.exportJson")
2189
+ })
2190
+ ]
2191
+ }),
2192
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2193
+ className: UsageBilling_module_css_default.kpiGrid,
2194
+ "data-testid": "billing-token-kpis",
2195
+ children: [
2196
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2197
+ className: UsageBilling_module_css_default.kpiTile,
2198
+ children: [
2199
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2200
+ className: UsageBilling_module_css_default.kpiLabel,
2201
+ children: t("billing.tokenCacheHitRate")
2202
+ }),
2203
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2204
+ className: UsageBilling_module_css_default.kpiValue,
2205
+ children: [kpis.cacheHitRate.toFixed(1), "%"]
2206
+ }),
2207
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2208
+ className: UsageBilling_module_css_default.kpiDetail,
2209
+ children: [
2210
+ formatTokens(kpis.hit),
2211
+ " / ",
2212
+ formatTokens(kpis.hit + kpis.miss)
2213
+ ]
2214
+ })
2215
+ ]
2216
+ }),
2217
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2218
+ className: UsageBilling_module_css_default.kpiTile,
2219
+ children: [
2220
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2221
+ className: UsageBilling_module_css_default.kpiLabel,
2222
+ children: t("billing.tokenReasoningShare")
2223
+ }),
2224
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2225
+ className: UsageBilling_module_css_default.kpiValue,
2226
+ children: [kpis.reasoningPct.toFixed(1), "%"]
2227
+ }),
2228
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2229
+ className: UsageBilling_module_css_default.kpiDetail,
2230
+ children: formatTokens(kpis.reasoning)
2231
+ })
2232
+ ]
2233
+ }),
2234
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2235
+ className: UsageBilling_module_css_default.kpiTile,
2236
+ children: [
2237
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2238
+ className: UsageBilling_module_css_default.kpiLabel,
2239
+ children: t("billing.tokenIo")
2240
+ }),
2241
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2242
+ className: UsageBilling_module_css_default.kpiValue,
2243
+ children: kpis.io.toFixed(2)
2244
+ }),
2245
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2246
+ className: UsageBilling_module_css_default.kpiDetail,
2247
+ children: [
2248
+ formatTokens(kpis.input),
2249
+ " / ",
2250
+ formatTokens(kpis.output)
2251
+ ]
2252
+ })
2253
+ ]
2254
+ }),
2255
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2256
+ className: UsageBilling_module_css_default.kpiTile,
2257
+ children: [
2258
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2259
+ className: UsageBilling_module_css_default.kpiLabel,
2260
+ children: t("billing.tokenPeak")
2261
+ }),
2262
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2263
+ className: UsageBilling_module_css_default.kpiValue,
2264
+ children: kpis.peak === void 0 ? "—" : shortNumber(kpis.peak.miss + kpis.peak.hit + kpis.peak.output)
2265
+ }),
2266
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2267
+ className: UsageBilling_module_css_default.kpiDetail,
2268
+ children: kpis.peak?.date ?? "—"
2269
+ })
2270
+ ]
2271
+ })
2272
+ ]
2273
+ }),
2274
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2275
+ className: UsageBilling_module_css_default.panel,
2276
+ "data-testid": "billing-token-daily",
2277
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2278
+ className: UsageBilling_module_css_default.panelHead,
2279
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
2280
+ className: UsageBilling_module_css_default.panelTitle,
2281
+ children: t("billing.tokenDaily")
2282
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2283
+ className: UsageBilling_module_css_default.rangeToggle,
2284
+ role: "group",
2285
+ "aria-label": t("billing.tokenDaily"),
2286
+ children: [7, 30].map((d) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2287
+ type: "button",
2288
+ className: clsx(UsageBilling_module_css_default.rangeButton, trendDays === d && UsageBilling_module_css_default.rangeButtonActive),
2289
+ "aria-pressed": trendDays === d,
2290
+ onClick: () => {
2291
+ onTrendDays(d);
2292
+ },
2293
+ "data-testid": `billing-token-${d}d`,
2294
+ children: d === 7 ? t("billing.trend7d") : t("billing.trend30d")
2295
+ }, d))
1944
2296
  })]
1945
- }),
1946
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1947
- className: UsageBilling_module_css_default.pluginInfoRow,
1948
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1949
- className: UsageBilling_module_css_default.pluginInfoLabel,
1950
- children: t("billing.pluginAuthor")
1951
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
1952
- className: UsageBilling_module_css_default.pluginInfoLink,
1953
- href: `https://github.com/${PLUGIN_AUTHOR_HANDLE}`,
1954
- target: "_blank",
1955
- rel: "noreferrer",
2297
+ }), chart === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2298
+ className: UsageBilling_module_css_default.chartEmpty,
2299
+ children: t("billing.trendEmpty")
2300
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2301
+ className: UsageBilling_module_css_default.chartWrap,
2302
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
2303
+ viewBox: `0 0 ${W} ${H}`,
2304
+ className: UsageBilling_module_css_default.chartSvg,
2305
+ role: "img",
2306
+ "aria-label": t("billing.tokenDaily"),
1956
2307
  children: [
1957
- PLUGIN_AUTHOR_NAME,
1958
- " (",
1959
- PLUGIN_AUTHOR_HANDLE,
1960
- ")"
2308
+ [
2309
+ 0,
2310
+ .5,
2311
+ 1
2312
+ ].map((f) => {
2313
+ const v = chart.max * f;
2314
+ const yy = chart.y(v);
2315
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("line", {
2316
+ x1: PAD.left,
2317
+ x2: W - PAD.right,
2318
+ y1: yy,
2319
+ y2: yy,
2320
+ className: UsageBilling_module_css_default.chartGrid
2321
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
2322
+ x: PAD.left - 8,
2323
+ y: yy + 3,
2324
+ textAnchor: "end",
2325
+ className: UsageBilling_module_css_default.chartAxisLabel,
2326
+ children: shortNumber(v)
2327
+ })] }, f);
2328
+ }),
2329
+ days.map((d, i) => {
2330
+ const x = chart.inner(i) - chart.barW / 2;
2331
+ const baseY = chart.y(0);
2332
+ const yMiss = chart.y(d.miss);
2333
+ const yHit = chart.y(d.miss + d.hit);
2334
+ const yOut = chart.y(d.miss + d.hit + d.output);
2335
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", { children: [
2336
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
2337
+ x,
2338
+ y: yMiss,
2339
+ width: chart.barW,
2340
+ height: baseY - yMiss,
2341
+ fill: MISS_COLOR
2342
+ }),
2343
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
2344
+ x,
2345
+ y: yHit,
2346
+ width: chart.barW,
2347
+ height: yMiss - yHit,
2348
+ fill: HIT_COLOR
2349
+ }),
2350
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
2351
+ x,
2352
+ y: yOut,
2353
+ width: chart.barW,
2354
+ height: yHit - yOut,
2355
+ fill: OUTPUT_COLOR
2356
+ })
2357
+ ] }, d.date);
2358
+ }),
2359
+ chart.indices.map((i) => {
2360
+ const d = days[i];
2361
+ if (d === void 0) return null;
2362
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
2363
+ x: chart.inner(i),
2364
+ y: H - 6,
2365
+ textAnchor: "middle",
2366
+ className: UsageBilling_module_css_default.chartAxisLabel,
2367
+ children: d.date.slice(5)
2368
+ }, d.date);
2369
+ })
2370
+ ]
2371
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2372
+ className: UsageBilling_module_css_default.chartLegend,
2373
+ children: [
2374
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2375
+ className: UsageBilling_module_css_default.chartTooltipSwatch,
2376
+ style: { background: MISS_COLOR }
2377
+ }), t("billing.tokenMiss")] }),
2378
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2379
+ className: UsageBilling_module_css_default.chartTooltipSwatch,
2380
+ style: { background: HIT_COLOR }
2381
+ }), t("billing.tokenHit")] }),
2382
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2383
+ className: UsageBilling_module_css_default.chartTooltipSwatch,
2384
+ style: { background: OUTPUT_COLOR }
2385
+ }), t("billing.tokenOutput")] })
1961
2386
  ]
1962
2387
  })]
1963
- }),
1964
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1965
- className: UsageBilling_module_css_default.pluginInfoRow,
1966
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1967
- className: UsageBilling_module_css_default.pluginInfoLabel,
1968
- children: t("billing.pluginRepository")
1969
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1970
- className: UsageBilling_module_css_default.pluginInfoLink,
1971
- href: PLUGIN_REPOSITORY,
1972
- target: "_blank",
1973
- rel: "noreferrer",
1974
- children: PLUGIN_REPOSITORY
1975
- })]
1976
- }),
1977
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1978
- className: UsageBilling_module_css_default.pluginInfoRow,
1979
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1980
- className: UsageBilling_module_css_default.pluginInfoLabel,
1981
- children: t("billing.pluginNpm")
1982
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1983
- className: UsageBilling_module_css_default.pluginInfoLink,
1984
- href: PLUGIN_NPM_URL,
1985
- target: "_blank",
1986
- rel: "noreferrer",
1987
- children: PLUGIN_NAME
1988
- })]
1989
- }),
1990
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1991
- className: UsageBilling_module_css_default.pluginInfoRow,
1992
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1993
- className: UsageBilling_module_css_default.pluginInfoLabel,
1994
- children: t("billing.pluginLicense")
1995
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1996
- className: UsageBilling_module_css_default.pluginInfoValue,
1997
- children: "MIT"
1998
- })]
1999
- })
2000
- ]
2001
- })]
2388
+ })]
2389
+ }),
2390
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2391
+ className: UsageBilling_module_css_default.panel,
2392
+ "data-testid": "billing-token-models",
2393
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2394
+ className: UsageBilling_module_css_default.panelHead,
2395
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
2396
+ className: UsageBilling_module_css_default.panelTitle,
2397
+ children: t("billing.tokenByModel")
2398
+ })
2399
+ }), models.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2400
+ className: UsageBilling_module_css_default.emptyRow,
2401
+ children: t("billing.noData")
2402
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2403
+ className: UsageBilling_module_css_default.tableScroll,
2404
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
2405
+ className: UsageBilling_module_css_default.modelTable,
2406
+ "data-testid": "billing-token-model-table",
2407
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
2408
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("billing.model") }),
2409
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
2410
+ className: UsageBilling_module_css_default.numCol,
2411
+ children: t("billing.inputTokens")
2412
+ }),
2413
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
2414
+ className: UsageBilling_module_css_default.numCol,
2415
+ children: t("billing.outputTokens")
2416
+ }),
2417
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
2418
+ className: UsageBilling_module_css_default.numCol,
2419
+ children: t("billing.tokenReasoningShort")
2420
+ }),
2421
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
2422
+ className: UsageBilling_module_css_default.numCol,
2423
+ children: t("billing.cacheHitRate")
2424
+ }),
2425
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
2426
+ className: UsageBilling_module_css_default.numCol,
2427
+ children: t("billing.tokenTotal")
2428
+ }),
2429
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
2430
+ className: UsageBilling_module_css_default.numCol,
2431
+ children: t("billing.tokenShare")
2432
+ }),
2433
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
2434
+ className: UsageBilling_module_css_default.numCol,
2435
+ children: t("billing.calls")
2436
+ })
2437
+ ] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: models.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
2438
+ "data-testid": "billing-token-model",
2439
+ children: [
2440
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2441
+ className: UsageBilling_module_css_default.modelName,
2442
+ children: m.name
2443
+ }) }),
2444
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
2445
+ className: UsageBilling_module_css_default.numCol,
2446
+ children: formatTokens(m.input)
2447
+ }),
2448
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
2449
+ className: UsageBilling_module_css_default.numCol,
2450
+ children: formatTokens(m.output)
2451
+ }),
2452
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
2453
+ className: UsageBilling_module_css_default.numCol,
2454
+ children: m.reasoning > 0 ? formatTokens(m.reasoning) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2455
+ className: UsageBilling_module_css_default.na,
2456
+ children: "—"
2457
+ })
2458
+ }),
2459
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("td", {
2460
+ className: UsageBilling_module_css_default.numCol,
2461
+ children: [m.cacheHitRate.toFixed(1), "%"]
2462
+ }),
2463
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
2464
+ className: UsageBilling_module_css_default.numCol,
2465
+ children: formatTokens(m.total)
2466
+ }),
2467
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
2468
+ className: UsageBilling_module_css_default.numCol,
2469
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2470
+ className: UsageBilling_module_css_default.tokenModelShareRow,
2471
+ children: [
2472
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2473
+ className: UsageBilling_module_css_default.tokenModelBar,
2474
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2475
+ className: UsageBilling_module_css_default.tokenModelParts,
2476
+ style: { width: `${(m.share * 100).toFixed(2)}%` },
2477
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2478
+ className: UsageBilling_module_css_default.tokenModelPartIn,
2479
+ style: { width: `${m.total > 0 ? m.input / m.total * 100 : 0}%` }
2480
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2481
+ className: UsageBilling_module_css_default.tokenModelPartOut,
2482
+ style: { width: `${m.total > 0 ? m.output / m.total * 100 : 0}%` }
2483
+ })]
2484
+ })
2485
+ }),
2486
+ (m.share * 100).toFixed(1),
2487
+ "%"
2488
+ ]
2489
+ })
2490
+ }),
2491
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
2492
+ className: UsageBilling_module_css_default.numCol,
2493
+ children: m.calls.toLocaleString()
2494
+ })
2495
+ ]
2496
+ }, m.key)) })]
2497
+ })
2498
+ })]
2499
+ })
2500
+ ]
2002
2501
  });
2003
2502
  }
2004
2503
  //#endregion
@@ -2622,7 +3121,24 @@ window.__ModuleLoader__.load({
2622
3121
  "billing.pluginAuthor": "作者",
2623
3122
  "billing.pluginRepository": "仓库",
2624
3123
  "billing.pluginNpm": "npm",
2625
- "billing.pluginLicense": "许可证"
3124
+ "billing.pluginLicense": "许可证",
3125
+ "billing.tabToken": "用量",
3126
+ "billing.tokenExport": "导出 Token",
3127
+ "billing.tokenExportCsv": "按日 Token CSV",
3128
+ "billing.tokenCacheHitRate": "缓存命中率",
3129
+ "billing.tokenReasoningShare": "思考占比",
3130
+ "billing.tokenReasoningShort": "思考",
3131
+ "billing.tokenIo": "输入/输出比",
3132
+ "billing.tokenPeak": "峰值日",
3133
+ "billing.tokenDaily": "每日 Token",
3134
+ "billing.tokenByModel": "模型 Token",
3135
+ "billing.tokenMiss": "未命中输入",
3136
+ "billing.tokenHit": "缓存命中",
3137
+ "billing.tokenOutput": "输出",
3138
+ "billing.tokenTotal": "总 Token",
3139
+ "billing.tokenShare": "占比",
3140
+ "billing.usageStatsTool": "注入用量查询工具",
3141
+ "billing.usageStatsToolHint": "让模型可在对话中查询用量/费用;会占用模型每次请求的上下文,coding 场景建议关闭(改后需重载应用生效)"
2626
3142
  };
2627
3143
  const en = {
2628
3144
  "billing.title": "Usage",
@@ -2787,7 +3303,24 @@ window.__ModuleLoader__.load({
2787
3303
  "billing.pluginAuthor": "Author",
2788
3304
  "billing.pluginRepository": "Repository",
2789
3305
  "billing.pluginNpm": "npm",
2790
- "billing.pluginLicense": "License"
3306
+ "billing.pluginLicense": "License",
3307
+ "billing.tabToken": "Usage",
3308
+ "billing.tokenExport": "Export tokens",
3309
+ "billing.tokenExportCsv": "Daily token CSV",
3310
+ "billing.tokenCacheHitRate": "Cache hit rate",
3311
+ "billing.tokenReasoningShare": "Reasoning share",
3312
+ "billing.tokenReasoningShort": "reasoning",
3313
+ "billing.tokenIo": "In/out ratio",
3314
+ "billing.tokenPeak": "Peak day",
3315
+ "billing.tokenDaily": "Daily tokens",
3316
+ "billing.tokenByModel": "Tokens by model",
3317
+ "billing.tokenMiss": "Uncached input",
3318
+ "billing.tokenHit": "Cache hit",
3319
+ "billing.tokenOutput": "Output",
3320
+ "billing.tokenTotal": "Total tokens",
3321
+ "billing.tokenShare": "Share",
3322
+ "billing.usageStatsTool": "Inject usage-stats tool",
3323
+ "billing.usageStatsToolHint": "Lets the model query usage/cost inside a conversation; it consumes context per request, so keep it off for coding (takes effect after a reload)"
2791
3324
  };
2792
3325
  //#endregion
2793
3326
  //#region src/client/provider-display.ts
@@ -2958,6 +3491,10 @@ window.__ModuleLoader__.load({
2958
3491
  id: "overview",
2959
3492
  labelKey: "billing.tabOverview"
2960
3493
  },
3494
+ {
3495
+ id: "token",
3496
+ labelKey: "billing.tabToken"
3497
+ },
2961
3498
  {
2962
3499
  id: "trends",
2963
3500
  labelKey: "billing.tabTrends"
@@ -2966,10 +3503,6 @@ window.__ModuleLoader__.load({
2966
3503
  id: "providers",
2967
3504
  labelKey: "billing.tabProviders"
2968
3505
  },
2969
- {
2970
- id: "details",
2971
- labelKey: "billing.tabDetails"
2972
- },
2973
3506
  {
2974
3507
  id: "pricing",
2975
3508
  labelKey: "billing.tabPricing"
@@ -3288,7 +3821,8 @@ window.__ModuleLoader__.load({
3288
3821
  output: 0,
3289
3822
  cacheHit: 0,
3290
3823
  cacheMiss: 0,
3291
- cost: 0
3824
+ cost: 0,
3825
+ reasoning: 0
3292
3826
  },
3293
3827
  byModel: {},
3294
3828
  byDay: {},
@@ -3381,6 +3915,38 @@ window.__ModuleLoader__.load({
3381
3915
  }
3382
3916
  }
3383
3917
  /**
3918
+ * 读取 usage_stats 工具开关当前值(插件自带接口,不依赖宿主浏览器设置白名单)。
3919
+ * @returns 当前是否注入;读取失败(服务未起/非 JSON)返回 undefined。
3920
+ */
3921
+ async function loadUsageTool() {
3922
+ try {
3923
+ const response = await fetch("/api/billing/usage-tool");
3924
+ if (!response.ok) return void 0;
3925
+ const parsed = JSON.parse(await response.text());
3926
+ return typeof parsed.enabled === "boolean" ? parsed.enabled : void 0;
3927
+ } catch {
3928
+ return;
3929
+ }
3930
+ }
3931
+ /**
3932
+ * 写 usage_stats 工具开关(插件自带接口)。工具注入是启动期决策,重启应用后生效。
3933
+ * @param enabled - 是否注入。
3934
+ * @returns 是否写成功。
3935
+ */
3936
+ async function saveUsageTool(enabled) {
3937
+ try {
3938
+ const response = await fetch("/api/billing/usage-tool", {
3939
+ method: "POST",
3940
+ headers: { "content-type": "application/json" },
3941
+ body: JSON.stringify({ enabled })
3942
+ });
3943
+ if (!response.ok) return false;
3944
+ return JSON.parse(await response.text()).ok === true;
3945
+ } catch {
3946
+ return false;
3947
+ }
3948
+ }
3949
+ /**
3384
3950
  * Sidebar footer trigger: compact pill in wide mode, icon in rail mode.
3385
3951
  * ZINE 模式下入口由主题插件的贴纸层承担,本触发器由 CSS
3386
3952
  * (body[data-zine-mode] 选择器)隐藏,组件本身无 zine 分支。
@@ -3511,6 +4077,23 @@ window.__ModuleLoader__.load({
3511
4077
  const [tab, setTab] = (0, react.useState)("overview");
3512
4078
  const [trendDays, setTrendDays] = (0, react.useState)(7);
3513
4079
  const [heatmapRange, setHeatmapRange] = (0, react.useState)("month");
4080
+ const [usageStatsEnabled, setUsageStatsEnabled] = (0, react.useState)(false);
4081
+ (0, react.useEffect)(() => {
4082
+ let mounted = true;
4083
+ loadUsageTool().then((enabled) => {
4084
+ if (mounted && enabled !== void 0) setUsageStatsEnabled(enabled);
4085
+ });
4086
+ return () => {
4087
+ mounted = false;
4088
+ };
4089
+ }, []);
4090
+ const toggleUsageStats = (0, react.useCallback)(() => {
4091
+ const next = !usageStatsEnabled;
4092
+ setUsageStatsEnabled(next);
4093
+ saveUsageTool(next).then((ok) => {
4094
+ if (!ok) setUsageStatsEnabled(!next);
4095
+ });
4096
+ }, [usageStatsEnabled]);
3514
4097
  const rateInfo = getRateInfo();
3515
4098
  const money = (cny) => formatMoney(currency === "usd" ? cnyToUsd(cny) : cny, currency);
3516
4099
  const lang = currency === "usd" ? "en" : "zh";
@@ -4312,6 +4895,32 @@ window.__ModuleLoader__.load({
4312
4895
  })
4313
4896
  ]
4314
4897
  }),
4898
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
4899
+ className: UsageBilling_module_css_default.budget,
4900
+ "data-testid": "billing-usage-stats-tool-setting",
4901
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4902
+ className: UsageBilling_module_css_default.budgetHead,
4903
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4904
+ className: UsageBilling_module_css_default.budgetLabel,
4905
+ children: t("billing.usageStatsTool")
4906
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4907
+ className: UsageBilling_module_css_default.budgetControls,
4908
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4909
+ type: "button",
4910
+ role: "switch",
4911
+ "aria-checked": usageStatsEnabled,
4912
+ "aria-label": t("billing.usageStatsTool"),
4913
+ "data-testid": "billing-usage-stats-tool-toggle",
4914
+ className: clsx(UsageBilling_module_css_default.switch, usageStatsEnabled && UsageBilling_module_css_default.switchOn),
4915
+ onClick: toggleUsageStats,
4916
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: UsageBilling_module_css_default.switchKnob })
4917
+ })
4918
+ })]
4919
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4920
+ className: UsageBilling_module_css_default.budgetHint,
4921
+ children: t("billing.usageStatsToolHint")
4922
+ })]
4923
+ }),
4315
4924
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PluginInfoCard, {
4316
4925
  t,
4317
4926
  version: stats.pluginVersion
@@ -4459,261 +5068,257 @@ window.__ModuleLoader__.load({
4459
5068
  })()
4460
5069
  ]
4461
5070
  }),
4462
- tab === "providers" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5071
+ tab === "providers" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4463
5072
  className: UsageBilling_module_css_default.tabPanel,
4464
5073
  "data-testid": "billing-tab-panel-providers",
4465
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
4466
- className: UsageBilling_module_css_default.panel,
4467
- "data-testid": "billing-panel-providers",
4468
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4469
- className: UsageBilling_module_css_default.panelHead,
4470
- children: [
4471
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
4472
- className: UsageBilling_module_css_default.panelTitle,
4473
- children: t("billing.providerBilling")
4474
- }),
4475
- renderSlot("billing.dashboard.decor", { position: "models" }),
4476
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4477
- className: UsageBilling_module_css_default.panelHint,
4478
- children: stats.updatedAt !== void 0 ? `${t("billing.lastUpdated")} ${formatClock(stats.updatedAt)}` : ""
4479
- })
4480
- ]
4481
- }), providerGroups.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4482
- className: UsageBilling_module_css_default.emptyRow,
4483
- "data-testid": "billing-provider-empty",
4484
- children: t("billing.noData")
4485
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4486
- className: UsageBilling_module_css_default.providerGroupList,
4487
- "data-testid": "billing-provider-groups",
4488
- children: providerGroups.map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4489
- className: UsageBilling_module_css_default.providerGroup,
4490
- "data-testid": "billing-provider-group",
5074
+ children: [
5075
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
5076
+ className: UsageBilling_module_css_default.panel,
5077
+ "data-testid": "billing-panel-providers",
5078
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5079
+ className: UsageBilling_module_css_default.panelHead,
4491
5080
  children: [
4492
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4493
- className: UsageBilling_module_css_default.providerGroupHead,
4494
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4495
- className: UsageBilling_module_css_default.providerGroupTitle,
4496
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4497
- className: clsx(UsageBilling_module_css_default.healthDot, group.dot),
4498
- "aria-hidden": "true"
4499
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4500
- className: UsageBilling_module_css_default.providerGroupName,
4501
- children: providerName(group.name)
4502
- })]
4503
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4504
- className: UsageBilling_module_css_default.providerGroupMeta,
4505
- children: [group.subscriptions.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4506
- className: UsageBilling_module_css_default.providerGroupBadge,
4507
- "data-testid": "billing-provider-sub-count",
4508
- children: [group.subscriptions.length, " 套餐"]
4509
- }), group.balance !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4510
- className: UsageBilling_module_css_default.providerGroupBalance,
4511
- "data-testid": "billing-provider-balance",
5081
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
5082
+ className: UsageBilling_module_css_default.panelTitle,
5083
+ children: t("billing.providerBilling")
5084
+ }),
5085
+ renderSlot("billing.dashboard.decor", { position: "models" }),
5086
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5087
+ className: UsageBilling_module_css_default.panelHint,
5088
+ children: stats.updatedAt !== void 0 ? `${t("billing.lastUpdated")} ${formatClock(stats.updatedAt)}` : ""
5089
+ })
5090
+ ]
5091
+ }), providerGroups.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5092
+ className: UsageBilling_module_css_default.emptyRow,
5093
+ "data-testid": "billing-provider-empty",
5094
+ children: t("billing.noData")
5095
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5096
+ className: UsageBilling_module_css_default.providerGroupList,
5097
+ "data-testid": "billing-provider-groups",
5098
+ children: providerGroups.map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5099
+ className: UsageBilling_module_css_default.providerGroup,
5100
+ "data-testid": "billing-provider-group",
5101
+ children: [
5102
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5103
+ className: UsageBilling_module_css_default.providerGroupHead,
5104
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5105
+ className: UsageBilling_module_css_default.providerGroupTitle,
4512
5106
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4513
- className: UsageBilling_module_css_default.providerGroupBalanceLabel,
4514
- children: t("billing.balance")
4515
- }), renderBalance(group.balance)]
5107
+ className: clsx(UsageBilling_module_css_default.healthDot, group.dot),
5108
+ "aria-hidden": "true"
5109
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5110
+ className: UsageBilling_module_css_default.providerGroupName,
5111
+ children: providerName(group.name)
5112
+ })]
5113
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5114
+ className: UsageBilling_module_css_default.providerGroupMeta,
5115
+ children: [group.subscriptions.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5116
+ className: UsageBilling_module_css_default.providerGroupBadge,
5117
+ "data-testid": "billing-provider-sub-count",
5118
+ children: [group.subscriptions.length, " 套餐"]
5119
+ }), group.balance !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5120
+ className: UsageBilling_module_css_default.providerGroupBalance,
5121
+ "data-testid": "billing-provider-balance",
5122
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5123
+ className: UsageBilling_module_css_default.providerGroupBalanceLabel,
5124
+ children: t("billing.balance")
5125
+ }), renderBalance(group.balance)]
5126
+ })]
4516
5127
  })]
4517
- })]
4518
- }),
4519
- group.models.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4520
- className: clsx(UsageBilling_module_css_default.tableScroll, UsageBilling_module_css_default.modelTableScroll),
4521
- "data-testid": "billing-table-scroll",
4522
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
4523
- className: UsageBilling_module_css_default.modelTable,
4524
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
4525
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("billing.model") }),
4526
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
4527
- className: UsageBilling_module_css_default.numCol,
4528
- children: t("billing.calls")
4529
- }),
4530
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
4531
- className: UsageBilling_module_css_default.numCol,
4532
- children: t("billing.inputTokens")
4533
- }),
4534
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
4535
- className: UsageBilling_module_css_default.numCol,
4536
- children: t("billing.outputTokens")
4537
- }),
4538
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
4539
- className: UsageBilling_module_css_default.numCol,
4540
- children: t("billing.cacheHitRate")
4541
- }),
4542
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
4543
- className: UsageBilling_module_css_default.numCol,
4544
- children: t("billing.actual")
4545
- })
4546
- ] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: group.models.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
4547
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4548
- className: UsageBilling_module_css_default.modelCell,
4549
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4550
- className: UsageBilling_module_css_default.modelName,
4551
- children: [
4552
- row.name,
4553
- row.uncatalogued && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4554
- className: UsageBilling_module_css_default.uncataloguedTag,
4555
- "data-testid": "billing-uncatalogued-tag",
4556
- children: t("billing.uncatalogued")
4557
- }),
4558
- row.estimatedPricing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4559
- className: UsageBilling_module_css_default.estimatedTag,
4560
- "data-testid": "billing-estimated-tag",
4561
- children: t("billing.estimatedPricing")
4562
- })
4563
- ]
4564
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4565
- className: UsageBilling_module_css_default.modelProvider,
4566
- children: providerName(row.provider)
4567
- })] })
4568
- }) }),
4569
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
4570
- className: UsageBilling_module_css_default.numCol,
4571
- children: row.calls.toLocaleString()
4572
- }),
4573
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
4574
- className: UsageBilling_module_css_default.numCol,
4575
- children: formatTokens(row.input)
4576
- }),
4577
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
4578
- className: UsageBilling_module_css_default.numCol,
4579
- children: formatTokens(row.output)
4580
- }),
4581
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
4582
- className: UsageBilling_module_css_default.numCol,
4583
- children: formatPercent(row.cacheHitRate)
4584
- }),
4585
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
4586
- className: UsageBilling_module_css_default.numCol,
4587
- children: row.plan ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4588
- className: UsageBilling_module_css_default.planTag,
4589
- children: t("billing.subscriptionIncluded")
4590
- }) : row.actual !== void 0 ? (() => {
4591
- const official = row.officialCost;
4592
- const third = row.actual - official;
4593
- if (official > 0 && third > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4594
- className: UsageBilling_module_css_default.bucketCost,
5128
+ }),
5129
+ group.models.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5130
+ className: clsx(UsageBilling_module_css_default.tableScroll, UsageBilling_module_css_default.modelTableScroll),
5131
+ "data-testid": "billing-table-scroll",
5132
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
5133
+ className: UsageBilling_module_css_default.modelTable,
5134
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
5135
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("billing.model") }),
5136
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
5137
+ className: UsageBilling_module_css_default.numCol,
5138
+ children: t("billing.calls")
5139
+ }),
5140
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
5141
+ className: UsageBilling_module_css_default.numCol,
5142
+ children: t("billing.inputTokens")
5143
+ }),
5144
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
5145
+ className: UsageBilling_module_css_default.numCol,
5146
+ children: t("billing.outputTokens")
5147
+ }),
5148
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
5149
+ className: UsageBilling_module_css_default.numCol,
5150
+ children: t("billing.cacheHitRate")
5151
+ }),
5152
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
5153
+ className: UsageBilling_module_css_default.numCol,
5154
+ children: t("billing.actual")
5155
+ })
5156
+ ] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: group.models.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
5157
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5158
+ className: UsageBilling_module_css_default.modelCell,
5159
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5160
+ className: UsageBilling_module_css_default.modelName,
4595
5161
  children: [
4596
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4597
- className: UsageBilling_module_css_default.bucketOfficial,
4598
- children: money(official)
4599
- }),
4600
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4601
- className: UsageBilling_module_css_default.bucketSep,
4602
- children: "/"
5162
+ row.name,
5163
+ row.uncatalogued && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5164
+ className: UsageBilling_module_css_default.uncataloguedTag,
5165
+ "data-testid": "billing-uncatalogued-tag",
5166
+ children: t("billing.uncatalogued")
4603
5167
  }),
4604
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4605
- className: UsageBilling_module_css_default.bucketThird,
4606
- children: money(third)
5168
+ row.estimatedPricing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5169
+ className: UsageBilling_module_css_default.estimatedTag,
5170
+ "data-testid": "billing-estimated-tag",
5171
+ children: t("billing.estimatedPricing")
4607
5172
  })
4608
5173
  ]
4609
- });
4610
- return money(row.actual);
4611
- })() : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4612
- className: UsageBilling_module_css_default.na,
4613
- children: "—"
4614
- })
4615
- })
4616
- ] }, row.key)) })]
4617
- })
4618
- }),
4619
- group.subscriptions.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4620
- className: UsageBilling_module_css_default.subscriptionGrid,
4621
- "data-testid": "billing-subscriptions-grid",
4622
- children: group.subscriptions.map((quota) => {
4623
- const statusText = subscriptionStatusText(quota.status, t);
4624
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4625
- className: UsageBilling_module_css_default.subscriptionCard,
4626
- "data-testid": "billing-subscription-card",
4627
- children: [
4628
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4629
- className: UsageBilling_module_css_default.subscriptionHead,
4630
- children: [
4631
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4632
- className: UsageBilling_module_css_default.subscriptionName,
4633
- children: providerName(quota.displayName)
4634
- }),
4635
- quota.planType === "code" && (() => {
4636
- const tier = tierInfoOf(quota.provider);
4637
- const tierFee = tier !== void 0 ? t("billing.subscriptionFeePerMonth").replace("{amount}", tier.currency === "USD" ? `$${tier.amount}` : `¥${tier.amount}`) : void 0;
4638
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4639
- className: UsageBilling_module_css_default.subscriptionPlan,
4640
- "data-kind": "code",
4641
- children: [
4642
- tierFee ?? (quota.subscriptionAmount !== void 0 && quota.subscriptionAmount > 0 ? t("billing.subscriptionFeePerMonth").replace("{amount}", money(quota.subscriptionAmount)) : t("billing.planTypeCode")),
4643
- tier?.label !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4644
- className: UsageBilling_module_css_default.subscriptionTier,
4645
- "data-testid": `billing-tier-${quota.provider}`,
4646
- children: tier.label
4647
- }),
4648
- tier !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4649
- className: UsageBilling_module_css_default.subscriptionAuto,
4650
- "data-testid": `billing-auto-${quota.provider}`,
4651
- children: t("billing.subscriptionAutoDetect")
4652
- })
4653
- ]
4654
- });
4655
- })(),
4656
- quota.planType === "token" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4657
- className: UsageBilling_module_css_default.subscriptionPlan,
4658
- "data-kind": "token",
4659
- children: t("billing.planTypeToken")
4660
- }),
4661
- quota.plan !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4662
- className: UsageBilling_module_css_default.subscriptionPlan,
4663
- children: quota.plan
4664
- })
4665
- ]
5174
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5175
+ className: UsageBilling_module_css_default.modelProvider,
5176
+ children: providerName(row.provider)
5177
+ })] })
5178
+ }) }),
5179
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
5180
+ className: UsageBilling_module_css_default.numCol,
5181
+ children: row.calls.toLocaleString()
5182
+ }),
5183
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
5184
+ className: UsageBilling_module_css_default.numCol,
5185
+ children: formatTokens(row.input)
4666
5186
  }),
4667
- statusText !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4668
- className: UsageBilling_module_css_default.subscriptionStatus,
4669
- children: statusText
5187
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
5188
+ className: UsageBilling_module_css_default.numCol,
5189
+ children: formatTokens(row.output)
4670
5190
  }),
4671
- quota.windows.length === 0 && statusText === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4672
- className: UsageBilling_module_css_default.subscriptionStatus,
4673
- children: t("billing.subscriptionNoApi")
5191
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
5192
+ className: UsageBilling_module_css_default.numCol,
5193
+ children: formatPercent(row.cacheHitRate)
4674
5194
  }),
4675
- quota.windows.map((window) => (() => {
4676
- const used = Math.min(100, Math.max(0, window.usedPercent));
4677
- const exhausted = Math.min(100, Math.max(0, window.remainingPercent)) <= 0;
4678
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4679
- className: UsageBilling_module_css_default.subscriptionWindow,
5195
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
5196
+ className: UsageBilling_module_css_default.numCol,
5197
+ children: row.plan ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5198
+ className: UsageBilling_module_css_default.planTag,
5199
+ children: t("billing.subscriptionIncluded")
5200
+ }) : row.actual !== void 0 ? (() => {
5201
+ const official = row.officialCost;
5202
+ const third = row.actual - official;
5203
+ if (official > 0 && third > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5204
+ className: UsageBilling_module_css_default.bucketCost,
5205
+ children: [
5206
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5207
+ className: UsageBilling_module_css_default.bucketOfficial,
5208
+ children: money(official)
5209
+ }),
5210
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5211
+ className: UsageBilling_module_css_default.bucketSep,
5212
+ children: "/"
5213
+ }),
5214
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5215
+ className: UsageBilling_module_css_default.bucketThird,
5216
+ children: money(third)
5217
+ })
5218
+ ]
5219
+ });
5220
+ return money(row.actual);
5221
+ })() : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5222
+ className: UsageBilling_module_css_default.na,
5223
+ children: "—"
5224
+ })
5225
+ })
5226
+ ] }, row.key)) })]
5227
+ })
5228
+ }),
5229
+ group.subscriptions.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5230
+ className: UsageBilling_module_css_default.subscriptionGrid,
5231
+ "data-testid": "billing-subscriptions-grid",
5232
+ children: group.subscriptions.map((quota) => {
5233
+ const statusText = subscriptionStatusText(quota.status, t);
5234
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5235
+ className: UsageBilling_module_css_default.subscriptionCard,
5236
+ "data-testid": "billing-subscription-card",
5237
+ children: [
5238
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5239
+ className: UsageBilling_module_css_default.subscriptionHead,
4680
5240
  children: [
4681
5241
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4682
- className: UsageBilling_module_css_default.subscriptionWindowLabel,
4683
- children: subscriptionWindowLabel(window.kind, t)
4684
- }),
4685
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4686
- className: UsageBilling_module_css_default.subscriptionTrack,
4687
- "aria-hidden": "true",
4688
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4689
- className: clsx(UsageBilling_module_css_default.subscriptionFill, used >= 100 && UsageBilling_module_css_default.subscriptionFillOver, used >= 80 && used < 100 && UsageBilling_module_css_default.subscriptionFillWarn),
4690
- style: { width: `${used}%` }
4691
- })
5242
+ className: UsageBilling_module_css_default.subscriptionName,
5243
+ children: providerName(quota.displayName)
4692
5244
  }),
4693
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4694
- className: clsx(UsageBilling_module_css_default.subscriptionPct, exhausted && UsageBilling_module_css_default.subscriptionExhausted),
4695
- children: exhausted ? t("billing.subscriptionExhausted") : t("billing.subscriptionRemaining").replace("{pct}", String(window.remainingPercent))
5245
+ quota.planType === "code" && (() => {
5246
+ const tier = tierInfoOf(quota.provider);
5247
+ const tierFee = tier !== void 0 ? t("billing.subscriptionFeePerMonth").replace("{amount}", tier.currency === "USD" ? `$${tier.amount}` : `¥${tier.amount}`) : void 0;
5248
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5249
+ className: UsageBilling_module_css_default.subscriptionPlan,
5250
+ "data-kind": "code",
5251
+ children: [
5252
+ tierFee ?? (quota.subscriptionAmount !== void 0 && quota.subscriptionAmount > 0 ? t("billing.subscriptionFeePerMonth").replace("{amount}", money(quota.subscriptionAmount)) : t("billing.planTypeCode")),
5253
+ tier?.label !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5254
+ className: UsageBilling_module_css_default.subscriptionTier,
5255
+ "data-testid": `billing-tier-${quota.provider}`,
5256
+ children: tier.label
5257
+ }),
5258
+ tier !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5259
+ className: UsageBilling_module_css_default.subscriptionAuto,
5260
+ "data-testid": `billing-auto-${quota.provider}`,
5261
+ children: t("billing.subscriptionAutoDetect")
5262
+ })
5263
+ ]
5264
+ });
5265
+ })(),
5266
+ quota.planType === "token" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5267
+ className: UsageBilling_module_css_default.subscriptionPlan,
5268
+ "data-kind": "token",
5269
+ children: t("billing.planTypeToken")
4696
5270
  }),
4697
- window.resetsAt !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4698
- className: UsageBilling_module_css_default.subscriptionReset,
4699
- children: t("billing.subscriptionReset").replace("{date}", `${localDayStamp(new Date(window.resetsAt).getTime())} ${formatClock(new Date(window.resetsAt).getTime())}`)
5271
+ quota.plan !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5272
+ className: UsageBilling_module_css_default.subscriptionPlan,
5273
+ children: quota.plan
4700
5274
  })
4701
5275
  ]
4702
- }, window.kind);
4703
- })())
4704
- ]
4705
- }, quota.provider);
5276
+ }),
5277
+ statusText !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5278
+ className: UsageBilling_module_css_default.subscriptionStatus,
5279
+ children: statusText
5280
+ }),
5281
+ quota.windows.length === 0 && statusText === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5282
+ className: UsageBilling_module_css_default.subscriptionStatus,
5283
+ children: t("billing.subscriptionNoApi")
5284
+ }),
5285
+ quota.windows.map((window) => (() => {
5286
+ const used = Math.min(100, Math.max(0, window.usedPercent));
5287
+ const exhausted = Math.min(100, Math.max(0, window.remainingPercent)) <= 0;
5288
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5289
+ className: UsageBilling_module_css_default.subscriptionWindow,
5290
+ children: [
5291
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5292
+ className: UsageBilling_module_css_default.subscriptionWindowLabel,
5293
+ children: subscriptionWindowLabel(window.kind, t)
5294
+ }),
5295
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5296
+ className: UsageBilling_module_css_default.subscriptionTrack,
5297
+ "aria-hidden": "true",
5298
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5299
+ className: clsx(UsageBilling_module_css_default.subscriptionFill, used >= 100 && UsageBilling_module_css_default.subscriptionFillOver, used >= 80 && used < 100 && UsageBilling_module_css_default.subscriptionFillWarn),
5300
+ style: { width: `${used}%` }
5301
+ })
5302
+ }),
5303
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5304
+ className: clsx(UsageBilling_module_css_default.subscriptionPct, exhausted && UsageBilling_module_css_default.subscriptionExhausted),
5305
+ children: exhausted ? t("billing.subscriptionExhausted") : t("billing.subscriptionRemaining").replace("{pct}", String(window.remainingPercent))
5306
+ }),
5307
+ window.resetsAt !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5308
+ className: UsageBilling_module_css_default.subscriptionReset,
5309
+ children: t("billing.subscriptionReset").replace("{date}", `${localDayStamp(new Date(window.resetsAt).getTime())} ${formatClock(new Date(window.resetsAt).getTime())}`)
5310
+ })
5311
+ ]
5312
+ }, window.kind);
5313
+ })())
5314
+ ]
5315
+ }, quota.provider);
5316
+ })
4706
5317
  })
4707
- })
4708
- ]
4709
- }, group.name))
4710
- })]
4711
- })
4712
- }),
4713
- tab === "details" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4714
- className: UsageBilling_module_css_default.tabPanel,
4715
- "data-testid": "billing-tab-panel-details",
4716
- children: [
5318
+ ]
5319
+ }, group.name))
5320
+ })]
5321
+ }),
4717
5322
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4718
5323
  className: UsageBilling_module_css_default.exportBar,
4719
5324
  "data-testid": "billing-export-bar",
@@ -4753,24 +5358,6 @@ window.__ModuleLoader__.load({
4753
5358
  })
4754
5359
  ]
4755
5360
  }),
4756
- stats.perf !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
4757
- className: UsageBilling_module_css_default.panel,
4758
- "data-testid": "billing-panel-perf",
4759
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4760
- className: UsageBilling_module_css_default.panelHead,
4761
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
4762
- className: UsageBilling_module_css_default.panelTitle,
4763
- children: t("billing.perfTitle")
4764
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4765
- className: UsageBilling_module_css_default.panelHint,
4766
- children: t("billing.perfHint")
4767
- })]
4768
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PerfPanel, {
4769
- perf: stats.perf,
4770
- models: chartModels,
4771
- t
4772
- })]
4773
- }),
4774
5361
  roleRows.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
4775
5362
  className: UsageBilling_module_css_default.panel,
4776
5363
  "data-testid": "billing-panel-roles",
@@ -4999,6 +5586,34 @@ window.__ModuleLoader__.load({
4999
5586
  })
5000
5587
  ]
5001
5588
  }),
5589
+ tab === "token" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5590
+ className: UsageBilling_module_css_default.tabPanel,
5591
+ "data-testid": "billing-tab-panel-token",
5592
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TokenPanel, {
5593
+ stats,
5594
+ currency,
5595
+ trendDays,
5596
+ onTrendDays: setTrendDays,
5597
+ t
5598
+ }), stats.perf !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
5599
+ className: UsageBilling_module_css_default.panel,
5600
+ "data-testid": "billing-panel-perf",
5601
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5602
+ className: UsageBilling_module_css_default.panelHead,
5603
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
5604
+ className: UsageBilling_module_css_default.panelTitle,
5605
+ children: t("billing.perfTitle")
5606
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5607
+ className: UsageBilling_module_css_default.panelHint,
5608
+ children: t("billing.perfHint")
5609
+ })]
5610
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PerfPanel, {
5611
+ perf: stats.perf,
5612
+ models: chartModels,
5613
+ t
5614
+ })]
5615
+ })]
5616
+ }),
5002
5617
  tab === "pricing" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5003
5618
  className: UsageBilling_module_css_default.tabPanel,
5004
5619
  "data-testid": "billing-tab-panel-pricing",
@@ -5734,6 +6349,7 @@ window.__ModuleLoader__.load({
5734
6349
  const metrics = createBillingMetrics();
5735
6350
  ctx.provide("billingMetrics", metrics);
5736
6351
  const budgetStore = createBillingBudgetStore();
6352
+ const connection = ctx.get("connection");
5737
6353
  ctx.effect(() => ctx.locale.register(NS, {
5738
6354
  zh,
5739
6355
  en
@@ -5751,7 +6367,7 @@ window.__ModuleLoader__.load({
5751
6367
  inject: () => ({
5752
6368
  checkModels: async () => {
5753
6369
  try {
5754
- const { result } = await ctx.connection.api.llm.models({});
6370
+ const { result } = await connection.api.llm.models({});
5755
6371
  if (!result.ok) return {
5756
6372
  checked: true,
5757
6373
  available: false,