@kenz1117/dsh-ui-usage-billing 0.9.0 → 0.9.2

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:10px;align-items:center;gap:12px;padding:10px 14px;transition:border-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:var(--dsw-static-blue-500);width:28px;height:28px;color:var(--dsw-static-neutral-bluish-00);border-radius:6px;flex:none;justify-content:center;align-items:center;display:inline-flex}.VWh0dG_triggerIcon svg{stroke-width:1.8px;width:15px;height:15px}.VWh0dG_triggerToday,.VWh0dG_triggerMonth{align-items:baseline;gap:4px;min-width:0;display:flex}.VWh0dG_triggerDivider{background:var(--dsw-alias-border-l1);align-self:stretch;width:1px}.VWh0dG_triggerAmount{color:var(--dsw-alias-label-primary);letter-spacing:-.01em;font-variant-numeric:tabular-nums;white-space:nowrap;font-size:18px;font-weight:600;line-height:22px}.VWh0dG_triggerAmountSub{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:13px;font-weight:600;line-height:18px}.VWh0dG_triggerMeta{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:10.5px;line-height:14px}.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:var(--dsw-alias-bg-layer-1);border-radius:16px;justify-content:space-between;align-items:center;gap:24px;padding:20px 24px;display:flex;position:relative;overflow:hidden}.VWh0dG_heroMain{flex-direction:column;gap:4px;min-width:0;display:flex}.VWh0dG_heroLabel{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:12px;line-height:17px}.VWh0dG_heroValue{letter-spacing:-.02em;font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--dsw-alias-label-primary);font-size:44px;font-weight:600;line-height:52px}.VWh0dG_heroMeta{color:var(--dsw-alias-label-caption);white-space:nowrap;font-size:12px;line-height:17px}.VWh0dG_heroGauge{flex:none;width:108px;height:108px;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:10px}.VWh0dG_heroGaugeArc{fill:none;stroke:var(--dsw-static-blue-500);stroke-width:10px;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:22px;font-weight:700;line-height:26px}.VWh0dG_heroGaugePctOver{color:var(--dsw-static-red-500)}.VWh0dG_heroGaugeLabel{color:var(--dsw-alias-label-tertiary);font-size:10.5px;line-height:14px}.VWh0dG_heroSide{border-left:1px solid var(--dsw-alias-border-l1);flex-direction:column;flex:none;gap:8px;padding-left:24px;display:flex}.VWh0dG_heroSideItem{flex-direction:column;gap:2px;display:flex}.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:17px;font-weight:600;line-height:23px;display:inline-flex}.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_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_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_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:110px;padding:4px 2px 0;display:flex;overflow-x:auto}.VWh0dG_roundsBarCol{flex-direction:column;flex:1 0 28px;justify-content:flex-end;align-items:stretch;height:100%;display:flex}.VWh0dG_roundsBarLabel{text-align:center;color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;max-width:100%;margin-bottom:2px;font-size:8px;line-height:1;overflow:hidden}.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}@media (width<=640px){.VWh0dG_kpiGrid{grid-template-columns:repeat(2,minmax(0,1fr))}.VWh0dG_hero{flex-direction:column;align-items:flex-start;gap:14px}.VWh0dG_heroGauge{width:96px;height:96px;position:absolute;top:20px;right:24px}.VWh0dG_heroMain{padding-right:112px}.VWh0dG_heroSide{border-left:none;border-top:1px solid var(--dsw-alias-border-l1);flex-direction:row;align-self:stretch;gap:20px;padding-top:14px;padding-left:0}.VWh0dG_heroSideItem{flex-direction:row;align-items:baseline;gap:8px}}";
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_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}@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,208 +34,250 @@ window.__ModuleLoader__.load({
34
34
  document.head.appendChild(tag);
35
35
  }
36
36
  var UsageBilling_module_css_default = {
37
+ "peakAlertPanelLabel": "VWh0dG_peakAlertPanelLabel",
37
38
  "shareDot": "VWh0dG_shareDot",
38
- "budget": "VWh0dG_budget",
39
- "chartStack": "VWh0dG_chartStack",
40
- "dashboardIn": "VWh0dG_dashboardIn",
41
- "rangeButton": "VWh0dG_rangeButton",
42
- "budgetUnit": "VWh0dG_budgetUnit",
43
- "heroValue": "VWh0dG_heroValue",
44
- "triggerPopBar": "VWh0dG_triggerPopBar",
45
- "panelTitle": "VWh0dG_panelTitle",
46
- "chartLine": "VWh0dG_chartLine",
47
- "bandTag": "VWh0dG_bandTag",
48
- "flatTag": "VWh0dG_flatTag",
49
- "healthBadge": "VWh0dG_healthBadge",
50
- "liveCostItem": "VWh0dG_liveCostItem",
51
- "closeButton": "VWh0dG_closeButton",
52
- "headTitleRow": "VWh0dG_headTitleRow",
39
+ "shareSegUser": "VWh0dG_shareSegUser",
40
+ "kpiGreen": "VWh0dG_kpiGreen",
41
+ "healthOk": "VWh0dG_healthOk",
42
+ "heroReadout": "VWh0dG_heroReadout",
43
+ "shareItem": "VWh0dG_shareItem",
44
+ "dashboardHead": "VWh0dG_dashboardHead",
53
45
  "dashboardTitle": "VWh0dG_dashboardTitle",
54
- "heroGaugeTrack": "VWh0dG_heroGaugeTrack",
55
- "panel": "VWh0dG_panel",
56
- "triggerIcon": "VWh0dG_triggerIcon",
57
- "modelTable": "VWh0dG_modelTable",
58
- "panelHint": "VWh0dG_panelHint",
59
- "budgetHead": "VWh0dG_budgetHead",
60
- "switch": "VWh0dG_switch",
61
- "pricingToggleText": "VWh0dG_pricingToggleText",
62
- "pricingChevronOpen": "VWh0dG_pricingChevronOpen",
63
46
  "estimatedTag": "VWh0dG_estimatedTag",
64
- "exportButton": "VWh0dG_exportButton",
65
- "heroSideValue": "VWh0dG_heroSideValue",
66
- "healthIdle": "VWh0dG_healthIdle",
67
- "currencyToggle": "VWh0dG_currencyToggle",
68
- "shareValue": "VWh0dG_shareValue",
69
- "liveTierOff": "VWh0dG_liveTierOff",
70
- "kpiTile": "VWh0dG_kpiTile",
71
- "liveTierPeak": "VWh0dG_liveTierPeak",
72
- "trendPanel": "VWh0dG_trendPanel",
73
- "railButton": "VWh0dG_railButton",
74
- "subscriptionStatus": "VWh0dG_subscriptionStatus",
75
- "healthBadgeBad": "VWh0dG_healthBadgeBad",
76
- "balanceDaysLow": "VWh0dG_balanceDaysLow",
77
- "trigger": "VWh0dG_trigger",
78
- "switchOn": "VWh0dG_switchOn",
79
- "rateBadge": "VWh0dG_rateBadge",
80
- "triggerMonth": "VWh0dG_triggerMonth",
81
- "rateBadgeLive": "VWh0dG_rateBadgeLive",
82
- "switchKnob": "VWh0dG_switchKnob",
83
- "healthOk": "VWh0dG_healthOk",
84
- "balanceCell": "VWh0dG_balanceCell",
85
- "liveCostBar": "VWh0dG_liveCostBar",
86
- "balanceDays": "VWh0dG_balanceDays",
87
- "providerGroupTitle": "VWh0dG_providerGroupTitle",
88
- "roundsBarLabel": "VWh0dG_roundsBarLabel",
89
- "modelName": "VWh0dG_modelName",
90
- "heroMeta": "VWh0dG_heroMeta",
91
- "heroGauge": "VWh0dG_heroGauge",
92
- "chartBar": "VWh0dG_chartBar",
93
- "heroSide": "VWh0dG_heroSide",
94
- "chartDot": "VWh0dG_chartDot",
95
- "currencyButtonActive": "VWh0dG_currencyButtonActive",
96
- "shareSegOff": "VWh0dG_shareSegOff",
97
- "chartTooltipSwatch": "VWh0dG_chartTooltipSwatch",
98
- "roundsBars": "VWh0dG_roundsBars",
99
- "subscriptionName": "VWh0dG_subscriptionName",
100
- "subscriptionPlan": "VWh0dG_subscriptionPlan",
101
- "providerGroupBadge": "VWh0dG_providerGroupBadge",
102
- "roundsFlagMark": "VWh0dG_roundsFlagMark",
103
- "roundsBarFlagged": "VWh0dG_roundsBarFlagged",
47
+ "providerGroup": "VWh0dG_providerGroup",
48
+ "peakAlertPanel": "VWh0dG_peakAlertPanel",
49
+ "budgetFill": "VWh0dG_budgetFill",
50
+ "bandTagOff": "VWh0dG_bandTagOff",
104
51
  "heatmapGrid": "VWh0dG_heatmapGrid",
105
- "heatmapLegend": "VWh0dG_heatmapLegend",
106
- "roundsBar": "VWh0dG_roundsBar",
107
- "shareTrack": "VWh0dG_shareTrack",
108
- "kpiLabel": "VWh0dG_kpiLabel",
109
- "chartLegendLine": "VWh0dG_chartLegendLine",
110
- "chartEmpty": "VWh0dG_chartEmpty",
111
- "tableScroll": "VWh0dG_tableScroll",
112
- "modelTableScroll": "VWh0dG_modelTableScroll",
113
- "kpiGrid": "VWh0dG_kpiGrid",
114
- "bandPriceOff": "VWh0dG_bandPriceOff",
115
- "shareSegUser": "VWh0dG_shareSegUser",
116
- "liveQuotaCrit": "VWh0dG_liveQuotaCrit",
117
- "providerGroupBalance": "VWh0dG_providerGroupBalance",
52
+ "deltaUp": "VWh0dG_deltaUp",
53
+ "budgetFillWarn": "VWh0dG_budgetFillWarn",
54
+ "providerGroupList": "VWh0dG_providerGroupList",
55
+ "budgetLabel": "VWh0dG_budgetLabel",
118
56
  "heroGaugePctOver": "VWh0dG_heroGaugePctOver",
119
- "panelHead": "VWh0dG_panelHead",
120
- "triggerToday": "VWh0dG_triggerToday",
121
- "heroGaugeSvg": "VWh0dG_heroGaugeSvg",
122
- "tabPanelIn": "VWh0dG_tabPanelIn",
123
- "chartLegend": "VWh0dG_chartLegend",
124
- "roundsBarCol": "VWh0dG_roundsBarCol",
125
- "chartWrap": "VWh0dG_chartWrap",
126
- "chartLegendBar": "VWh0dG_chartLegendBar",
127
- "providerGroupMeta": "VWh0dG_providerGroupMeta",
128
- "heatmapCellEmpty": "VWh0dG_heatmapCellEmpty",
129
- "roundsBarWrap": "VWh0dG_roundsBarWrap",
57
+ "roundsBar": "VWh0dG_roundsBar",
58
+ "peakAlertPanelHead": "VWh0dG_peakAlertPanelHead",
130
59
  "modelProvider": "VWh0dG_modelProvider",
131
- "healthDot": "VWh0dG_healthDot",
132
- "dashboardModal": "VWh0dG_dashboardModal",
133
- "budgetControls": "VWh0dG_budgetControls",
134
- "triggerPopLabel": "VWh0dG_triggerPopLabel",
135
- "bandPrice": "VWh0dG_bandPrice",
60
+ "peakAlertField": "VWh0dG_peakAlertField",
61
+ "currencyButton": "VWh0dG_currencyButton",
62
+ "heroGauge": "VWh0dG_heroGauge",
63
+ "shareSegTool": "VWh0dG_shareSegTool",
64
+ "roundsBarLabel": "VWh0dG_roundsBarLabel",
65
+ "triggerMeta": "VWh0dG_triggerMeta",
66
+ "tabButton": "VWh0dG_tabButton",
67
+ "switch": "VWh0dG_switch",
68
+ "heroGaugeArc": "VWh0dG_heroGaugeArc",
69
+ "bucketStatLabel": "VWh0dG_bucketStatLabel",
70
+ "chartTooltipDate": "VWh0dG_chartTooltipDate",
71
+ "bucketStat": "VWh0dG_bucketStat",
72
+ "budgetInput": "VWh0dG_budgetInput",
73
+ "roundsBarColPeak": "VWh0dG_roundsBarColPeak",
136
74
  "subscriptionPct": "VWh0dG_subscriptionPct",
137
- "tabPanel": "VWh0dG_tabPanel",
138
- "triggerDivider": "VWh0dG_triggerDivider",
139
- "triggerAmountSub": "VWh0dG_triggerAmountSub",
140
- "budgetFill": "VWh0dG_budgetFill",
141
- "bandTagOff": "VWh0dG_bandTagOff",
142
- "subscriptionReset": "VWh0dG_subscriptionReset",
143
- "providerGroupHead": "VWh0dG_providerGroupHead",
144
- "providerGroupBalanceLabel": "VWh0dG_providerGroupBalanceLabel",
145
- "budgetTrack": "VWh0dG_budgetTrack",
75
+ "planTag": "VWh0dG_planTag",
76
+ "exportBar": "VWh0dG_exportBar",
77
+ "liveCostItem": "VWh0dG_liveCostItem",
146
78
  "tabNav": "VWh0dG_tabNav",
79
+ "dashboardModal": "VWh0dG_dashboardModal",
80
+ "heroMain": "VWh0dG_heroMain",
81
+ "providerGroupBalance": "VWh0dG_providerGroupBalance",
82
+ "roundsBarCol": "VWh0dG_roundsBarCol",
83
+ "kpiDetail": "VWh0dG_kpiDetail",
84
+ "chartLegendLine": "VWh0dG_chartLegendLine",
85
+ "shareValue": "VWh0dG_shareValue",
86
+ "peakAlertHint": "VWh0dG_peakAlertHint",
87
+ "subscriptionWindowLabel": "VWh0dG_subscriptionWindowLabel",
88
+ "heatmapLegend": "VWh0dG_heatmapLegend",
147
89
  "chartTooltipRow": "VWh0dG_chartTooltipRow",
148
- "modelCell": "VWh0dG_modelCell",
149
- "budgetLabel": "VWh0dG_budgetLabel",
150
- "dashboardRight": "VWh0dG_dashboardRight",
151
- "rangeToggle": "VWh0dG_rangeToggle",
152
- "pricingToggle": "VWh0dG_pricingToggle",
153
- "heroSideItem": "VWh0dG_heroSideItem",
90
+ "switchOn": "VWh0dG_switchOn",
91
+ "emptyRow": "VWh0dG_emptyRow",
92
+ "heatmapCell": "VWh0dG_heatmapCell",
93
+ "roundsFlagBadge": "VWh0dG_roundsFlagBadge",
94
+ "balanceDaysLow": "VWh0dG_balanceDaysLow",
95
+ "providerGroupTitle": "VWh0dG_providerGroupTitle",
96
+ "triggerSparkBar": "VWh0dG_triggerSparkBar",
97
+ "peakAlertSelect": "VWh0dG_peakAlertSelect",
98
+ "shareSegPeak": "VWh0dG_shareSegPeak",
154
99
  "exportLabel": "VWh0dG_exportLabel",
155
- "costCol": "VWh0dG_costCol",
156
- "providerGroup": "VWh0dG_providerGroup",
157
- "triggerPopValue": "VWh0dG_triggerPopValue",
158
- "kpiValue": "VWh0dG_kpiValue",
159
- "pricingTable": "VWh0dG_pricingTable",
160
- "heroGaugeCenter": "VWh0dG_heroGaugeCenter",
161
- "planTag": "VWh0dG_planTag",
100
+ "heroMeta": "VWh0dG_heroMeta",
101
+ "budgetOverPulse": "VWh0dG_budgetOverPulse",
102
+ "chartGrid": "VWh0dG_chartGrid",
162
103
  "rounds": "VWh0dG_rounds",
163
- "triggerAmount": "VWh0dG_triggerAmount",
164
- "triggerMeta": "VWh0dG_triggerMeta",
165
- "budgetInput": "VWh0dG_budgetInput",
166
- "exportBar": "VWh0dG_exportBar",
167
- "chartAxisLabel": "VWh0dG_chartAxisLabel",
104
+ "pricingToggleText": "VWh0dG_pricingToggleText",
105
+ "liveCostSep": "VWh0dG_liveCostSep",
106
+ "modelTable": "VWh0dG_modelTable",
107
+ "heroSideItem": "VWh0dG_heroSideItem",
108
+ "subscriptionWindow": "VWh0dG_subscriptionWindow",
109
+ "panel": "VWh0dG_panel",
168
110
  "heatmapFooter": "VWh0dG_heatmapFooter",
169
- "healthBadgeOk": "VWh0dG_healthBadgeOk",
170
- "kpiGreen": "VWh0dG_kpiGreen",
171
- "shareSeg": "VWh0dG_shareSeg",
172
- "triggerPopBars": "VWh0dG_triggerPopBars",
173
- "deltaDown": "VWh0dG_deltaDown",
174
- "providerGroupName": "VWh0dG_providerGroupName",
111
+ "rateBadgeLive": "VWh0dG_rateBadgeLive",
112
+ "balanceDays": "VWh0dG_balanceDays",
113
+ "chartAxisLabel": "VWh0dG_chartAxisLabel",
114
+ "settingsTitle": "VWh0dG_settingsTitle",
115
+ "closeButton": "VWh0dG_closeButton",
116
+ "dashboardBody": "VWh0dG_dashboardBody",
117
+ "panelHead": "VWh0dG_panelHead",
118
+ "peakAlertIn": "VWh0dG_peakAlertIn",
119
+ "heatmap": "VWh0dG_heatmap",
120
+ "bandTag": "VWh0dG_bandTag",
121
+ "shareLegend": "VWh0dG_shareLegend",
122
+ "subscriptionCard": "VWh0dG_subscriptionCard",
123
+ "chartStack": "VWh0dG_chartStack",
124
+ "peakAlertText": "VWh0dG_peakAlertText",
125
+ "rangeButton": "VWh0dG_rangeButton",
175
126
  "delta": "VWh0dG_delta",
176
- "budgetValue": "VWh0dG_budgetValue",
127
+ "heroSideSpacer": "VWh0dG_heroSideSpacer",
128
+ "chartEmpty": "VWh0dG_chartEmpty",
129
+ "healthBadgeOk": "VWh0dG_healthBadgeOk",
130
+ "liveTierPeak": "VWh0dG_liveTierPeak",
131
+ "tabPanel": "VWh0dG_tabPanel",
132
+ "bucketSep": "VWh0dG_bucketSep",
133
+ "modelDot": "VWh0dG_modelDot",
134
+ "triggerSpark": "VWh0dG_triggerSpark",
135
+ "heroSideLabel": "VWh0dG_heroSideLabel",
177
136
  "pricingChevron": "VWh0dG_pricingChevron",
178
- "chartSvg": "VWh0dG_chartSvg",
179
- "shareSegTool": "VWh0dG_shareSegTool",
180
- "chartGrid": "VWh0dG_chartGrid",
181
- "liveCostSep": "VWh0dG_liveCostSep",
182
- "subscriptionHead": "VWh0dG_subscriptionHead",
183
- "kpiDetail": "VWh0dG_kpiDetail",
137
+ "railButton": "VWh0dG_railButton",
138
+ "bandPriceOff": "VWh0dG_bandPriceOff",
139
+ "triggerSub": "VWh0dG_triggerSub",
140
+ "heroGaugeTrack": "VWh0dG_heroGaugeTrack",
141
+ "bucketOfficial": "VWh0dG_bucketOfficial",
142
+ "healthBadgeBad": "VWh0dG_healthBadgeBad",
143
+ "triggerWrap": "VWh0dG_triggerWrap",
184
144
  "dashboardSubtitle": "VWh0dG_dashboardSubtitle",
185
- "triggerPopRow": "VWh0dG_triggerPopRow",
186
- "dashboardHead": "VWh0dG_dashboardHead",
187
- "heroGaugeLabel": "VWh0dG_heroGaugeLabel",
188
- "chartCrosshair": "VWh0dG_chartCrosshair",
189
- "budgetFillWarn": "VWh0dG_budgetFillWarn",
190
- "na": "VWh0dG_na",
191
- "rateBadgeBuiltin": "VWh0dG_rateBadgeBuiltin",
145
+ "kpiValue": "VWh0dG_kpiValue",
146
+ "dashboardRight": "VWh0dG_dashboardRight",
147
+ "peakAlertOff": "VWh0dG_peakAlertOff",
192
148
  "liveQuotaWarn": "VWh0dG_liveQuotaWarn",
149
+ "uncataloguedTag": "VWh0dG_uncataloguedTag",
150
+ "trigger": "VWh0dG_trigger",
193
151
  "subscriptionFillOver": "VWh0dG_subscriptionFillOver",
194
- "shareLegend": "VWh0dG_shareLegend",
195
- "heroSideLabel": "VWh0dG_heroSideLabel",
196
- "subscriptionCard": "VWh0dG_subscriptionCard",
197
- "chartTooltip": "VWh0dG_chartTooltip",
198
- "heatmapCell": "VWh0dG_heatmapCell",
199
- "budgetOverPulse": "VWh0dG_budgetOverPulse",
200
- "providerGroupList": "VWh0dG_providerGroupList",
201
- "shareSegAssistant": "VWh0dG_shareSegAssistant",
202
- "emptyRow": "VWh0dG_emptyRow",
203
- "shareItem": "VWh0dG_shareItem",
204
- "currencyButton": "VWh0dG_currencyButton",
205
- "triggerWrap": "VWh0dG_triggerWrap",
206
- "dashboard": "VWh0dG_dashboard",
207
- "tabButton": "VWh0dG_tabButton",
208
- "heroLabel": "VWh0dG_heroLabel",
209
- "triggerPop": "VWh0dG_triggerPop",
210
- "deltaUp": "VWh0dG_deltaUp",
211
- "rangeButtonActive": "VWh0dG_rangeButtonActive",
212
- "budgetFillOver": "VWh0dG_budgetFillOver",
213
- "chartTooltipDate": "VWh0dG_chartTooltipDate",
214
- "modelDot": "VWh0dG_modelDot",
215
- "subscriptionWindow": "VWh0dG_subscriptionWindow",
216
- "subscriptionWindowLabel": "VWh0dG_subscriptionWindowLabel",
217
- "heroGaugeArc": "VWh0dG_heroGaugeArc",
218
- "heroGaugeArcOver": "VWh0dG_heroGaugeArcOver",
219
152
  "subscriptionTrack": "VWh0dG_subscriptionTrack",
220
- "roundsFlagBadge": "VWh0dG_roundsFlagBadge",
221
- "uncataloguedTag": "VWh0dG_uncataloguedTag",
153
+ "costCol": "VWh0dG_costCol",
154
+ "budgetHint": "VWh0dG_budgetHint",
155
+ "providerGroupHead": "VWh0dG_providerGroupHead",
156
+ "rangeToggle": "VWh0dG_rangeToggle",
157
+ "chartTooltipSwatch": "VWh0dG_chartTooltipSwatch",
222
158
  "roundsEmpty": "VWh0dG_roundsEmpty",
223
- "heatmap": "VWh0dG_heatmap",
159
+ "shareSegAssistant": "VWh0dG_shareSegAssistant",
160
+ "chartLegendBar": "VWh0dG_chartLegendBar",
161
+ "trendPanel": "VWh0dG_trendPanel",
162
+ "modelCell": "VWh0dG_modelCell",
163
+ "pricingToggle": "VWh0dG_pricingToggle",
164
+ "healthBadge": "VWh0dG_healthBadge",
165
+ "budgetValue": "VWh0dG_budgetValue",
166
+ "providerGroupBalanceLabel": "VWh0dG_providerGroupBalanceLabel",
167
+ "peakAlertCorner": "VWh0dG_peakAlertCorner",
168
+ "modelName": "VWh0dG_modelName",
169
+ "na": "VWh0dG_na",
170
+ "heroValue": "VWh0dG_heroValue",
171
+ "budgetUnit": "VWh0dG_budgetUnit",
172
+ "dashboardIn": "VWh0dG_dashboardIn",
173
+ "kpiLabel": "VWh0dG_kpiLabel",
174
+ "switchKnob": "VWh0dG_switchKnob",
175
+ "peakAlertCenter": "VWh0dG_peakAlertCenter",
176
+ "panelTitle": "VWh0dG_panelTitle",
177
+ "chartSvg": "VWh0dG_chartSvg",
178
+ "rateBadge": "VWh0dG_rateBadge",
179
+ "roundsAxis": "VWh0dG_roundsAxis",
180
+ "bucketSummary": "VWh0dG_bucketSummary",
181
+ "tableScroll": "VWh0dG_tableScroll",
182
+ "heroGaugeLabel": "VWh0dG_heroGaugeLabel",
183
+ "triggerPop": "VWh0dG_triggerPop",
184
+ "liveCostBar": "VWh0dG_liveCostBar",
185
+ "subscriptionFill": "VWh0dG_subscriptionFill",
224
186
  "subscriptionFillWarn": "VWh0dG_subscriptionFillWarn",
187
+ "peakAlertPreview": "VWh0dG_peakAlertPreview",
188
+ "heroCurrency": "VWh0dG_heroCurrency",
189
+ "triggerPopBar": "VWh0dG_triggerPopBar",
190
+ "deltaDown": "VWh0dG_deltaDown",
191
+ "rangeButtonActive": "VWh0dG_rangeButtonActive",
192
+ "healthIdle": "VWh0dG_healthIdle",
193
+ "kpiGrid": "VWh0dG_kpiGrid",
194
+ "healthBad": "VWh0dG_healthBad",
195
+ "peakAlertClose": "VWh0dG_peakAlertClose",
196
+ "triggerPopBars": "VWh0dG_triggerPopBars",
197
+ "roundsBars": "VWh0dG_roundsBars",
198
+ "peakAlertCheck": "VWh0dG_peakAlertCheck",
199
+ "shareSeg": "VWh0dG_shareSeg",
200
+ "tabPanelIn": "VWh0dG_tabPanelIn",
201
+ "chartWrap": "VWh0dG_chartWrap",
202
+ "heatmapCellEmpty": "VWh0dG_heatmapCellEmpty",
203
+ "subscriptionHead": "VWh0dG_subscriptionHead",
204
+ "bucketStatValue": "VWh0dG_bucketStatValue",
205
+ "chartLegend": "VWh0dG_chartLegend",
206
+ "dashboard": "VWh0dG_dashboard",
207
+ "currencyToggle": "VWh0dG_currencyToggle",
208
+ "providerGroupName": "VWh0dG_providerGroupName",
209
+ "exportButton": "VWh0dG_exportButton",
210
+ "liveQuotaCrit": "VWh0dG_liveQuotaCrit",
211
+ "peakAlertCountdown": "VWh0dG_peakAlertCountdown",
212
+ "shareSegOff": "VWh0dG_shareSegOff",
213
+ "bandPrice": "VWh0dG_bandPrice",
214
+ "bucketThird": "VWh0dG_bucketThird",
215
+ "currencyButtonActive": "VWh0dG_currencyButtonActive",
216
+ "subscriptionStatus": "VWh0dG_subscriptionStatus",
217
+ "subscriptionPlan": "VWh0dG_subscriptionPlan",
218
+ "peakAlertPeak": "VWh0dG_peakAlertPeak",
219
+ "headTitleRow": "VWh0dG_headTitleRow",
220
+ "rateBadgeBuiltin": "VWh0dG_rateBadgeBuiltin",
221
+ "healthDot": "VWh0dG_healthDot",
222
+ "peakAlert": "VWh0dG_peakAlert",
223
+ "heroTop": "VWh0dG_heroTop",
224
+ "shareTrack": "VWh0dG_shareTrack",
225
+ "triggerBody": "VWh0dG_triggerBody",
226
+ "triggerAmount": "VWh0dG_triggerAmount",
227
+ "heroLabel": "VWh0dG_heroLabel",
228
+ "subscriptionReset": "VWh0dG_subscriptionReset",
229
+ "roundsBarFlagged": "VWh0dG_roundsBarFlagged",
230
+ "heroGaugeSvg": "VWh0dG_heroGaugeSvg",
231
+ "chartLine": "VWh0dG_chartLine",
232
+ "flatTag": "VWh0dG_flatTag",
233
+ "budgetControls": "VWh0dG_budgetControls",
234
+ "subscriptionName": "VWh0dG_subscriptionName",
225
235
  "heatmapHover": "VWh0dG_heatmapHover",
226
- "shareSegPeak": "VWh0dG_shareSegPeak",
227
- "hero": "VWh0dG_hero",
236
+ "heroGaugeArcOver": "VWh0dG_heroGaugeArcOver",
237
+ "bucketCost": "VWh0dG_bucketCost",
238
+ "liveTierOff": "VWh0dG_liveTierOff",
239
+ "heroSideValue": "VWh0dG_heroSideValue",
240
+ "roundsBarWrap": "VWh0dG_roundsBarWrap",
241
+ "tabButtonActive": "VWh0dG_tabButtonActive",
242
+ "triggerPopValue": "VWh0dG_triggerPopValue",
243
+ "chartDot": "VWh0dG_chartDot",
244
+ "bucketStatSub": "VWh0dG_bucketStatSub",
245
+ "budgetInputWrap": "VWh0dG_budgetInputWrap",
246
+ "chartCrosshair": "VWh0dG_chartCrosshair",
247
+ "triggerPopRow": "VWh0dG_triggerPopRow",
248
+ "triggerPopLabel": "VWh0dG_triggerPopLabel",
249
+ "subscriptionExhausted": "VWh0dG_subscriptionExhausted",
250
+ "peakAlertTag": "VWh0dG_peakAlertTag",
228
251
  "heroGaugePct": "VWh0dG_heroGaugePct",
252
+ "balanceCell": "VWh0dG_balanceCell",
253
+ "triggerSparkHot": "VWh0dG_triggerSparkHot",
254
+ "budgetTrack": "VWh0dG_budgetTrack",
255
+ "modelTableScroll": "VWh0dG_modelTableScroll",
256
+ "providerGroupBadge": "VWh0dG_providerGroupBadge",
257
+ "heroGaugeCenter": "VWh0dG_heroGaugeCenter",
258
+ "pricingTable": "VWh0dG_pricingTable",
229
259
  "numCol": "VWh0dG_numCol",
260
+ "settingsHead": "VWh0dG_settingsHead",
261
+ "peakAlertNum": "VWh0dG_peakAlertNum",
262
+ "roundsFlagMark": "VWh0dG_roundsFlagMark",
263
+ "chartBar": "VWh0dG_chartBar",
264
+ "peakAlertPanelBody": "VWh0dG_peakAlertPanelBody",
265
+ "providerGroupMeta": "VWh0dG_providerGroupMeta",
266
+ "budgetFillOver": "VWh0dG_budgetFillOver",
230
267
  "subscriptionGrid": "VWh0dG_subscriptionGrid",
231
- "roundsAxis": "VWh0dG_roundsAxis",
232
- "tabButtonActive": "VWh0dG_tabButtonActive",
233
- "dashboardBody": "VWh0dG_dashboardBody",
234
- "subscriptionExhausted": "VWh0dG_subscriptionExhausted",
235
- "healthBad": "VWh0dG_healthBad",
236
- "heroMain": "VWh0dG_heroMain",
237
- "subscriptionFill": "VWh0dG_subscriptionFill",
238
- "budgetInputWrap": "VWh0dG_budgetInputWrap"
268
+ "pricingChevronOpen": "VWh0dG_pricingChevronOpen",
269
+ "triggerIcon": "VWh0dG_triggerIcon",
270
+ "triggerRow": "VWh0dG_triggerRow",
271
+ "roundsBarColOff": "VWh0dG_roundsBarColOff",
272
+ "pricingTip": "VWh0dG_pricingTip",
273
+ "budget": "VWh0dG_budget",
274
+ "heroSide": "VWh0dG_heroSide",
275
+ "panelHint": "VWh0dG_panelHint",
276
+ "budgetHead": "VWh0dG_budgetHead",
277
+ "settingsHint": "VWh0dG_settingsHint",
278
+ "chartTooltip": "VWh0dG_chartTooltip",
279
+ "hero": "VWh0dG_hero",
280
+ "kpiTile": "VWh0dG_kpiTile"
239
281
  };
240
282
  //#endregion
241
283
  //#region src/client/plan-knowledge.ts
@@ -352,7 +394,8 @@ window.__ModuleLoader__.load({
352
394
  /** Default share of traffic assumed to fall in the peak band (0..1). */
353
395
  const DEFAULT_PEAK_SHARE = .5;
354
396
  /**
355
- * 高峰时段判定(北京时间,UTC+8,无夏令时):09:00–12:00、14:00–18:00。
397
+ * 工作日高峰时段判定(北京时间,UTC+8,无夏令时):09:00–12:00、14:00–18:00。
398
+ * 周末(周六/周日)北京全天为低谷,不调用本函数判定峰/平。
356
399
  * @param beijingHour - 北京时间的小时数(0–23)。
357
400
  */
358
401
  function isPeakHour(beijingHour) {
@@ -361,12 +404,26 @@ window.__ModuleLoader__.load({
361
404
  /**
362
405
  * 由时刻(epoch 毫秒)推断计费时段;时刻未知/非法时按高峰计(保守:未知
363
406
  * 时刻不低估成本,与社区 dsh-usage-chart 的 tierAt 语义一致)。
407
+ * 周末(北京时间周六/周日)全天不区分峰谷,统一按低谷价。
364
408
  * @param timeMs - Unix epoch 毫秒;null/undefined/NaN 视为未知。
365
409
  */
366
410
  function tierAt(timeMs) {
367
411
  if (timeMs === null || timeMs === void 0 || !Number.isFinite(timeMs)) return "peak";
412
+ if (isBeijingWeekend(timeMs)) return "offPeak";
368
413
  return isPeakHour((new Date(timeMs).getUTCHours() + 8) % 24) ? "peak" : "offPeak";
369
414
  }
415
+ /** 时刻是否落在北京时间周末(周六/周日)。 */
416
+ function isBeijingWeekend(timeMs) {
417
+ const day = new Date(timeMs + 8 * 36e5).getUTCDay();
418
+ return day === 0 || day === 6;
419
+ }
420
+ /** 距下一个工作日(周一)北京时间 09:00 峰时的毫秒数:周末全天低谷的下一档。 */
421
+ function nextWeekdayPeakInMs(nowMs) {
422
+ const bj = new Date(nowMs + 8 * 36e5);
423
+ const day = bj.getUTCDay();
424
+ const elapsed = bj.getUTCHours() * 36e5 + bj.getUTCMinutes() * 6e4 + bj.getUTCSeconds() * 1e3 + bj.getUTCMilliseconds();
425
+ return (day === 0 ? 1 : 2) * 864e5 - elapsed + 9 * 36e5;
426
+ }
370
427
  /** 峰谷切换边界(北京时间的当日分钟数):09:00 / 12:00 / 14:00 / 18:00。 */
371
428
  const TIER_BOUNDARY_MINUTES = [
372
429
  540,
@@ -384,6 +441,10 @@ window.__ModuleLoader__.load({
384
441
  * @returns 当前档位与到下一个切换边界的毫秒数。
385
442
  */
386
443
  function tierCountdown(nowMs) {
444
+ if (isBeijingWeekend(nowMs)) return {
445
+ tier: "offPeak",
446
+ nextSwitchInMs: nextWeekdayPeakInMs(nowMs)
447
+ };
387
448
  const dayMs = beijingMillisOfDay(nowMs);
388
449
  for (const boundary of TIER_BOUNDARY_MINUTES) {
389
450
  const boundaryMs = boundary * 6e4;
@@ -948,9 +1009,55 @@ window.__ModuleLoader__.load({
948
1009
  "k3": "kimi-k3",
949
1010
  "kimi-k3": "kimi-k3"
950
1011
  };
1012
+ /**
1013
+ * 模型 id 归一化:小写、去括号附注(如 `gpt5.6 luna(go)` 只看主体)、再去所有
1014
+ * 非字母数字分隔符(空格 / 横杠 / 点 / 下划线)。用于日志里的模型 id 与计费
1015
+ * 目录键做宽松匹配,提升「大小写/分隔符差异导致未收录」的识别率。
1016
+ * @param id - 原始模型 id(日志或目录键)。
1017
+ * @returns 归一化键(字母数字小写串)。
1018
+ */
1019
+ function canonModelId(id) {
1020
+ return String(id).toLowerCase().replace(/\([^)]*\)/g, "").replace(/[^a-z0-9]+/g, "");
1021
+ }
1022
+ /**
1023
+ * 目录常量键的归一化索引:归一化键 → 真实计费键。只索引静态来源(内置目录、
1024
+ * 别名表、dsh-spend 兜底键);models.dev 补充条目是运行时注入,单独实时匹配。
1025
+ */
1026
+ const CATALOG_CANON_INDEX = (() => {
1027
+ const map = /* @__PURE__ */ new Map();
1028
+ const add = (candidate, target) => {
1029
+ const canon = canonModelId(candidate);
1030
+ if (canon !== "" && !map.has(canon)) map.set(canon, target);
1031
+ };
1032
+ for (const entry of MODEL_CATALOG) add(entry.key, entry.key);
1033
+ for (const [alias, key] of Object.entries(MODEL_KEY_ALIASES)) add(alias, key);
1034
+ for (const rate of FALLBACK_RATES) add(rate.key, rate.key);
1035
+ return map;
1036
+ })();
1037
+ /**
1038
+ * 解析真实日志模型 id → 计费目录键。先精确别名映射(既有行为);未命中时做
1039
+ * 归一化匹配(忽略大小写/分隔符/括号附注),命中内置目录 / 别名目标 / 兜底键 /
1040
+ * models.dev 补充键即返回其真实键;完全未知时保持原样(回退 other,不计费)。
1041
+ * 供聚合层折叠与客户端渲染共用,两侧一致。
1042
+ * @param id - 真实模型 id(日志里出现的形式)。
1043
+ * @returns 计费目录键。
1044
+ */
1045
+ function resolveCatalogKey(id) {
1046
+ const exact = MODEL_KEY_ALIASES[id] ?? id;
1047
+ if (exact === id) {
1048
+ const canon = canonModelId(id);
1049
+ if (canon !== "") {
1050
+ const hit = CATALOG_CANON_INDEX.get(canon);
1051
+ if (hit !== void 0) return hit;
1052
+ const extraHit = (liveExtraModels ?? []).find((item) => canonModelId(item.key) === canon);
1053
+ if (extraHit !== void 0) return extraHit.key;
1054
+ }
1055
+ }
1056
+ return exact;
1057
+ }
951
1058
  /** 取一个计费键的实时单价(实时覆盖 > dsh-spend 官方价兜底)。 */
952
1059
  function livePriceOf(key) {
953
- const resolved = MODEL_KEY_ALIASES[key] ?? key;
1060
+ const resolved = resolveCatalogKey(key);
954
1061
  const live = livePrices?.[resolved];
955
1062
  if (live !== void 0) return live;
956
1063
  const fallback = FALLBACK_RATES.find((rate) => rate.key.toLowerCase() === resolved.toLowerCase());
@@ -963,7 +1070,7 @@ window.__ModuleLoader__.load({
963
1070
  }
964
1071
  /** Lookup a model by its stats key; falls back to the generic `other` entry. */
965
1072
  function modelOf(key) {
966
- const resolved = MODEL_KEY_ALIASES[key] ?? key;
1073
+ const resolved = resolveCatalogKey(key);
967
1074
  const found = MODEL_CATALOG.find((entry) => entry.key === resolved);
968
1075
  const extra = liveExtraModels?.find((item) => item.key === resolved);
969
1076
  const base = found ?? (extra !== void 0 ? extraEntryOf(extra) : (() => {
@@ -1009,7 +1116,7 @@ window.__ModuleLoader__.load({
1009
1116
  for (const model of liveCatalogModels ?? []) {
1010
1117
  const rawKey = model.id.toLowerCase();
1011
1118
  if ((() => {
1012
- const aliasKey = MODEL_KEY_ALIASES[model.id] ?? model.id;
1119
+ const aliasKey = resolveCatalogKey(model.id);
1013
1120
  return MODEL_CATALOG.find((item) => item.key === aliasKey);
1014
1121
  })() !== void 0) continue;
1015
1122
  if (known.has(rawKey)) continue;
@@ -1030,7 +1137,7 @@ window.__ModuleLoader__.load({
1030
1137
  }
1031
1138
  };
1032
1139
  else entry = {
1033
- key: MODEL_KEY_ALIASES[model.id] ?? model.id,
1140
+ key: resolveCatalogKey(model.id),
1034
1141
  name: model.name ?? model.id,
1035
1142
  provider: model.provider,
1036
1143
  colorVar: "dsw-static-neutral-400",
@@ -1452,10 +1559,12 @@ window.__ModuleLoader__.load({
1452
1559
  children: visible.map((round) => {
1453
1560
  const flagged = flagKey.has(`${round.sessionId}:${round.turn}`);
1454
1561
  const height = Math.max(1, round.cost / maxCost * 100);
1562
+ const peak = tierAt(round.startedAt) === "peak";
1455
1563
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1456
- className: UsageBilling_module_css_default.roundsBarCol,
1564
+ className: clsx(UsageBilling_module_css_default.roundsBarCol, peak ? UsageBilling_module_css_default.roundsBarColPeak : UsageBilling_module_css_default.roundsBarColOff),
1457
1565
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1458
1566
  className: UsageBilling_module_css_default.roundsBarLabel,
1567
+ style: { bottom: `${height}%` },
1459
1568
  children: money(round.cost)
1460
1569
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1461
1570
  className: UsageBilling_module_css_default.roundsBarWrap,
@@ -1828,6 +1937,7 @@ window.__ModuleLoader__.load({
1828
1937
  "billing.todayRate": "今日汇率",
1829
1938
  "billing.rateLive": "实时",
1830
1939
  "billing.rateBuiltin": "内置",
1940
+ "billing.pricingTip": "DeepSeek 模型自北京时间 2026-08-23(周日)00:00 起:工作日高峰 9-12 / 14-18(×2),周末(周六 / 周日)全天低谷价;双价单元格按峰 / 谷展示,费用按调用时刻计。",
1831
1941
  "billing.balance": "余额",
1832
1942
  "billing.balanceUnconfigured": "未配置",
1833
1943
  "billing.balanceUnauthorized": "密钥无效",
@@ -1870,6 +1980,13 @@ window.__ModuleLoader__.load({
1870
1980
  "billing.tabProviders": "明细",
1871
1981
  "billing.tabDetails": "统计",
1872
1982
  "billing.tabPricing": "费率",
1983
+ "billing.tabSettings": "设置",
1984
+ "billing.settingsHead": "偏好设置",
1985
+ "billing.settingsHint": "管理与计费相关的偏好",
1986
+ "billing.budgetHint": "设置月度上限,用于本月预计与超支分段提醒",
1987
+ "billing.peakAlertHint": "在切档前弹窗提醒,可选同步系统通知",
1988
+ "billing.peakAlertDescPeak": "高峰价生效,不急的调用可稍候",
1989
+ "billing.peakAlertDescOff": "价格减半省钱窗口已开启",
1873
1990
  "billing.export": "导出",
1874
1991
  "billing.exportCsvDay": "按日 CSV",
1875
1992
  "billing.exportCsvSession": "按会话 CSV",
@@ -1888,13 +2005,28 @@ window.__ModuleLoader__.load({
1888
2005
  "billing.tierToOff": "后转平价",
1889
2006
  "billing.tierAlertEnterPeak": "{minutes} 分钟后进入峰时(DeepSeek 高峰价 ×2),不急的调用可稍等",
1890
2007
  "billing.tierAlertEnterOff": "{minutes} 分钟后进入平价(价格减半)",
2008
+ "billing.peakAlertTitlePeak": "即将进入高峰价",
2009
+ "billing.peakAlertTitleOff": "即将进入平价",
2010
+ "billing.peakAlert": "峰谷切换提醒",
2011
+ "billing.peakAlertLeadMin": "提前量(分钟)",
2012
+ "billing.peakAlertPosCorner": "右下角",
2013
+ "billing.peakAlertPosCenter": "屏幕居中",
2014
+ "billing.peakAlertModePeak": "仅进入峰时",
2015
+ "billing.peakAlertModeOff": "仅进入平价",
2016
+ "billing.peakAlertModeBoth": "峰与谷都提醒",
2017
+ "billing.peakAlertWebNotify": "同时发系统通知",
2018
+ "billing.peakAlertPreview": "预览提醒",
1891
2019
  "billing.planTypeCode": "订阅制",
1892
2020
  "billing.planTypeToken": "按量",
1893
2021
  "billing.subscriptionFeePerMonth": "{amount}/月",
1894
2022
  "billing.triggerToday": "今日",
1895
2023
  "billing.triggerMonth": "当月",
1896
2024
  "billing.subscriptionIncluded": "订阅包含",
1897
- "billing.free": "免费"
2025
+ "billing.free": "免费",
2026
+ "billing.official": "官方",
2027
+ "billing.thirdParty": "三方",
2028
+ "billing.officialCost": "官方费用",
2029
+ "billing.thirdPartyCost": "三方费用"
1898
2030
  };
1899
2031
  const en = {
1900
2032
  "billing.title": "Usage",
@@ -1946,6 +2078,7 @@ window.__ModuleLoader__.load({
1946
2078
  "billing.todayRate": "Today rate",
1947
2079
  "billing.rateLive": "Live",
1948
2080
  "billing.rateBuiltin": "Built-in",
2081
+ "billing.pricingTip": "DeepSeek models: from 2026-08-23 (Sun) 00:00 Beijing, weekdays peak 9-12 / 14-18 (×2), weekends (Sat/Sun) all-day off-peak; cells show peak/off-peak price, billed at call time.",
1949
2082
  "billing.balance": "Balance",
1950
2083
  "billing.balanceUnconfigured": "Not set",
1951
2084
  "billing.balanceUnauthorized": "Bad key",
@@ -1988,6 +2121,13 @@ window.__ModuleLoader__.load({
1988
2121
  "billing.tabProviders": "Details",
1989
2122
  "billing.tabDetails": "Stats",
1990
2123
  "billing.tabPricing": "Rates",
2124
+ "billing.tabSettings": "Settings",
2125
+ "billing.settingsHead": "Preferences",
2126
+ "billing.settingsHint": "Manage billing-related preferences",
2127
+ "billing.budgetHint": "Set a monthly cap for projections and tier alerts",
2128
+ "billing.peakAlertHint": "Alert before a tier switch, optionally via system notification",
2129
+ "billing.peakAlertDescPeak": "Peak pricing active — non-urgent calls can wait",
2130
+ "billing.peakAlertDescOff": "Off-peak savings window is on",
1991
2131
  "billing.export": "Export",
1992
2132
  "billing.exportCsvDay": "Daily CSV",
1993
2133
  "billing.exportCsvSession": "Sessions CSV",
@@ -2006,15 +2146,174 @@ window.__ModuleLoader__.load({
2006
2146
  "billing.tierToOff": "until off-peak",
2007
2147
  "billing.tierAlertEnterPeak": "Peak pricing (2x) starts in {minutes} min — non-urgent calls can wait",
2008
2148
  "billing.tierAlertEnterOff": "Off-peak pricing (50% off) starts in {minutes} min",
2149
+ "billing.peakAlertTitlePeak": "Peak pricing incoming",
2150
+ "billing.peakAlertTitleOff": "Off-peak incoming",
2151
+ "billing.peakAlert": "Peak/off-peak alert",
2152
+ "billing.peakAlertLeadMin": "Lead time (min)",
2153
+ "billing.peakAlertPosCorner": "Bottom-right",
2154
+ "billing.peakAlertPosCenter": "Center",
2155
+ "billing.peakAlertModePeak": "Entering peak only",
2156
+ "billing.peakAlertModeOff": "Entering off-peak only",
2157
+ "billing.peakAlertModeBoth": "Both",
2158
+ "billing.peakAlertWebNotify": "Also send system notification",
2159
+ "billing.peakAlertPreview": "Preview alert",
2009
2160
  "billing.planTypeCode": "Subscription",
2010
2161
  "billing.planTypeToken": "Usage",
2011
2162
  "billing.subscriptionFeePerMonth": "{amount}/mo",
2012
2163
  "billing.triggerToday": "Today",
2013
2164
  "billing.triggerMonth": "This month",
2014
2165
  "billing.subscriptionIncluded": "Included",
2015
- "billing.free": "Free"
2166
+ "billing.free": "Free",
2167
+ "billing.official": "Official",
2168
+ "billing.thirdParty": "Third-party",
2169
+ "billing.officialCost": "Official cost",
2170
+ "billing.thirdPartyCost": "Third-party cost"
2016
2171
  };
2017
2172
  //#endregion
2173
+ //#region src/client/provider-display.ts
2174
+ /** 中文厂商显示名 → 英文显示名;未收录的中文名不在表内,原样返回。 */
2175
+ const PROVIDER_NAMES_EN = {
2176
+ "智谱 AI": "Zhipu AI",
2177
+ "阿里通义": "Alibaba Qwen",
2178
+ "字节豆包": "ByteDance Doubao",
2179
+ "月之暗面": "Moonshot AI",
2180
+ "小米": "Xiaomi",
2181
+ "百度文心": "Baidu ERNIE",
2182
+ "腾讯混元": "Tencent Hunyuan",
2183
+ "零一万物": "01.AI",
2184
+ "阶跃星辰": "StepFun",
2185
+ "科大讯飞": "iFlytek Spark",
2186
+ "商汤": "SenseNova",
2187
+ "百川智能": "Baichuan",
2188
+ "小米 Token Plan(海外)": "Xiaomi Token Plan (Global)",
2189
+ "小米 Token Plan(国内)": "Xiaomi Token Plan (CN)",
2190
+ "小米 Token Plan(新加坡)": "Xiaomi Token Plan (SG)",
2191
+ "火山引擎 Token Plan": "Volcengine Token Plan",
2192
+ "火山方舟 Token Plan": "Volcengine Ark Token Plan",
2193
+ "豆包 Token Plan": "Doubao Token Plan",
2194
+ "百度文心 Plan": "Baidu ERNIE Plan"
2195
+ };
2196
+ /**
2197
+ * 把厂商显示名按界面语言本地化:中文名映射成英文,其余(已是英文 / 未收录 /
2198
+ * 未知)原样返回。仅在渲染层调用,不影响数据层的中文 key 匹配。
2199
+ * @param name - 数据层返回的厂商显示名(多为中文)。
2200
+ * @param lang - 当前界面语言(跟随币种)。
2201
+ * @returns 本地化后的显示名。
2202
+ */
2203
+ function localizeProviderName(name, lang) {
2204
+ if (lang === "en") return PROVIDER_NAMES_EN[name] ?? name;
2205
+ return name;
2206
+ }
2207
+ //#endregion
2208
+ //#region src/client/peak-alert.ts
2209
+ /**
2210
+ * 峰谷切换提醒(增强版)纯逻辑:偏好持久化 + 切档前命中判定。
2211
+ *
2212
+ * 参照 dsh-cost-meter 的 peak/off-peak 提醒:在距下次「进入峰时 / 进入平价」
2213
+ * 不足提前量时,弹可视化色条浮层 + 可选的系统通知。偏好经 localStorage 持久化
2214
+ * (默认关闭,用户到面板设置开启);「同一切换点只提醒一次」由 budget store 的
2215
+ * `lastTierSwitchAt` 承担(与原系统通知共用一份去重,避免一条切换提醒弹两次)。
2216
+ */
2217
+ /** 配置持久化 key。 */
2218
+ const PEAK_ALERT_KEY = "dsh-billing-peak-alert-v1";
2219
+ /** 默认配置:关、2 分钟提前、右下角、开系统通知、峰与谷都提醒。 */
2220
+ const DEFAULT_PEAK_ALERT_CONFIG = {
2221
+ enabled: false,
2222
+ leadMin: 2,
2223
+ position: "bottom-right",
2224
+ webNotify: true,
2225
+ mode: "both"
2226
+ };
2227
+ /** 读取本地偏好(缺失/损坏回退默认,字段宽松校验)。 */
2228
+ function loadPeakAlertConfig() {
2229
+ try {
2230
+ const raw = localStorage.getItem(PEAK_ALERT_KEY);
2231
+ if (raw === null) return { ...DEFAULT_PEAK_ALERT_CONFIG };
2232
+ const parsed = JSON.parse(raw);
2233
+ const mode = parsed.mode === "peak" || parsed.mode === "offPeak" ? parsed.mode : DEFAULT_PEAK_ALERT_CONFIG.mode;
2234
+ const position = parsed.position === "center" ? "center" : "bottom-right";
2235
+ return {
2236
+ enabled: parsed.enabled === true,
2237
+ leadMin: typeof parsed.leadMin === "number" && Number.isFinite(parsed.leadMin) ? Math.min(30, Math.max(1, Math.round(parsed.leadMin))) : DEFAULT_PEAK_ALERT_CONFIG.leadMin,
2238
+ position,
2239
+ webNotify: parsed.webNotify !== false,
2240
+ mode
2241
+ };
2242
+ } catch {
2243
+ return { ...DEFAULT_PEAK_ALERT_CONFIG };
2244
+ }
2245
+ }
2246
+ /** 保存偏好;存储失败静默(降级为关闭,不影响其它能力)。 */
2247
+ function savePeakAlertConfig(config) {
2248
+ try {
2249
+ localStorage.setItem(PEAK_ALERT_KEY, JSON.stringify(config));
2250
+ } catch {}
2251
+ }
2252
+ /**
2253
+ * 计算是否需要提醒:已启用、距切换不足提前量、按模式过滤、且该切换点未提醒过。
2254
+ * 导出供测试:纯函数。
2255
+ * @param nowMs - 当前时刻(epoch 毫秒)。
2256
+ * @param config - 峰谷提醒偏好。
2257
+ * @param lastAlertedAt - 上次提醒过的切换点时刻(budget store 的 lastTierSwitchAt);同点跳过。
2258
+ * @returns 命中(含即将进入的档位与切换时刻),否则 null。
2259
+ */
2260
+ function computePeakAlert(nowMs, config, lastAlertedAt) {
2261
+ if (!config.enabled) return null;
2262
+ const upcoming = upcomingTierSwitch(nowMs, config.leadMin * 6e4);
2263
+ if (upcoming === null) return null;
2264
+ if (config.mode === "peak" && upcoming.entering !== "peak") return null;
2265
+ if (config.mode === "offPeak" && upcoming.entering !== "offPeak") return null;
2266
+ if (upcoming.atMs === lastAlertedAt) return null;
2267
+ return upcoming;
2268
+ }
2269
+ //#endregion
2270
+ //#region src/client/PeakAlertBanner.tsx
2271
+ /**
2272
+ * 峰谷切换提醒浮层:切档前状态条(右下角或居中)。用 `position: fixed` 即可在
2273
+ * 任意宿主容器内覆盖整个视口,因此不需要 portal。布局为「档位徽标 + 大号等宽
2274
+ * 倒计时 + 一句说明 + 关闭」,克制冷调、无重力阴影。渲染是受控的:父组件把命中
2275
+ * (hit)与偏好传入,显示剩余分钟并在切换后消失。
2276
+ */
2277
+ /** 渲染一个切档前提醒状态条。 */
2278
+ function PeakAlertBanner({ hit, config, t, onDismiss }) {
2279
+ const [nowMs, setNowMs] = (0, react.useState)(() => Date.now());
2280
+ (0, react.useEffect)(() => {
2281
+ const timer = setInterval(() => setNowMs(Date.now()), 1e3);
2282
+ return () => clearInterval(timer);
2283
+ }, []);
2284
+ if (nowMs >= hit.atMs) return null;
2285
+ const minutes = Math.max(1, Math.round((hit.atMs - nowMs) / 6e4));
2286
+ const entering = hit.entering;
2287
+ const tag = entering === "peak" ? t("billing.tierPeak") : t("billing.tierOff");
2288
+ const desc = entering === "peak" ? t("billing.peakAlertDescPeak") : t("billing.peakAlertDescOff");
2289
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2290
+ className: clsx(UsageBilling_module_css_default.peakAlert, entering === "peak" ? UsageBilling_module_css_default.peakAlertPeak : UsageBilling_module_css_default.peakAlertOff, config.position === "center" ? UsageBilling_module_css_default.peakAlertCenter : UsageBilling_module_css_default.peakAlertCorner),
2291
+ "data-testid": "billing-peak-alert",
2292
+ role: "alert",
2293
+ children: [
2294
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2295
+ className: UsageBilling_module_css_default.peakAlertTag,
2296
+ children: tag
2297
+ }),
2298
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2299
+ className: UsageBilling_module_css_default.peakAlertCountdown,
2300
+ children: [minutes, "m"]
2301
+ }),
2302
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2303
+ className: UsageBilling_module_css_default.peakAlertText,
2304
+ children: desc
2305
+ }),
2306
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2307
+ type: "button",
2308
+ className: UsageBilling_module_css_default.peakAlertClose,
2309
+ onClick: onDismiss,
2310
+ "aria-label": t("billing.close"),
2311
+ children: "×"
2312
+ })
2313
+ ]
2314
+ });
2315
+ }
2316
+ //#endregion
2018
2317
  //#region src/client/UsageBilling.tsx
2019
2318
  /**
2020
2319
  * UsageBilling: sidebar footer trigger + full billing dashboard modal.
@@ -2030,9 +2329,9 @@ window.__ModuleLoader__.load({
2030
2329
  /** 会话明细面板最多展示的行数(完整长尾在服务端另有一层封顶)。 */
2031
2330
  const SESSION_DISPLAY_LIMIT = 20;
2032
2331
  /**
2033
- * Tab 定义(顺序即渲染顺序):概览=主数字/预算/KPI/热力图,趋势=趋势图/每轮费用,
2034
- * 明细=厂商计费与订阅,统计=工作区/会话明细,费率=模型单价表。导出供测试断言
2035
- * tab 与文案 key 对齐、decor 锚点落在正确分区。
2332
+ * Tab 定义(顺序即渲染顺序):概览=主数字/KPI/热力图,趋势=趋势图/每轮费用,
2333
+ * 明细=厂商计费与订阅,统计=工作区/会话明细,费率=模型单价表,设置=预算与峰谷提醒。
2334
+ * 导出供测试断言 tab 与文案 key 对齐、decor 锚点落在正确分区。
2036
2335
  */
2037
2336
  const DASHBOARD_TABS = [
2038
2337
  {
@@ -2054,6 +2353,10 @@ window.__ModuleLoader__.load({
2054
2353
  {
2055
2354
  id: "pricing",
2056
2355
  labelKey: "billing.tabPricing"
2356
+ },
2357
+ {
2358
+ id: "settings",
2359
+ labelKey: "billing.tabSettings"
2057
2360
  }
2058
2361
  ];
2059
2362
  /** 项目名取 cwd 的末级目录;无 cwd 时由调用方回退为 em dash。 */
@@ -2452,21 +2755,9 @@ window.__ModuleLoader__.load({
2452
2755
  stroke: "currentColor",
2453
2756
  "aria-hidden": "true",
2454
2757
  children: [
2455
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
2456
- x: "2.5",
2457
- y: "5",
2458
- width: "19",
2459
- height: "14",
2460
- rx: "2.5"
2461
- }),
2462
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2.5 9.5h19" }),
2463
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
2464
- x: "6",
2465
- y: "12",
2466
- width: "4",
2467
- height: "3.5",
2468
- rx: "0.75"
2469
- })
2758
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M4 7h16v11H4z" }),
2759
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M4 10h16" }),
2760
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M8 14h3" })
2470
2761
  ]
2471
2762
  });
2472
2763
  if (!wide) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -2477,6 +2768,8 @@ window.__ModuleLoader__.load({
2477
2768
  title: `${t("billing.title")} · ${formatMoney(monthCost)}`,
2478
2769
  children: cardIcon
2479
2770
  });
2771
+ const sparkMax = Math.max(...days.map((d) => d.cost), 0);
2772
+ const sparkHeights = days.map((d) => sparkMax > 0 ? 4 + d.cost / sparkMax * 12 : 4);
2480
2773
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2481
2774
  className: UsageBilling_module_css_default.triggerWrap,
2482
2775
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
@@ -2484,7 +2777,7 @@ window.__ModuleLoader__.load({
2484
2777
  className: UsageBilling_module_css_default.trigger,
2485
2778
  "data-testid": "billing-trigger",
2486
2779
  onClick: onOpen,
2487
- title: `${t("billing.title")} · ${t("billing.triggerMonth")} ${formatMoney(monthCost)}`,
2780
+ title: `${t("billing.title")} · ${formatMoney(monthCost)}`,
2488
2781
  children: [
2489
2782
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2490
2783
  className: UsageBilling_module_css_default.triggerIcon,
@@ -2492,27 +2785,36 @@ window.__ModuleLoader__.load({
2492
2785
  children: cardIcon
2493
2786
  }),
2494
2787
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2495
- className: UsageBilling_module_css_default.triggerToday,
2496
- "data-testid": "billing-trigger-today",
2497
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2498
- className: UsageBilling_module_css_default.triggerMeta,
2499
- children: t("billing.triggerToday")
2500
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2501
- className: UsageBilling_module_css_default.triggerAmount,
2502
- children: formatMoney(todayCost)
2503
- })]
2504
- }),
2505
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: UsageBilling_module_css_default.triggerDivider }),
2506
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2507
- className: UsageBilling_module_css_default.triggerMonth,
2508
- "data-testid": "billing-trigger-month",
2509
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2510
- className: UsageBilling_module_css_default.triggerMeta,
2511
- children: t("billing.triggerMonth")
2512
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2513
- className: UsageBilling_module_css_default.triggerAmountSub,
2514
- children: formatMoney(monthCost)
2788
+ className: UsageBilling_module_css_default.triggerBody,
2789
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2790
+ className: UsageBilling_module_css_default.triggerRow,
2791
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2792
+ className: UsageBilling_module_css_default.triggerMeta,
2793
+ children: t("billing.triggerMonth")
2794
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2795
+ className: UsageBilling_module_css_default.triggerAmount,
2796
+ children: formatMoney(monthCost)
2797
+ })]
2798
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2799
+ className: UsageBilling_module_css_default.triggerSub,
2800
+ "data-testid": "billing-trigger-today",
2801
+ children: [
2802
+ t("billing.triggerToday"),
2803
+ " ",
2804
+ formatMoney(todayCost),
2805
+ " · ",
2806
+ weekCost > 0 ? `${t("billing.weekCost")} ${formatMoney(weekCost)}` : ""
2807
+ ]
2515
2808
  })]
2809
+ }),
2810
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2811
+ className: UsageBilling_module_css_default.triggerSpark,
2812
+ "data-testid": "billing-trigger-spark",
2813
+ "aria-hidden": "true",
2814
+ children: sparkHeights.map((h, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2815
+ className: index === sparkHeights.length - 1 ? UsageBilling_module_css_default.triggerSparkHot : UsageBilling_module_css_default.triggerSparkBar,
2816
+ style: { height: `${h}px` }
2817
+ }, days[index]?.date ?? String(index)))
2516
2818
  })
2517
2819
  ]
2518
2820
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
@@ -2552,13 +2854,10 @@ window.__ModuleLoader__.load({
2552
2854
  }),
2553
2855
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2554
2856
  className: UsageBilling_module_css_default.triggerPopBars,
2555
- children: (() => {
2556
- const max = Math.max(...days.map((d) => d.cost), 0);
2557
- return days.map((d) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2558
- className: UsageBilling_module_css_default.triggerPopBar,
2559
- style: { height: `${max > 0 ? 4 + d.cost / max * 18 : 4}px` }
2560
- }, d.date));
2561
- })()
2857
+ children: sparkHeights.map((_h, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2858
+ className: UsageBilling_module_css_default.triggerPopBar,
2859
+ style: { height: `${sparkMax > 0 ? 4 + days[index].cost / sparkMax * 18 : 4}px` }
2860
+ }, days[index]?.date ?? String(index)))
2562
2861
  })
2563
2862
  ]
2564
2863
  })]
@@ -2568,12 +2867,14 @@ window.__ModuleLoader__.load({
2568
2867
  * The centered billing dashboard modal.
2569
2868
  * @param props - stats, locale function, close handler, model health, balances, renderSlot.
2570
2869
  */
2571
- function BillingDashboard({ stats, t, onClose, health, balances, quotas, currency, onCurrency, turns, renderSlot, budgetEnabled, budgetAmount, onToggleBudget, onBudgetAmount }) {
2870
+ function BillingDashboard({ stats, t, onClose, health, balances, quotas, currency, onCurrency, turns, renderSlot, budgetEnabled, budgetAmount, onToggleBudget, onBudgetAmount, peakConfig, onPeakConfig, onPreviewPeak }) {
2572
2871
  const { total, byModel, byDay } = stats;
2573
2872
  const [tab, setTab] = (0, react.useState)("overview");
2574
2873
  const [trendDays, setTrendDays] = (0, react.useState)(7);
2575
2874
  const rateInfo = getRateInfo();
2576
2875
  const money = (cny) => formatMoney(currency === "usd" ? cnyToUsd(cny) : cny, currency);
2876
+ const lang = currency === "usd" ? "en" : "zh";
2877
+ const providerName = (name) => localizeProviderName(name, lang);
2577
2878
  const unitMoney = (price, native) => price === 0 ? t("billing.free") : formatUnitPrice(convertUnitPrice(price, native, currency, rateInfo.rate), currency === "usd" ? "USD" : "CNY");
2578
2879
  const roundFlags = (0, react.useMemo)(() => flagAnomalies([...turns].reverse()), [turns]);
2579
2880
  const peakShare = (0, react.useMemo)(() => peakOffpeakCost(turns), [turns]);
@@ -2715,12 +3016,33 @@ window.__ModuleLoader__.load({
2715
3016
  plan: data.plan === true,
2716
3017
  ...data.cost > 0 ? { actual: data.cost } : {},
2717
3018
  uncatalogued,
2718
- estimatedPricing: entry.estimated === true
3019
+ estimatedPricing: entry.estimated === true,
3020
+ officialCalls: data.officialCalls ?? 0,
3021
+ officialCost: data.officialCost ?? 0
2719
3022
  };
2720
3023
  }).sort((a, b) => (b.actual ?? b.estimated) - (a.actual ?? a.estimated)).map((row, index) => ({
2721
3024
  ...row,
2722
3025
  color: CHART_PALETTE[index % CHART_PALETTE.length] ?? "#8b95a3"
2723
3026
  })), [byModel]);
3027
+ const bucketSummary = (0, react.useMemo)(() => {
3028
+ let officialCost = 0;
3029
+ let officialCalls = 0;
3030
+ let thirdCalls = 0;
3031
+ for (const row of modelRows) {
3032
+ const official = row.officialCost;
3033
+ if (official > 0) officialCost += official;
3034
+ officialCalls += row.officialCalls;
3035
+ thirdCalls += Math.max(0, row.calls - row.officialCalls);
3036
+ }
3037
+ const thirdCost = Math.max(0, modelRows.reduce((sum, r) => sum + (r.actual ?? 0), 0) - officialCost);
3038
+ if (officialCost <= 0 && thirdCost <= 0 && officialCalls <= 0 && thirdCalls <= 0) return void 0;
3039
+ return {
3040
+ officialCost,
3041
+ officialCalls,
3042
+ thirdCost,
3043
+ thirdCalls
3044
+ };
3045
+ }, [modelRows]);
2724
3046
  const providerGroups = (0, react.useMemo)(() => {
2725
3047
  const subscriptionsByVendor = /* @__PURE__ */ new Map();
2726
3048
  for (const quota of quotas) {
@@ -2882,53 +3204,62 @@ window.__ModuleLoader__.load({
2882
3204
  children: [
2883
3205
  renderSlot("billing.dashboard.decor", { position: "hero" }),
2884
3206
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2885
- className: UsageBilling_module_css_default.heroMain,
2886
- children: [
2887
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2888
- className: UsageBilling_module_css_default.heroLabel,
2889
- children: t("billing.monthCost")
2890
- }),
2891
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2892
- className: UsageBilling_module_css_default.heroValue,
2893
- children: money(monthCost)
2894
- }),
2895
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2896
- className: UsageBilling_module_css_default.heroMeta,
2897
- children: [
2898
- monthCalls.toLocaleString(),
2899
- " ",
2900
- t("billing.calls")
2901
- ]
2902
- })
2903
- ]
2904
- }),
2905
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2906
- className: UsageBilling_module_css_default.heroGauge,
2907
- "data-testid": "billing-hero-gauge",
2908
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
2909
- className: UsageBilling_module_css_default.heroGaugeSvg,
2910
- viewBox: "0 0 120 120",
2911
- "aria-hidden": "true",
2912
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
2913
- className: UsageBilling_module_css_default.heroGaugeTrack,
2914
- cx: "60",
2915
- cy: "60",
2916
- r: "52"
2917
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
2918
- className: clsx(UsageBilling_module_css_default.heroGaugeArc, heroGauge.over && UsageBilling_module_css_default.heroGaugeArcOver),
2919
- cx: "60",
2920
- cy: "60",
2921
- r: "52",
2922
- style: { strokeDasharray: `${heroGauge.pct / 100 * 326.7} 326.7` }
2923
- })]
2924
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2925
- className: UsageBilling_module_css_default.heroGaugeCenter,
2926
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2927
- className: clsx(UsageBilling_module_css_default.heroGaugePct, heroGauge.over && UsageBilling_module_css_default.heroGaugePctOver),
2928
- children: [heroGauge.pct.toFixed(0), "%"]
2929
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2930
- className: UsageBilling_module_css_default.heroGaugeLabel,
2931
- children: heroGauge.label
3207
+ className: UsageBilling_module_css_default.heroTop,
3208
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3209
+ className: UsageBilling_module_css_default.heroMain,
3210
+ children: [
3211
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3212
+ className: UsageBilling_module_css_default.heroLabel,
3213
+ children: t("billing.monthCost")
3214
+ }),
3215
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3216
+ className: UsageBilling_module_css_default.heroReadout,
3217
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3218
+ className: UsageBilling_module_css_default.heroCurrency,
3219
+ "aria-hidden": "true",
3220
+ children: currency === "usd" ? "$" : "¥"
3221
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3222
+ className: UsageBilling_module_css_default.heroValue,
3223
+ children: money(monthCost).slice(1)
3224
+ })]
3225
+ }),
3226
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3227
+ className: UsageBilling_module_css_default.heroMeta,
3228
+ children: [
3229
+ monthCalls.toLocaleString(),
3230
+ " ",
3231
+ t("billing.calls")
3232
+ ]
3233
+ })
3234
+ ]
3235
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3236
+ className: UsageBilling_module_css_default.heroGauge,
3237
+ "data-testid": "billing-hero-gauge",
3238
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
3239
+ className: UsageBilling_module_css_default.heroGaugeSvg,
3240
+ viewBox: "0 0 120 120",
3241
+ "aria-hidden": "true",
3242
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
3243
+ className: UsageBilling_module_css_default.heroGaugeTrack,
3244
+ cx: "60",
3245
+ cy: "60",
3246
+ r: "52"
3247
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
3248
+ className: clsx(UsageBilling_module_css_default.heroGaugeArc, heroGauge.over && UsageBilling_module_css_default.heroGaugeArcOver),
3249
+ cx: "60",
3250
+ cy: "60",
3251
+ r: "52",
3252
+ style: { strokeDasharray: `${heroGauge.pct / 100 * 326.7} 326.7` }
3253
+ })]
3254
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3255
+ className: UsageBilling_module_css_default.heroGaugeCenter,
3256
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3257
+ className: clsx(UsageBilling_module_css_default.heroGaugePct, heroGauge.over && UsageBilling_module_css_default.heroGaugePctOver),
3258
+ children: [heroGauge.pct.toFixed(0), "%"]
3259
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3260
+ className: UsageBilling_module_css_default.heroGaugeLabel,
3261
+ children: heroGauge.label
3262
+ })]
2932
3263
  })]
2933
3264
  })]
2934
3265
  }),
@@ -2972,83 +3303,15 @@ window.__ModuleLoader__.load({
2972
3303
  className: UsageBilling_module_css_default.heroSideValue,
2973
3304
  children: money(monthCostProjected)
2974
3305
  })]
3306
+ }),
3307
+ monthCostProjected <= 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3308
+ className: UsageBilling_module_css_default.heroSideSpacer,
3309
+ "aria-hidden": "true"
2975
3310
  })
2976
3311
  ]
2977
3312
  })
2978
3313
  ]
2979
3314
  }),
2980
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2981
- className: UsageBilling_module_css_default.budget,
2982
- "data-testid": "billing-budget",
2983
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2984
- className: UsageBilling_module_css_default.budgetHead,
2985
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2986
- className: UsageBilling_module_css_default.budgetLabel,
2987
- children: t("billing.budget")
2988
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2989
- className: UsageBilling_module_css_default.budgetControls,
2990
- children: [
2991
- budgetEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2992
- className: UsageBilling_module_css_default.budgetInputWrap,
2993
- "data-testid": "billing-budget-input-wrap",
2994
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2995
- className: UsageBilling_module_css_default.budgetUnit,
2996
- "aria-hidden": "true",
2997
- children: "¥"
2998
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2999
- className: UsageBilling_module_css_default.budgetInput,
3000
- "data-testid": "billing-budget-input",
3001
- type: "number",
3002
- min: 0,
3003
- step: 1,
3004
- value: budgetAmount === 0 ? "" : budgetAmount,
3005
- placeholder: stats.budget !== void 0 ? String(stats.budget) : "0",
3006
- "aria-label": `${t("billing.budget")}(${currency === "usd" ? "USD" : "CNY"})`,
3007
- title: `${t("billing.budget")}(${currency === "usd" ? "USD" : "CNY"})`,
3008
- onChange: (e) => {
3009
- onBudgetAmount(e.target.valueAsNumber);
3010
- }
3011
- })]
3012
- }),
3013
- budgetEnabled && budgetAmount > 0 && (() => {
3014
- const pct = monthCost / budgetAmount * 100;
3015
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3016
- className: UsageBilling_module_css_default.budgetValue,
3017
- "data-testid": "billing-budget-value",
3018
- children: [
3019
- money(monthCost),
3020
- " / ",
3021
- money(budgetAmount),
3022
- " · ",
3023
- pct.toFixed(1),
3024
- "%"
3025
- ]
3026
- });
3027
- })(),
3028
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3029
- type: "button",
3030
- role: "switch",
3031
- "aria-checked": budgetEnabled,
3032
- "aria-label": t("billing.budget"),
3033
- "data-testid": "billing-budget-toggle",
3034
- className: clsx(UsageBilling_module_css_default.switch, budgetEnabled && UsageBilling_module_css_default.switchOn),
3035
- onClick: onToggleBudget,
3036
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: UsageBilling_module_css_default.switchKnob })
3037
- })
3038
- ]
3039
- })]
3040
- }), budgetEnabled && budgetAmount > 0 && (() => {
3041
- const pct = monthCost / budgetAmount * 100;
3042
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3043
- className: UsageBilling_module_css_default.budgetTrack,
3044
- "data-testid": "billing-budget-track",
3045
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3046
- className: clsx(UsageBilling_module_css_default.budgetFill, pct >= 100 && UsageBilling_module_css_default.budgetFillOver, pct >= 80 && pct < 100 && UsageBilling_module_css_default.budgetFillWarn),
3047
- style: { width: `${Math.min(pct, 100)}%` }
3048
- })
3049
- });
3050
- })()]
3051
- }),
3052
3315
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3053
3316
  className: UsageBilling_module_css_default.kpiGrid,
3054
3317
  "data-testid": "billing-kpi-grid",
@@ -3161,6 +3424,223 @@ window.__ModuleLoader__.load({
3161
3424
  })
3162
3425
  ]
3163
3426
  }),
3427
+ tab === "settings" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3428
+ className: UsageBilling_module_css_default.tabPanel,
3429
+ "data-testid": "billing-tab-panel-settings",
3430
+ children: [
3431
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3432
+ className: UsageBilling_module_css_default.settingsHead,
3433
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
3434
+ className: UsageBilling_module_css_default.settingsTitle,
3435
+ children: t("billing.settingsHead")
3436
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3437
+ className: UsageBilling_module_css_default.settingsHint,
3438
+ children: t("billing.settingsHint")
3439
+ })]
3440
+ }),
3441
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3442
+ className: UsageBilling_module_css_default.budget,
3443
+ "data-testid": "billing-budget",
3444
+ children: [
3445
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3446
+ className: UsageBilling_module_css_default.budgetHead,
3447
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3448
+ className: UsageBilling_module_css_default.budgetLabel,
3449
+ children: t("billing.budget")
3450
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3451
+ className: UsageBilling_module_css_default.budgetControls,
3452
+ children: [
3453
+ budgetEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3454
+ className: UsageBilling_module_css_default.budgetInputWrap,
3455
+ "data-testid": "billing-budget-input-wrap",
3456
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3457
+ className: UsageBilling_module_css_default.budgetUnit,
3458
+ "aria-hidden": "true",
3459
+ children: "¥"
3460
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3461
+ className: UsageBilling_module_css_default.budgetInput,
3462
+ "data-testid": "billing-budget-input",
3463
+ type: "number",
3464
+ min: 0,
3465
+ step: 1,
3466
+ value: budgetAmount === 0 ? "" : budgetAmount,
3467
+ placeholder: stats.budget !== void 0 ? String(stats.budget) : "0",
3468
+ "aria-label": `${t("billing.budget")}(${currency === "usd" ? "USD" : "CNY"})`,
3469
+ title: `${t("billing.budget")}(${currency === "usd" ? "USD" : "CNY"})`,
3470
+ onChange: (e) => {
3471
+ onBudgetAmount(e.target.valueAsNumber);
3472
+ }
3473
+ })]
3474
+ }),
3475
+ budgetEnabled && budgetAmount > 0 && (() => {
3476
+ const pct = monthCost / budgetAmount * 100;
3477
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3478
+ className: UsageBilling_module_css_default.budgetValue,
3479
+ "data-testid": "billing-budget-value",
3480
+ children: [
3481
+ money(monthCost),
3482
+ " / ",
3483
+ money(budgetAmount),
3484
+ " · ",
3485
+ pct.toFixed(1),
3486
+ "%"
3487
+ ]
3488
+ });
3489
+ })(),
3490
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3491
+ type: "button",
3492
+ role: "switch",
3493
+ "aria-checked": budgetEnabled,
3494
+ "aria-label": t("billing.budget"),
3495
+ "data-testid": "billing-budget-toggle",
3496
+ className: clsx(UsageBilling_module_css_default.switch, budgetEnabled && UsageBilling_module_css_default.switchOn),
3497
+ onClick: onToggleBudget,
3498
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: UsageBilling_module_css_default.switchKnob })
3499
+ })
3500
+ ]
3501
+ })]
3502
+ }),
3503
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3504
+ className: UsageBilling_module_css_default.budgetHint,
3505
+ children: t("billing.budgetHint")
3506
+ }),
3507
+ budgetEnabled && budgetAmount > 0 && (() => {
3508
+ const pct = monthCost / budgetAmount * 100;
3509
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3510
+ className: UsageBilling_module_css_default.budgetTrack,
3511
+ "data-testid": "billing-budget-track",
3512
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3513
+ className: clsx(UsageBilling_module_css_default.budgetFill, pct >= 100 && UsageBilling_module_css_default.budgetFillOver, pct >= 80 && pct < 100 && UsageBilling_module_css_default.budgetFillWarn),
3514
+ style: { width: `${Math.min(pct, 100)}%` }
3515
+ })
3516
+ });
3517
+ })()
3518
+ ]
3519
+ }),
3520
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3521
+ className: UsageBilling_module_css_default.peakAlertPanel,
3522
+ "data-testid": "billing-peak-alert-settings",
3523
+ children: [
3524
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3525
+ className: UsageBilling_module_css_default.peakAlertPanelHead,
3526
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3527
+ className: UsageBilling_module_css_default.peakAlertPanelLabel,
3528
+ children: t("billing.peakAlert")
3529
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3530
+ type: "button",
3531
+ role: "switch",
3532
+ "aria-checked": peakConfig.enabled,
3533
+ "aria-label": t("billing.peakAlert"),
3534
+ "data-testid": "billing-peak-alert-toggle",
3535
+ className: clsx(UsageBilling_module_css_default.switch, peakConfig.enabled && UsageBilling_module_css_default.switchOn),
3536
+ onClick: () => {
3537
+ onPeakConfig({
3538
+ ...peakConfig,
3539
+ enabled: !peakConfig.enabled
3540
+ });
3541
+ },
3542
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: UsageBilling_module_css_default.switchKnob })
3543
+ })]
3544
+ }),
3545
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3546
+ className: UsageBilling_module_css_default.peakAlertHint,
3547
+ children: t("billing.peakAlertHint")
3548
+ }),
3549
+ peakConfig.enabled && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3550
+ className: UsageBilling_module_css_default.peakAlertPanelBody,
3551
+ children: [
3552
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3553
+ className: UsageBilling_module_css_default.peakAlertField,
3554
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("billing.peakAlertLeadMin") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3555
+ type: "number",
3556
+ min: 1,
3557
+ max: 30,
3558
+ step: 1,
3559
+ value: peakConfig.leadMin,
3560
+ className: UsageBilling_module_css_default.peakAlertNum,
3561
+ "aria-label": t("billing.peakAlertLeadMin"),
3562
+ onChange: (e) => {
3563
+ const v = Number(e.target.valueAsNumber);
3564
+ onPeakConfig({
3565
+ ...peakConfig,
3566
+ leadMin: Number.isFinite(v) ? Math.min(30, Math.max(1, Math.round(v))) : peakConfig.leadMin
3567
+ });
3568
+ }
3569
+ })]
3570
+ }),
3571
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3572
+ className: UsageBilling_module_css_default.peakAlertField,
3573
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("billing.peakAlertPosCorner") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
3574
+ value: peakConfig.position,
3575
+ className: UsageBilling_module_css_default.peakAlertSelect,
3576
+ onChange: (e) => {
3577
+ onPeakConfig({
3578
+ ...peakConfig,
3579
+ position: e.target.value === "center" ? "center" : "bottom-right"
3580
+ });
3581
+ },
3582
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
3583
+ value: "bottom-right",
3584
+ children: t("billing.peakAlertPosCorner")
3585
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
3586
+ value: "center",
3587
+ children: t("billing.peakAlertPosCenter")
3588
+ })]
3589
+ })]
3590
+ }),
3591
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3592
+ className: UsageBilling_module_css_default.peakAlertField,
3593
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("billing.peakAlert") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
3594
+ value: peakConfig.mode,
3595
+ className: UsageBilling_module_css_default.peakAlertSelect,
3596
+ onChange: (e) => {
3597
+ const m = e.target.value;
3598
+ onPeakConfig({
3599
+ ...peakConfig,
3600
+ mode: m === "peak" || m === "offPeak" ? m : "both"
3601
+ });
3602
+ },
3603
+ children: [
3604
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
3605
+ value: "both",
3606
+ children: t("billing.peakAlertModeBoth")
3607
+ }),
3608
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
3609
+ value: "peak",
3610
+ children: t("billing.peakAlertModePeak")
3611
+ }),
3612
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
3613
+ value: "offPeak",
3614
+ children: t("billing.peakAlertModeOff")
3615
+ })
3616
+ ]
3617
+ })]
3618
+ }),
3619
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3620
+ className: UsageBilling_module_css_default.peakAlertCheck,
3621
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3622
+ type: "checkbox",
3623
+ checked: peakConfig.webNotify,
3624
+ onChange: (e) => {
3625
+ onPeakConfig({
3626
+ ...peakConfig,
3627
+ webNotify: e.target.checked
3628
+ });
3629
+ }
3630
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("billing.peakAlertWebNotify") })]
3631
+ }),
3632
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3633
+ type: "button",
3634
+ className: UsageBilling_module_css_default.peakAlertPreview,
3635
+ onClick: onPreviewPeak,
3636
+ children: t("billing.peakAlertPreview")
3637
+ })
3638
+ ]
3639
+ })
3640
+ ]
3641
+ })
3642
+ ]
3643
+ }),
3164
3644
  tab === "trends" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3165
3645
  className: UsageBilling_module_css_default.tabPanel,
3166
3646
  "data-testid": "billing-tab-panel-trends",
@@ -3341,7 +3821,7 @@ window.__ModuleLoader__.load({
3341
3821
  "aria-hidden": "true"
3342
3822
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3343
3823
  className: UsageBilling_module_css_default.providerGroupName,
3344
- children: group.name
3824
+ children: providerName(group.name)
3345
3825
  })]
3346
3826
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3347
3827
  className: UsageBilling_module_css_default.providerGroupMeta,
@@ -3406,7 +3886,7 @@ window.__ModuleLoader__.load({
3406
3886
  ]
3407
3887
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3408
3888
  className: UsageBilling_module_css_default.modelProvider,
3409
- children: row.provider
3889
+ children: providerName(row.provider)
3410
3890
  })] })
3411
3891
  }) }),
3412
3892
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
@@ -3430,7 +3910,28 @@ window.__ModuleLoader__.load({
3430
3910
  children: row.plan ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3431
3911
  className: UsageBilling_module_css_default.planTag,
3432
3912
  children: t("billing.subscriptionIncluded")
3433
- }) : row.actual !== void 0 ? money(row.actual) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3913
+ }) : row.actual !== void 0 ? (() => {
3914
+ const official = row.officialCost;
3915
+ const third = row.actual - official;
3916
+ if (official > 0 && third > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3917
+ className: UsageBilling_module_css_default.bucketCost,
3918
+ children: [
3919
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3920
+ className: UsageBilling_module_css_default.bucketOfficial,
3921
+ children: money(official)
3922
+ }),
3923
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3924
+ className: UsageBilling_module_css_default.bucketSep,
3925
+ children: "/"
3926
+ }),
3927
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3928
+ className: UsageBilling_module_css_default.bucketThird,
3929
+ children: money(third)
3930
+ })
3931
+ ]
3932
+ });
3933
+ return money(row.actual);
3934
+ })() : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3434
3935
  className: UsageBilling_module_css_default.na,
3435
3936
  children: "—"
3436
3937
  })
@@ -3452,7 +3953,7 @@ window.__ModuleLoader__.load({
3452
3953
  children: [
3453
3954
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3454
3955
  className: UsageBilling_module_css_default.subscriptionName,
3455
- children: quota.displayName
3956
+ children: providerName(quota.displayName)
3456
3957
  }),
3457
3958
  quota.planType === "code" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3458
3959
  className: UsageBilling_module_css_default.subscriptionPlan,
@@ -3602,6 +4103,64 @@ window.__ModuleLoader__.load({
3602
4103
  })
3603
4104
  ]
3604
4105
  }),
4106
+ bucketSummary !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
4107
+ className: UsageBilling_module_css_default.panel,
4108
+ "data-testid": "billing-panel-buckets",
4109
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4110
+ className: UsageBilling_module_css_default.panelHead,
4111
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h3", {
4112
+ className: UsageBilling_module_css_default.panelTitle,
4113
+ children: [
4114
+ t("billing.official"),
4115
+ " / ",
4116
+ t("billing.thirdParty")
4117
+ ]
4118
+ })
4119
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4120
+ className: UsageBilling_module_css_default.bucketSummary,
4121
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4122
+ className: UsageBilling_module_css_default.bucketStat,
4123
+ children: [
4124
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4125
+ className: UsageBilling_module_css_default.bucketStatLabel,
4126
+ children: t("billing.official")
4127
+ }),
4128
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4129
+ className: UsageBilling_module_css_default.bucketStatValue,
4130
+ children: money(bucketSummary.officialCost)
4131
+ }),
4132
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4133
+ className: UsageBilling_module_css_default.bucketStatSub,
4134
+ children: [
4135
+ bucketSummary.officialCalls,
4136
+ " ",
4137
+ t("billing.calls")
4138
+ ]
4139
+ })
4140
+ ]
4141
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4142
+ className: UsageBilling_module_css_default.bucketStat,
4143
+ children: [
4144
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4145
+ className: UsageBilling_module_css_default.bucketStatLabel,
4146
+ children: t("billing.thirdParty")
4147
+ }),
4148
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4149
+ className: UsageBilling_module_css_default.bucketStatValue,
4150
+ children: money(bucketSummary.thirdCost)
4151
+ }),
4152
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4153
+ className: UsageBilling_module_css_default.bucketStatSub,
4154
+ children: [
4155
+ bucketSummary.thirdCalls,
4156
+ " ",
4157
+ t("billing.calls")
4158
+ ]
4159
+ })
4160
+ ]
4161
+ })]
4162
+ })]
4163
+ }),
3605
4164
  stats.byWorkspace !== void 0 && stats.byWorkspace.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3606
4165
  className: UsageBilling_module_css_default.panel,
3607
4166
  "data-testid": "billing-panel-workspaces",
@@ -3735,119 +4294,126 @@ window.__ModuleLoader__.load({
3735
4294
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3736
4295
  className: UsageBilling_module_css_default.panel,
3737
4296
  "data-testid": "billing-panel-pricing",
3738
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3739
- className: UsageBilling_module_css_default.panelHead,
3740
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
3741
- className: UsageBilling_module_css_default.panelTitle,
3742
- children: t("billing.pricing")
3743
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3744
- className: UsageBilling_module_css_default.panelHint,
3745
- children: [
3746
- t("billing.todayRate"),
3747
- " 1 USD = ",
3748
- formatMoney(rateInfo.rate),
3749
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3750
- className: clsx(UsageBilling_module_css_default.rateBadge, rateInfo.live ? UsageBilling_module_css_default.rateBadgeLive : UsageBilling_module_css_default.rateBadgeBuiltin),
3751
- children: rateInfo.live ? t("billing.rateLive") : t("billing.rateBuiltin")
3752
- })
3753
- ]
3754
- })]
3755
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3756
- className: UsageBilling_module_css_default.tableScroll,
3757
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
3758
- className: UsageBilling_module_css_default.pricingTable,
3759
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
3760
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Model" }),
3761
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
3762
- className: UsageBilling_module_css_default.numCol,
3763
- children: t("billing.input")
3764
- }),
3765
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
3766
- className: UsageBilling_module_css_default.numCol,
3767
- children: t("billing.cacheHit")
3768
- }),
3769
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
3770
- className: UsageBilling_module_css_default.numCol,
3771
- children: t("billing.output")
3772
- }),
3773
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("billing.band") })
3774
- ] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: catalogEntries().map((entry) => {
3775
- const hasPrice = entry.price.input > 0 || entry.price.output > 0;
3776
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
3777
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3778
- className: UsageBilling_module_css_default.modelCell,
3779
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3780
- className: UsageBilling_module_css_default.modelDot,
3781
- style: { background: resolveToken(entry.colorVar) }
3782
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3783
- className: UsageBilling_module_css_default.modelName,
3784
- children: [entry.name, entry.uncatalogued && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3785
- className: UsageBilling_module_css_default.uncataloguedTag,
3786
- "data-testid": "billing-price-uncatalogued",
3787
- children: t("billing.uncatalogued")
3788
- })]
3789
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3790
- className: UsageBilling_module_css_default.modelProvider,
3791
- children: entry.provider
3792
- })] })]
3793
- }) }),
3794
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
4297
+ children: [
4298
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4299
+ className: UsageBilling_module_css_default.panelHead,
4300
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
4301
+ className: UsageBilling_module_css_default.panelTitle,
4302
+ children: t("billing.pricing")
4303
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4304
+ className: UsageBilling_module_css_default.panelHint,
4305
+ children: [
4306
+ t("billing.todayRate"),
4307
+ " 1 USD = ",
4308
+ formatMoney(rateInfo.rate),
4309
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4310
+ className: clsx(UsageBilling_module_css_default.rateBadge, rateInfo.live ? UsageBilling_module_css_default.rateBadgeLive : UsageBilling_module_css_default.rateBadgeBuiltin),
4311
+ children: rateInfo.live ? t("billing.rateLive") : t("billing.rateBuiltin")
4312
+ })
4313
+ ]
4314
+ })]
4315
+ }),
4316
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4317
+ className: UsageBilling_module_css_default.pricingTip,
4318
+ children: t("billing.pricingTip")
4319
+ }),
4320
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4321
+ className: UsageBilling_module_css_default.tableScroll,
4322
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
4323
+ className: UsageBilling_module_css_default.pricingTable,
4324
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
4325
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: "Model" }),
4326
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
3795
4327
  className: UsageBilling_module_css_default.numCol,
3796
- children: hasPrice ? entry.price.offPeak !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3797
- className: UsageBilling_module_css_default.bandPrice,
3798
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: unitMoney(entry.price.input, entry.price.currency) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3799
- className: UsageBilling_module_css_default.bandPriceOff,
3800
- children: unitMoney(entry.price.offPeak.input, entry.price.currency)
3801
- })]
3802
- }) : unitMoney(entry.price.input, entry.price.currency) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3803
- className: UsageBilling_module_css_default.na,
3804
- children: "—"
3805
- })
4328
+ children: t("billing.input")
3806
4329
  }),
3807
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
4330
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
3808
4331
  className: UsageBilling_module_css_default.numCol,
3809
- children: hasPrice ? entry.price.offPeak !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3810
- className: UsageBilling_module_css_default.bandPrice,
3811
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: unitMoney(entry.price.cacheHit, entry.price.currency) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3812
- className: UsageBilling_module_css_default.bandPriceOff,
3813
- children: unitMoney(entry.price.offPeak.cacheHit, entry.price.currency)
3814
- })]
3815
- }) : unitMoney(entry.price.cacheHit, entry.price.currency) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3816
- className: UsageBilling_module_css_default.na,
3817
- children: "—"
3818
- })
4332
+ children: t("billing.cacheHit")
3819
4333
  }),
3820
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
4334
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
3821
4335
  className: UsageBilling_module_css_default.numCol,
3822
- children: hasPrice ? entry.price.offPeak !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3823
- className: UsageBilling_module_css_default.bandPrice,
3824
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: unitMoney(entry.price.output, entry.price.currency) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3825
- className: UsageBilling_module_css_default.bandPriceOff,
3826
- children: unitMoney(entry.price.offPeak.output, entry.price.currency)
3827
- })]
3828
- }) : unitMoney(entry.price.output, entry.price.currency) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3829
- className: UsageBilling_module_css_default.na,
3830
- children: "—"
3831
- })
4336
+ children: t("billing.output")
3832
4337
  }),
3833
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: entry.price.offPeak !== void 0 && entry.peakHours !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3834
- className: UsageBilling_module_css_default.bandTag,
3835
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
3836
- t("billing.peak"),
3837
- " ",
3838
- entry.peakHours
3839
- ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3840
- className: UsageBilling_module_css_default.bandTagOff,
3841
- children: [t("billing.offPeak"), " 50%"]
3842
- })]
3843
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3844
- className: UsageBilling_module_css_default.flatTag,
3845
- children: t("billing.flat")
3846
- }) })
3847
- ] }, entry.key);
3848
- }) })]
4338
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("billing.band") })
4339
+ ] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: catalogEntries().map((entry) => {
4340
+ const hasPrice = entry.price.input > 0 || entry.price.output > 0;
4341
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
4342
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4343
+ className: UsageBilling_module_css_default.modelCell,
4344
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4345
+ className: UsageBilling_module_css_default.modelDot,
4346
+ style: { background: resolveToken(entry.colorVar) }
4347
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4348
+ className: UsageBilling_module_css_default.modelName,
4349
+ children: [entry.name, entry.uncatalogued && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4350
+ className: UsageBilling_module_css_default.uncataloguedTag,
4351
+ "data-testid": "billing-price-uncatalogued",
4352
+ children: t("billing.uncatalogued")
4353
+ })]
4354
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4355
+ className: UsageBilling_module_css_default.modelProvider,
4356
+ children: providerName(entry.provider)
4357
+ })] })]
4358
+ }) }),
4359
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
4360
+ className: UsageBilling_module_css_default.numCol,
4361
+ children: hasPrice ? entry.price.offPeak !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4362
+ className: UsageBilling_module_css_default.bandPrice,
4363
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: unitMoney(entry.price.input, entry.price.currency) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4364
+ className: UsageBilling_module_css_default.bandPriceOff,
4365
+ children: unitMoney(entry.price.offPeak.input, entry.price.currency)
4366
+ })]
4367
+ }) : unitMoney(entry.price.input, entry.price.currency) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4368
+ className: UsageBilling_module_css_default.na,
4369
+ children: "—"
4370
+ })
4371
+ }),
4372
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
4373
+ className: UsageBilling_module_css_default.numCol,
4374
+ children: hasPrice ? entry.price.offPeak !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4375
+ className: UsageBilling_module_css_default.bandPrice,
4376
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: unitMoney(entry.price.cacheHit, entry.price.currency) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4377
+ className: UsageBilling_module_css_default.bandPriceOff,
4378
+ children: unitMoney(entry.price.offPeak.cacheHit, entry.price.currency)
4379
+ })]
4380
+ }) : unitMoney(entry.price.cacheHit, entry.price.currency) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4381
+ className: UsageBilling_module_css_default.na,
4382
+ children: "—"
4383
+ })
4384
+ }),
4385
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
4386
+ className: UsageBilling_module_css_default.numCol,
4387
+ children: hasPrice ? entry.price.offPeak !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4388
+ className: UsageBilling_module_css_default.bandPrice,
4389
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: unitMoney(entry.price.output, entry.price.currency) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4390
+ className: UsageBilling_module_css_default.bandPriceOff,
4391
+ children: unitMoney(entry.price.offPeak.output, entry.price.currency)
4392
+ })]
4393
+ }) : unitMoney(entry.price.output, entry.price.currency) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4394
+ className: UsageBilling_module_css_default.na,
4395
+ children: "—"
4396
+ })
4397
+ }),
4398
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: entry.price.offPeak !== void 0 && entry.peakHours !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4399
+ className: UsageBilling_module_css_default.bandTag,
4400
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
4401
+ t("billing.peak"),
4402
+ " ",
4403
+ entry.peakHours
4404
+ ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4405
+ className: UsageBilling_module_css_default.bandTagOff,
4406
+ children: [t("billing.offPeak"), " 50%"]
4407
+ })]
4408
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4409
+ className: UsageBilling_module_css_default.flatTag,
4410
+ children: t("billing.flat")
4411
+ }) })
4412
+ ] }, entry.key);
4413
+ }) })]
4414
+ })
3849
4415
  })
3850
- })]
4416
+ ]
3851
4417
  })
3852
4418
  }),
3853
4419
  renderSlot("billing.dashboard.decor", { position: "footer" })
@@ -3929,6 +4495,19 @@ window.__ModuleLoader__.load({
3929
4495
  const budgetAmount = useStore((s) => s.amount);
3930
4496
  const tierAlertDays = useStore((s) => s.tierAlertDays);
3931
4497
  const lastTierSwitchAt = useStore((s) => s.lastTierSwitchAt);
4498
+ const [peakConfig, setPeakConfig] = (0, react.useState)(() => loadPeakAlertConfig());
4499
+ const [peakHit, setPeakHit] = (0, react.useState)(null);
4500
+ const [peakPreview, setPeakPreview] = (0, react.useState)(null);
4501
+ const updatePeakConfig = (0, react.useCallback)((config) => {
4502
+ setPeakConfig(config);
4503
+ savePeakAlertConfig(config);
4504
+ }, []);
4505
+ const previewPeak = (0, react.useCallback)(() => {
4506
+ setPeakPreview({
4507
+ entering: tierAt(Date.now()) === "peak" ? "offPeak" : "peak",
4508
+ atMs: Date.now() + 3 * 6e4
4509
+ });
4510
+ }, []);
3932
4511
  const effectiveBudget = budgetAmount > 0 ? budgetAmount : stats.budget ?? 0;
3933
4512
  const toggleBudget = (0, react.useCallback)(() => {
3934
4513
  const next = !budgetEnabled;
@@ -3957,20 +4536,21 @@ window.__ModuleLoader__.load({
3957
4536
  t
3958
4537
  ]);
3959
4538
  (0, react.useEffect)(() => {
3960
- const leadMs = 2 * 6e4;
3961
- const now = Date.now();
3962
- const upcoming = upcomingTierSwitch(now, leadMs);
4539
+ const upcoming = computePeakAlert(Date.now(), peakConfig, lastTierSwitchAt);
3963
4540
  if (upcoming === null) return;
3964
- if (upcoming.atMs === lastTierSwitchAt) return;
3965
4541
  actions.markTierSwitchAlerted(upcoming.atMs);
4542
+ setPeakHit(upcoming);
4543
+ if (!peakConfig.webNotify) return;
3966
4544
  if (typeof Notification === "undefined" || Notification.permission !== "granted") return;
3967
- const minutes = Math.max(1, Math.round((upcoming.atMs - now) / 6e4));
4545
+ const minutes = Math.max(1, Math.round((upcoming.atMs - Date.now()) / 6e4));
4546
+ const title = upcoming.entering === "peak" ? t("billing.peakAlertTitlePeak") : t("billing.peakAlertTitleOff");
3968
4547
  const body = upcoming.entering === "peak" ? t("billing.tierAlertEnterPeak").replace("{minutes}", String(minutes)) : t("billing.tierAlertEnterOff").replace("{minutes}", String(minutes));
3969
4548
  try {
3970
- new Notification(t("billing.budget"), { body });
4549
+ new Notification(title, { body });
3971
4550
  } catch {}
3972
4551
  }, [
3973
4552
  lastTierSwitchAt,
4553
+ peakConfig,
3974
4554
  actions,
3975
4555
  t
3976
4556
  ]);
@@ -4025,30 +4605,45 @@ window.__ModuleLoader__.load({
4025
4605
  ]);
4026
4606
  (0, react.useEffect)(() => registerOpen(openDashboard), [registerOpen, openDashboard]);
4027
4607
  const turns = (0, react.useMemo)(() => stats.byTurn ?? [], [stats.byTurn]);
4028
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageBillingTrigger, {
4029
- ...props,
4030
- t,
4031
- onOpen: openDashboard,
4032
- monthCost,
4033
- todayCost,
4034
- weekCost,
4035
- days: last7
4036
- }), open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BillingDashboard, {
4037
- stats,
4038
- t,
4039
- onClose: close,
4040
- health,
4041
- balances,
4042
- quotas,
4043
- currency,
4044
- onCurrency: setCurrency,
4045
- turns,
4046
- renderSlot,
4047
- budgetEnabled,
4048
- budgetAmount: effectiveBudget,
4049
- onToggleBudget: toggleBudget,
4050
- onBudgetAmount: actions.setAmount
4051
- })] });
4608
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
4609
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageBillingTrigger, {
4610
+ ...props,
4611
+ t,
4612
+ onOpen: openDashboard,
4613
+ monthCost,
4614
+ todayCost,
4615
+ weekCost,
4616
+ days: last7
4617
+ }),
4618
+ open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BillingDashboard, {
4619
+ stats,
4620
+ t,
4621
+ onClose: close,
4622
+ health,
4623
+ balances,
4624
+ quotas,
4625
+ currency,
4626
+ onCurrency: setCurrency,
4627
+ turns,
4628
+ renderSlot,
4629
+ budgetEnabled,
4630
+ budgetAmount: effectiveBudget,
4631
+ onToggleBudget: toggleBudget,
4632
+ onBudgetAmount: actions.setAmount,
4633
+ peakConfig,
4634
+ onPeakConfig: updatePeakConfig,
4635
+ onPreviewPeak: previewPeak
4636
+ }),
4637
+ (peakHit !== null || peakPreview !== null) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PeakAlertBanner, {
4638
+ hit: peakHit ?? peakPreview,
4639
+ config: peakConfig,
4640
+ t,
4641
+ onDismiss: () => {
4642
+ setPeakHit(null);
4643
+ setPeakPreview(null);
4644
+ }
4645
+ })
4646
+ ] });
4052
4647
  }
4053
4648
  //#endregion
4054
4649
  //#region src/client/live-cost.tsx
@@ -4340,12 +4935,85 @@ window.__ModuleLoader__.load({
4340
4935
  });
4341
4936
  }
4342
4937
  //#endregion
4938
+ //#region src/client/completion-notify.ts
4939
+ /** 配置持久化 key:开启/关闭 + 提醒持续模式(0=常驻,其余=秒后自动关)。 */
4940
+ const COMPLETION_NOTIFY_KEY = "dsh-billing-completion-notify-v1";
4941
+ const DEFAULT_CONFIG = {
4942
+ enabled: false,
4943
+ timeout: 0
4944
+ };
4945
+ /** 读取本地配置(缺失/损坏时回退默认)。 */
4946
+ function loadNotifyConfig() {
4947
+ try {
4948
+ const raw = localStorage.getItem(COMPLETION_NOTIFY_KEY);
4949
+ if (raw === null) return { ...DEFAULT_CONFIG };
4950
+ const parsed = JSON.parse(raw);
4951
+ return {
4952
+ enabled: parsed.enabled === true,
4953
+ timeout: typeof parsed.timeout === "number" ? parsed.timeout : 0
4954
+ };
4955
+ } catch {
4956
+ return { ...DEFAULT_CONFIG };
4957
+ }
4958
+ }
4959
+ /** 判断一个会话是否「完成」:completed 标志为真,或已不再 running。 */
4960
+ function isFinished(summary) {
4961
+ if (summary.completed === true) return true;
4962
+ return summary.running === false;
4963
+ }
4964
+ /**
4965
+ * 安装对话完成提醒:订阅 sessions.list 快照,用 `previousFinished` 记住每条
4966
+ * 会话上次是运行中还是已完成;只有「之前运行中 → 现在已完成」的迁移才提醒,
4967
+ * 首次快照只建立基线、不提醒。返回清理函数(dispose 时释放订阅)。
4968
+ * @param list - `ctx.sessions.list`(宿主注入的会话列表快照源)。
4969
+ */
4970
+ function installCompletionNotifier(list, getConfig) {
4971
+ const previousFinished = /* @__PURE__ */ new Set();
4972
+ let queuedTitle;
4973
+ const snapshot = list.getSnapshot();
4974
+ for (const id of snapshot.ids) {
4975
+ const summary = snapshot.byId[id];
4976
+ if (summary !== void 0 && isFinished(summary)) previousFinished.add(String(id));
4977
+ }
4978
+ const notify = (title) => {
4979
+ const { enabled, timeout } = getConfig();
4980
+ if (!enabled) return;
4981
+ if (typeof Notification === "undefined") return;
4982
+ if (Notification.permission !== "granted") return;
4983
+ try {
4984
+ new Notification(title, {
4985
+ body: title,
4986
+ tag: "dsh-billing-completion",
4987
+ requireInteraction: timeout === 0
4988
+ });
4989
+ } catch {}
4990
+ };
4991
+ return list.subscribe(() => {
4992
+ const state = list.getSnapshot();
4993
+ const finishedTitles = [];
4994
+ for (const id of state.ids) {
4995
+ const summary = state.byId[id];
4996
+ if (summary === void 0) continue;
4997
+ const key = String(id);
4998
+ const finished = isFinished(summary);
4999
+ if (finished && !previousFinished.has(key)) finishedTitles.push(summary.title ?? summary.id ?? key);
5000
+ if (finished) previousFinished.add(key);
5001
+ else previousFinished.delete(key);
5002
+ }
5003
+ if (finishedTitles.length > 0) {
5004
+ queuedTitle = finishedTitles.length === 1 ? finishedTitles[0] : `${finishedTitles.length} 个会话已完成`;
5005
+ if (queuedTitle !== void 0) notify(queuedTitle);
5006
+ }
5007
+ });
5008
+ }
5009
+ //#endregion
4343
5010
  //#region src/client/apply.ts
4344
5011
  /** Required services for the usage billing surface. */
4345
5012
  const inject = [
4346
5013
  "slots",
4347
5014
  "locale",
4348
- "connection"
5015
+ "connection",
5016
+ "sessions"
4349
5017
  ];
4350
5018
  /**
4351
5019
  * Client plugin body: the UsageBilling entry in the sidebar footer.
@@ -4419,6 +5087,9 @@ window.__ModuleLoader__.load({
4419
5087
  order: 0,
4420
5088
  locale: NS
4421
5089
  }, LiveCostBar));
5090
+ ctx.effect(() => {
5091
+ return installCompletionNotifier(ctx.sessions.list, loadNotifyConfig);
5092
+ }, "ui-usage-billing: completion notifier");
4422
5093
  }
4423
5094
  //#endregion
4424
5095
  exports.UsageBilling = UsageBilling;