@cassius0924/dsh-usage-dashboard 0.3.1 → 0.5.0

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.
@@ -0,0 +1,253 @@
1
+ /** Locale namespace and complete bilingual copy for the dashboard surfaces. */
2
+ export declare const NS = "dsh-usage-dashboard";
3
+ export declare const zh: {
4
+ readonly 'meta.locale': "zh";
5
+ readonly 'nav.quota': "额度";
6
+ readonly 'widget.title': "DeepSeek 额度";
7
+ readonly 'common.unknownModel': "未知模型";
8
+ readonly 'common.calls': "{count} 次调用";
9
+ readonly 'common.callsShort': "{count} 次";
10
+ readonly 'common.sessions': "{count} 个会话";
11
+ readonly 'common.records': "{count} 条";
12
+ readonly 'common.rows': "{count} 行";
13
+ readonly 'common.input': "输入";
14
+ readonly 'common.output': "输出";
15
+ readonly 'common.cacheHit': "缓存命中";
16
+ readonly 'common.status': "状态";
17
+ readonly 'common.available': "可用";
18
+ readonly 'common.unavailable': "不可用";
19
+ readonly 'common.justNow': "刚刚";
20
+ readonly 'common.minutesAgo': "{count} 分钟前";
21
+ readonly 'common.hoursAgo': "{count} 小时前";
22
+ readonly 'common.daysAgo': "{count} 天前";
23
+ readonly 'common.listSeparator': "、";
24
+ readonly 'common.period': "。";
25
+ readonly 'delta.noBaselineTitle': "{label}没有用量,无从对比";
26
+ readonly 'delta.noBaseline': "无对比";
27
+ readonly 'delta.flat': "持平";
28
+ readonly 'period.volume': "{tokens} tokens · {calls}";
29
+ readonly 'budget.unset': "还没设置月度预算,无法提前判断是否会超支。";
30
+ readonly 'budget.configure': "设置预算";
31
+ readonly 'budget.over': "已超预算 ¥{amount}";
32
+ readonly 'budget.forecastOver': "照当前速度,预计超出 ¥{amount}";
33
+ readonly 'budget.forecast': "照当前速度,预计月底 ¥{amount}";
34
+ readonly 'budget.title': "本月预算";
35
+ readonly 'budget.progressLabel': "本月预算使用进度";
36
+ readonly 'budget.used': "已使用 {percent}%,{forecast}";
37
+ readonly 'budget.remaining': "剩余 ¥{amount}";
38
+ readonly 'budget.exceeded': "超出 ¥{amount}";
39
+ readonly 'pricing.title': "计价说明";
40
+ readonly 'pricing.currentPeak': "当前 高峰时段";
41
+ readonly 'pricing.currentOffPeak': "当前 闲时";
42
+ readonly 'pricing.model': "模型";
43
+ readonly 'pricing.period': "时段";
44
+ readonly 'pricing.unitPrice': "单价";
45
+ readonly 'pricing.inputCacheHit': "输入·缓存命中";
46
+ readonly 'pricing.inputCacheMiss': "输入·未命中";
47
+ readonly 'pricing.output': "输出";
48
+ readonly 'pricing.peak': "高峰";
49
+ readonly 'pricing.fixed': "固定";
50
+ readonly 'pricing.offPeak': "闲时";
51
+ readonly 'pricing.unit': "单位:{currency} / 百万 tokens。";
52
+ readonly 'pricing.splitNote': "高峰时段为北京时间 {windows},其余为闲时(价格减半);{date} 之前的用量仍按旧价估算。";
53
+ readonly 'pricing.switchNote': "{date} 00:00 起改为峰谷定价(高峰 {windows},闲时价格减半),届时本页会按每条记录的时间自动分段计价。";
54
+ readonly 'pricing.unknown': "未知模型按 deepseek-v4-pro 计价。";
55
+ readonly 'coverage.noRange': "暂无有效用量时间";
56
+ readonly 'coverage.title': "统计范围";
57
+ readonly 'coverage.gaps': "存在缺口";
58
+ readonly 'coverage.complete': "本机读取完整";
59
+ readonly 'coverage.brief': "扫描 {scanned} / {listed} 个会话 · {records} 条用量记录";
60
+ readonly 'coverage.scanned': "成功扫描";
61
+ readonly 'coverage.failed': "读取失败";
62
+ readonly 'coverage.skipped': "跳过记录";
63
+ readonly 'coverage.time': "记录时间:{range}";
64
+ readonly 'coverage.scope': "这里只统计当前设备上的 DSH 会话日志,不包含其他设备、DeepSeek 平台直接调用或已删除的本地日志。";
65
+ readonly 'coverage.warning': "本次回放有日志无法读取或用量记录格式异常,页面汇总可能低于实际消耗;可刷新重试,并以 DeepSeek 官方平台账单为准。";
66
+ readonly 'export.title': "导出全部本机 DSH 会话日志数据(不受统计周期影响)";
67
+ readonly 'export.done': "已导出";
68
+ readonly 'export.action': "导出";
69
+ readonly 'export.menuLabel': "选择导出格式";
70
+ readonly 'export.dailyCsv': "逐天 CSV";
71
+ readonly 'export.modelCsv': "逐模型 CSV";
72
+ readonly 'export.fullJson': "完整 JSON";
73
+ readonly 'export.jsonHint': "含图表与排行";
74
+ readonly 'cache.empty': "还没有 prompt token 可统计缓存命中。";
75
+ readonly 'cache.rate': "缓存命中率";
76
+ readonly 'cache.saved': "已节省费用(估算)";
77
+ readonly 'cache.allMiss': "若全部未命中";
78
+ readonly 'cache.aria': "缓存命中 {hit}%,未命中 {miss}%";
79
+ readonly 'cache.hitLegend': "缓存命中 {tokens}";
80
+ readonly 'cache.missLegend': "未命中 {tokens}(按未命中价计费)";
81
+ readonly 'cache.lowHint': "命中率偏低:频繁改动 system prompt / 工具定义会让前缀缓存失效,把稳定内容放在对话最前面能提高命中率。";
82
+ readonly 'cache.goodHint': "前缀缓存把重复的 prompt 前缀按命中价计费,是这份账单上最大的省钱杠杆。";
83
+ readonly 'peak.empty': "还没有可按时段归类的用量。";
84
+ readonly 'peak.aria': "高峰时段 {peak}%,闲时 {offPeak}%";
85
+ readonly 'peak.peakLegend': "高峰 {share}% · {tokens} tokens · {calls}";
86
+ readonly 'peak.offPeakLegend': "闲时 {share}% · {tokens} tokens · {calls}";
87
+ readonly 'peak.newPrice': "同样用量在新价下";
88
+ readonly 'peak.increase': "较现价 +{percent}%";
89
+ readonly 'peak.shift': "若高峰用量都挪到闲时";
90
+ readonly 'peak.saving': "可省 ¥{amount}";
91
+ readonly 'peak.schedule': "高峰时段为北京时间 {windows},闲时价格减半。";
92
+ readonly 'peak.activeHint': "把批量、可延后的任务放到闲时跑,同样的 token 只要一半的钱。";
93
+ readonly 'peak.futureHint': "新价 {date} 00:00 生效;上面两个数字是按你已有的全部用量重算的。";
94
+ readonly 'sessions.empty': "还没有产生费用的会话。";
95
+ readonly 'sessions.detail': "{tokens} tokens · {calls} · {ago}";
96
+ readonly 'sessions.share': "占 {percent}%";
97
+ readonly 'sessions.more': "共 {count} 个会话有用量,上面是最贵的 {shown} 个。";
98
+ readonly 'sessions.fallbackTitle': "会话 {id}";
99
+ readonly 'models.empty': "还没有可归类的模型用量。";
100
+ readonly 'models.shareAria': "{name} 占总费用 {percent}%";
101
+ readonly 'models.detail': "{tokens} tokens · {calls} · 输入 {input} / 输出 {output} / 缓存 {cache}";
102
+ readonly 'models.all': "全部模型";
103
+ readonly 'models.selected': "模型 ×{count}";
104
+ readonly 'models.filterTitle': "筛选图表中显示的模型";
105
+ readonly 'models.filterLabel': "筛选图表模型";
106
+ readonly 'window.year': "近 1 年";
107
+ readonly 'window.days': "近 {days} 天";
108
+ readonly 'window.groupLabel': "统计周期";
109
+ readonly 'window.viewTitle': "查看{window}的用量与排行";
110
+ readonly 'window.yearButton': "1 年";
111
+ readonly 'window.daysButton': "{days} 天";
112
+ readonly 'metric.tokens': "tokens";
113
+ readonly 'metric.usage': "用量";
114
+ readonly 'metric.cost': "费用";
115
+ readonly 'metric.calls': "调用";
116
+ readonly 'metric.groupLabel': "图表指标";
117
+ readonly 'metric.compareTitle': "按{metric}比较";
118
+ readonly 'chart.dailyTitle': "{window} · 逐天{metric}";
119
+ readonly 'chart.hourlyTitle': "{window} · {metric}按小时分布(0–23 点)";
120
+ readonly 'chart.peak': "峰值 {value}";
121
+ readonly 'chart.dimensionLabel': "切换图表维度";
122
+ readonly 'chart.daily': "逐天";
123
+ readonly 'chart.hourly': "逐小时";
124
+ readonly 'chart.noWindowData': "{window}没有用量记录,换个更长周期看看。";
125
+ readonly 'chart.heatmapTitle': "近一年 · 每日用量热力图";
126
+ readonly 'chart.empty': "还没有用量记录。在 DSH 里跑一轮对话,这里会出现逐天 / 逐小时统计与费用估算。";
127
+ readonly 'chart.hourPoint': "{hour} 点";
128
+ readonly 'chart.tooltip': "{head} · {tokens} tokens · ¥{cost} · {calls}";
129
+ readonly 'chart.less': "少";
130
+ readonly 'chart.more': "多";
131
+ readonly 'chart.month1': "1月";
132
+ readonly 'chart.month2': "2月";
133
+ readonly 'chart.month3': "3月";
134
+ readonly 'chart.month4': "4月";
135
+ readonly 'chart.month5': "5月";
136
+ readonly 'chart.month6': "6月";
137
+ readonly 'chart.month7': "7月";
138
+ readonly 'chart.month8': "8月";
139
+ readonly 'chart.month9': "9月";
140
+ readonly 'chart.month10': "10月";
141
+ readonly 'chart.month11': "11月";
142
+ readonly 'chart.month12': "12月";
143
+ readonly 'number.tenThousand': "{value}万";
144
+ readonly 'number.hundredMillion': "{value}亿";
145
+ readonly 'fresh.none': "尚无成功记录";
146
+ readonly 'fresh.justNow': "刚刚更新";
147
+ readonly 'fresh.minutes': "更新于 {count} 分钟前";
148
+ readonly 'fresh.hours': "更新于 {count} 小时前";
149
+ readonly 'fresh.days': "更新于 {count} 天前";
150
+ readonly 'sync.first': "首次同步中";
151
+ readonly 'sync.syncing': "同步中 · 当前数据{age}";
152
+ readonly 'sync.fresh': "已同步 · {age}";
153
+ readonly 'sync.cached': "缓存数据 · {age}";
154
+ readonly 'sync.fallback': "缓存回退 · {age}";
155
+ readonly 'sync.error': "同步失败 · 暂无可显示的用量";
156
+ readonly 'status.neverSynced': "还没有成功同步过用量数据";
157
+ readonly 'status.usageTime': "用量数据时间:{time}";
158
+ readonly 'status.forceRefresh': "强制刷新(绕过缓存)";
159
+ readonly 'status.refreshing': "刷新中";
160
+ readonly 'status.refresh': "刷新";
161
+ readonly 'error.balanceLoad': "余额加载失败";
162
+ readonly 'error.usageLoad': "用量加载失败";
163
+ readonly 'error.refreshCached': "刷新失败,正在展示缓存数据({error})";
164
+ readonly 'error.balanceRefreshCached': "余额刷新失败,正在展示缓存余额({error})";
165
+ readonly 'error.usageRefreshCached': "用量刷新失败,正在展示缓存用量({error})";
166
+ readonly 'error.query': "查询失败";
167
+ readonly 'error.credentialsUnavailable': "凭证服务不可用";
168
+ readonly 'error.credentialRead': "读取 API Key 失败:{detail}";
169
+ readonly 'error.noApiKey': "未配置 DEEPSEEK_API_KEY(可在「设置 → 模型」中填写)";
170
+ readonly 'error.balanceRequest': "请求余额接口失败:{detail}";
171
+ readonly 'error.balanceHttp': "余额接口返回错误(HTTP {status})";
172
+ readonly 'error.balanceParse': "解析余额响应失败";
173
+ readonly 'error.persistenceUnavailable': "会话持久化服务不可用";
174
+ readonly 'error.sessionList': "读取会话列表失败:{detail}";
175
+ readonly 'error.sessionLogRead': "读取会话日志失败:{detail}";
176
+ readonly 'error.missingSessionId': "缺少会话 id";
177
+ readonly 'alert.lowTitle': "余额 {balance} {currency} 已低于预警线 {threshold}";
178
+ readonly 'alert.runway': ",按近期用量估计还能撑 {days}";
179
+ readonly 'alert.topUp': "去充值";
180
+ readonly 'balance.title': "账户余额";
181
+ readonly 'balance.remaining': "剩余余额";
182
+ readonly 'balance.breakdownTitle': "查看充值与赠送额度明细";
183
+ readonly 'balance.toppedUp': "充值额度 {amount}";
184
+ readonly 'balance.granted': "赠送额度 {amount}";
185
+ readonly 'balance.runway': "预计可用";
186
+ readonly 'balance.runwayBreakdownTitle': "查看预计可用天数说明";
187
+ readonly 'balance.days': "{count} 天";
188
+ readonly 'balance.overYear': "> 365 天";
189
+ readonly 'balance.noRunway': "近 {days} 天没有用量,无法估算";
190
+ readonly 'balance.runwayTitle': "按近 {days} 天日均 ¥{cost} 估算(含无用量的日子;今天尚未过完)";
191
+ readonly 'balance.empty': "读不到余额。请确认「设置 → 模型」里已填 DEEPSEEK_API_KEY,然后点右上角刷新。";
192
+ readonly 'sessionUsage.title': "当前会话消耗(费用为估算)";
193
+ readonly 'sessionUsage.cost': "本会话费用";
194
+ readonly 'sessionUsage.tokens': "本会话 tokens";
195
+ readonly 'sessionUsage.calls': "本会话调用";
196
+ readonly 'sessionUsage.range': "活跃时间 {range}";
197
+ readonly 'sessionUsage.empty': "这个会话还没有产生用量。发一条消息后,这里会显示这个会话专属的费用与模型明细。";
198
+ readonly 'overview.title': "消耗概览(费用为估算)";
199
+ readonly 'overview.today': "今日";
200
+ readonly 'overview.month': "本月";
201
+ readonly 'overview.total': "累计";
202
+ readonly 'overview.vsYesterday': "较昨日";
203
+ readonly 'overview.vsLastMonth': "较上月同期";
204
+ readonly 'overview.empty': "还没有可统计的消耗。";
205
+ readonly 'usage.trendTitle': "用量趋势(tokens)";
206
+ readonly 'usage.windowInput': "{window}输入";
207
+ readonly 'usage.modelCalls': "模型调用";
208
+ readonly 'heatmap.title': "用量热力图";
209
+ readonly 'peak.title': "高峰 / 闲时分布";
210
+ readonly 'cache.title': "缓存命中与节省";
211
+ readonly 'models.title': "模型成本排行 · {window}";
212
+ readonly 'sessions.title': "会话成本排行 · {window}";
213
+ readonly 'links.title': "快捷入口";
214
+ readonly 'links.usage': "查看额度 / 用量";
215
+ readonly 'links.apiKey': "生成 API Key";
216
+ readonly 'links.status': "服务状态";
217
+ readonly 'settings.title': "设置";
218
+ readonly 'settings.widget': "在其他页面显示右下角悬浮额度窗口";
219
+ readonly 'settings.widgetHint': "额度页会自动隐藏浮窗;其他页面是否展示由下方选择决定。";
220
+ readonly 'settings.widgetTabs': "展示浮窗的页面";
221
+ readonly 'settings.widgetTabsHint': "页面列表来自 DSH 的实时 Tab 注册表;其他插件新增的 Tab 也会自动出现在这里。";
222
+ readonly 'settings.widgetTabsEmpty': "当前没有可配置的会话页面。";
223
+ readonly 'settings.lowBalance': "余额预警线";
224
+ readonly 'settings.lowBalanceOn': "余额低于 {amount} {currency} 时,这里和悬浮窗都会转为警示色。填 0 关闭。";
225
+ readonly 'settings.lowBalanceOff': "已关闭余额预警。填一个大于 0 的数开启。";
226
+ readonly 'settings.monthlyBudget': "月度预算";
227
+ readonly 'settings.monthlyBudgetOn': "按北京时间自然月跟踪 {amount} CNY 预算,并在消耗概览预测月底花费。填 0 关闭。";
228
+ readonly 'settings.monthlyBudgetOff': "填一个大于 0 的金额,消耗概览会显示进度与月底预测。";
229
+ readonly 'widget.updatedNow': "刚刚更新";
230
+ readonly 'widget.stale': "{minutes} 分钟前的数据,点 ↻ 更新";
231
+ readonly 'widget.loading': "查询中…";
232
+ readonly 'widget.lowTitle': "余额低于预警线 {amount}";
233
+ readonly 'widget.todayCostTitle': "今日消耗(估算)· {age}";
234
+ readonly 'widget.todayCost': "今日消耗";
235
+ readonly 'widget.sessionCostTitle': "当前会话累计消耗(估算)";
236
+ readonly 'widget.sessionCost': "当前会话";
237
+ readonly 'widget.noBalance': "暂无余额数据";
238
+ readonly 'widget.dragCard': "拖动到四个角落";
239
+ readonly 'widget.dragGrip': "拖动以移动";
240
+ readonly 'widget.refresh': "刷新余额与今日用量";
241
+ readonly 'widget.expand': "展开";
242
+ readonly 'widget.collapse': "收起";
243
+ readonly 'widget.expandAria': "展开额度窗口";
244
+ readonly 'widget.collapseAria': "收起额度窗口";
245
+ readonly 'messageCost.label': "本轮费用";
246
+ readonly 'messageCost.tooltip': "由 dsh-usage-dashboard 提供 · 本轮对话费用为估算值";
247
+ readonly 'messageCost.aria': "{amount},本轮对话估算费用,由 dsh-usage-dashboard 提供";
248
+ readonly 'boundary.title': "额度面板出错了";
249
+ readonly 'boundary.body': "渲染时抛了异常,通常是浏览器里存着旧版本的缓存数据。清掉本插件的本地数据再重新加载就能恢复。";
250
+ readonly 'boundary.reset': "清除本地数据并重新加载";
251
+ };
252
+ export type LocaleKey = keyof typeof zh;
253
+ export declare const en: Record<LocaleKey, string>;
@@ -0,0 +1,10 @@
1
+ /** Estimated spend contributed beside each completed chat turn. */
2
+ import { type ReactElement } from 'react';
3
+ export interface MessageCostProps {
4
+ sessionId: string;
5
+ messageId: string;
6
+ }
7
+ /** Small costs need more than the dashboard's two-decimal money formatter or
8
+ * almost every individual turn would misleadingly read as ¥0.00. */
9
+ export declare const fmtTurnCost: (cost: number) => string;
10
+ export declare function MessageCost({ sessionId, messageId }: MessageCostProps): ReactElement | null;
@@ -0,0 +1,12 @@
1
+ import { type Translate } from './i18n.tsx';
2
+ /** Value axis shared by daily, hourly, and per-model usage charts. */
3
+ export declare const CHART_METRICS: readonly ["tokens", "cost", "calls"];
4
+ export type ChartMetric = (typeof CHART_METRICS)[number];
5
+ export interface ChartMetricPoint {
6
+ total: number;
7
+ cost: number;
8
+ calls: number;
9
+ }
10
+ export declare const isChartMetric: (value: unknown) => value is ChartMetric;
11
+ export declare function chartMetricValue(metric: ChartMetric, point: ChartMetricPoint): number;
12
+ export declare function chartMetricName(metric: ChartMetric, t?: Translate): string;
@@ -5,6 +5,17 @@ export interface Store<T> {
5
5
  }
6
6
  /** Whether the floating balance widget is shown. */
7
7
  export declare const widgetVisibleStore: Store<boolean>;
8
+ /** Conversation view ids on which the widget is allowed to appear. `null`
9
+ * means "all available views" and preserves the pre-setting default; once a
10
+ * user customizes the list, newly installed plugin tabs arrive unchecked. */
11
+ export declare const widgetTabIdsStore: Store<string[] | null>;
8
12
  /** Balance (in the account's own currency) below which both surfaces warn.
9
13
  * 0 turns the warning off. */
10
14
  export declare const lowBalanceStore: Store<number>;
15
+ /** Monthly estimated-cost budget in CNY. 0 leaves budget tracking disabled. */
16
+ export declare const monthlyBudgetStore: Store<number>;
17
+ /** Shared time range for the usage chart and both cost rankings. */
18
+ export declare const usageWindowStore: Store<7 | 30 | 90 | 365>;
19
+ /** Whether charts compare token volume, estimated CNY cost, or call count. */
20
+ export declare const chartMetricStore: Store<"cost" | "calls" | "tokens">;
21
+ export declare const quotaViewActiveStore: Store<boolean>;
@@ -1,2 +1,2 @@
1
1
  /** All plugin styles in one sheet, injected once at client load. */
2
- export declare const css = "\n.dsh-quota-root{position:absolute;right:16px;bottom:16px;z-index:2147483000;pointer-events:auto;font-family:system-ui,-apple-system,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif;font-size:13px;line-height:1.45;color:var(--dsw-alias-label-primary,#1f2328);transition:left .28s cubic-bezier(.22,1,.36,1),top .28s cubic-bezier(.22,1,.36,1)}\n.dsh-quota-root.dsh-quota-dragging{transition:none}\n.dsh-quota-card,.dsh-quota-card *{box-sizing:border-box}\n.dsh-quota-card{background:var(--dsw-alias-bg-overlay,#ffffff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.12));border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.18);padding:12px 14px;min-width:208px;max-width:270px;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none}\n.dsh-quota-root.dsh-quota-dragging .dsh-quota-card{cursor:grabbing;box-shadow:0 12px 32px rgba(0,0,0,.28)}\n.dsh-quota-header{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px;min-width:0}\n.dsh-quota-title{font-weight:600;font-size:13px;color:var(--dsw-alias-label-primary,#1f2328);display:flex;align-items:center;gap:6px;min-width:0;overflow:hidden}\n.dsh-quota-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dsh-quota-grip{color:var(--dsw-alias-label-secondary,#59636e);opacity:.7;font-size:11px;letter-spacing:0;cursor:grab;flex:none}\n.dsh-quota-dot{width:8px;height:8px;border-radius:50%;background:var(--dsw-alias-state-success-primary,#2da44e);flex:none}\n.dsh-quota-dot--error{background:var(--dsw-alias-state-error-primary,#cf222e)}\n.dsh-quota-dot--warn{background:var(--dsw-alias-state-warning-primary,#bf8700)}\n.dsh-quota-total--low{color:var(--dsw-alias-state-warning-primary,#9a6700)!important}\n.dsh-quota-dot--idle{background:var(--dsw-alias-label-secondary,#59636e);opacity:.6}\n.dsh-quota-collapsed-total{font-weight:700;font-size:13px;color:var(--dsw-alias-brand-primary,#0969da);flex:none;font-variant-numeric:tabular-nums}\n.dsh-quota-actions{display:flex;gap:2px;flex:none}\n.dsh-quota-btn{border:none;background:transparent;cursor:pointer;color:var(--dsw-alias-label-secondary,#59636e);padding:3px 7px;border-radius:6px;font-size:13px;line-height:1}\n.dsh-quota-btn:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.06));color:var(--dsw-alias-label-primary,#1f2328)}\n.dsh-quota-btn:active:not(:disabled){transform:scale(.92)}\n.dsh-quota-btn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px}\n.dsh-quota-btn:disabled{opacity:.5;cursor:default}\n.dsh-quota-body{color:var(--dsw-alias-label-secondary,#59636e)}\n.dsh-quota-remaining-label{font-size:11px;color:var(--dsw-alias-label-tertiary,#59636e);margin-bottom:2px}\n.dsh-quota-total{font-size:24px;font-weight:700;color:var(--dsw-alias-label-primary,#1f2328);letter-spacing:-.02em;font-variant-numeric:tabular-nums}\n.dsh-quota-currency{font-size:14px;font-weight:600;margin-left:3px;color:var(--dsw-alias-label-secondary,#59636e)}\n.dsh-quota-row{display:flex;justify-content:space-between;gap:12px;margin-top:6px;font-size:12px}\n.dsh-quota-label{color:var(--dsw-alias-label-secondary,#59636e)}\n.dsh-quota-value{color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}\n.dsh-quota-error{color:var(--dsw-alias-state-error-primary,#cf222e)}\n.dq-balance{display:flex;flex-direction:column;gap:16px;padding:20px 24px 48px;max-width:860px;margin:0 auto;font-family:system-ui,-apple-system,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif;font-size:13px;line-height:1.5;color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-card{background:var(--dsw-alias-bg-layer-1,#ffffff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08));border-radius:12px;padding:16px}\n.dq-card-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary,#59636e);margin:0 0 12px;letter-spacing:.02em}\n.dq-balance-grid{display:flex;flex-wrap:wrap;gap:12px 24px}\n.dq-stat{min-width:110px}\n.dq-stat-label{font-size:11px;color:var(--dsw-alias-label-tertiary,#59636e);margin-bottom:2px}\n.dq-stat-value{font-size:18px;font-weight:650;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}\n.dq-stat-value--ok{color:var(--dsw-alias-state-success-primary,#2da44e)}\n.dq-stat-value--bad{color:var(--dsw-alias-state-error-primary,#cf222e)}\n.dq-runway{cursor:help;text-decoration:underline dotted var(--dsw-alias-border-l2,rgba(0,0,0,.25));text-underline-offset:4px}\n.dq-remaining{position:relative;cursor:help}\n.dq-remaining-breakdown{display:none;position:absolute;top:calc(100% + 6px);left:0;z-index:20;flex-direction:column;gap:4px;padding:8px 10px;background:var(--dsw-alias-bg-overlay,#ffffff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.12));border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.15);white-space:nowrap;font-size:12px;font-weight:500;color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-remaining:hover .dq-remaining-breakdown{display:flex}\n.dq-remaining-granted{color:var(--dsw-alias-label-tertiary,#59636e);font-weight:400;font-size:11px}\n.dq-period-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}\n@media (max-width:620px){.dq-period-grid{grid-template-columns:1fr}}\n.dq-period{background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.06));border-radius:10px;padding:12px 14px;min-width:0}\n.dq-period-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:4px}\n.dq-period-label{font-size:11px;color:var(--dsw-alias-label-tertiary,#59636e)}\n.dq-period-cost{font-size:22px;font-weight:680;letter-spacing:-.01em;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;line-height:1.25}\n.dq-period-sub{font-size:11.5px;color:var(--dsw-alias-label-secondary,#59636e);margin-top:2px;font-variant-numeric:tabular-nums;line-height:1.45}\n.dq-delta{display:inline-flex;align-items:center;gap:3px;font-size:11px;font-weight:600;padding:1px 6px;border-radius:999px;white-space:nowrap;cursor:help;font-variant-numeric:tabular-nums}\n.dq-delta--up{color:var(--dsw-alias-state-warning-primary,#9a6700);background:rgba(191,135,0,.14)}\n.dq-delta--down{color:var(--dsw-alias-state-success-primary,#1a7f37);background:rgba(45,164,78,.14)}\n.dq-delta--flat,.dq-delta--new{color:var(--dsw-alias-label-tertiary,#59636e);background:rgba(120,130,150,.14);font-weight:500}\n.dq-delta-label{font-weight:400;opacity:.8}\n.dq-pricing{margin-top:12px;border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08));padding-top:10px}\n.dq-pricing-summary{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);cursor:pointer;list-style:none;width:fit-content;border-radius:6px;padding:2px 4px;margin-left:-4px}\n.dq-pricing-summary::-webkit-details-marker{display:none}\n.dq-pricing-summary::before{content:\"\u25B8\";display:inline-block;font-size:10px;opacity:.7;transition:transform .15s ease}\n.dq-pricing[open] .dq-pricing-summary::before{transform:rotate(90deg)}\n.dq-pricing-summary:hover{color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-pricing-summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}\n.dq-pricing-now{font-size:11px;font-weight:600;padding:1px 7px;border-radius:999px;color:var(--dsw-alias-label-tertiary,#59636e);background:rgba(120,130,150,.14)}\n.dq-pricing-now--peak{color:var(--dsw-alias-state-warning-primary,#9a6700);background:rgba(191,135,0,.14)}\n.dq-pricing-body{margin-top:10px;overflow-x:auto}\n.dq-pricing-table{border-collapse:collapse;font-size:11.5px;font-variant-numeric:tabular-nums;min-width:100%}\n.dq-pricing-table th{text-align:left;font-weight:500;color:var(--dsw-alias-label-tertiary,#59636e);padding:4px 12px 4px 0;white-space:nowrap;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}\n.dq-pricing-table td{padding:4px 12px 4px 0;color:var(--dsw-alias-label-primary,#1f2328);white-space:nowrap;vertical-align:top}\n.dq-pricing-table tbody tr+tr td{border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.05))}\n.dq-pricing-foot{margin:8px 0 0;font-size:11.5px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-peak-track{height:8px;border-radius:999px;background:var(--dsw-alias-state-success-primary,#2da44e);opacity:.85;overflow:hidden}\n.dq-peak-fill{height:100%;border-radius:999px;background:var(--dsw-alias-state-warning-primary,#bf8700);transition:width .35s cubic-bezier(.22,1,.36,1)}\n.dq-peak-legend{display:flex;flex-wrap:wrap;gap:6px 20px;margin-top:8px;font-size:11.5px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}\n.dq-peak-legend span{display:inline-flex;align-items:center;gap:6px}\n.dq-legend-swatch--peak{background:var(--dsw-alias-state-warning-primary,#bf8700)}\n.dq-legend-swatch--offpeak{background:var(--dsw-alias-state-success-primary,#2da44e);opacity:.85}\n.dq-peak-figures{display:flex;flex-wrap:wrap;gap:12px 32px;margin-top:14px}\n.dq-peak-delta{font-size:11px;font-weight:500;margin-left:8px;color:var(--dsw-alias-state-warning-primary,#9a6700)}\n.dq-peak-delta--save{color:var(--dsw-alias-state-success-primary,#1a7f37)}\n.dq-peak-foot{margin:10px 0 0;font-size:11.5px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-cache-figures{display:flex;flex-wrap:wrap;gap:12px 32px;margin-bottom:12px}\n.dq-muted-value{color:var(--dsw-alias-label-secondary,#59636e)!important;font-weight:550}\n.dq-stat-value--warn{color:var(--dsw-alias-state-warning-primary,#9a6700)}\n.dq-cache-track{height:8px;border-radius:999px;background:var(--dsw-alias-state-warning-primary,#bf8700);overflow:hidden}\n.dq-cache-fill{height:100%;border-radius:999px;background:var(--dsw-alias-state-success-primary,#2da44e);transition:width .35s cubic-bezier(.22,1,.36,1)}\n.dq-cache-legend{display:flex;flex-wrap:wrap;gap:6px 18px;margin-top:8px;font-size:11.5px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}\n.dq-cache-legend span{display:inline-flex;align-items:center;gap:6px}\n.dq-legend-swatch--hit{background:var(--dsw-alias-state-success-primary,#2da44e)}\n.dq-legend-swatch--miss{background:var(--dsw-alias-state-warning-primary,#bf8700)}\n.dq-cache-foot{margin:10px 0 0;font-size:11.5px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-sessions{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:14px}\n.dq-session{display:flex;flex-direction:column;gap:5px;min-width:0}\n.dq-session-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px}\n.dq-session-title{font-size:13px;font-weight:550;color:var(--dsw-alias-label-primary,#1f2328);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dq-session-cost{font-size:14px;font-weight:650;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;flex:none}\n.dq-session-track{height:6px;border-radius:999px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.12));overflow:hidden}\n.dq-session-fill{height:100%;border-radius:999px;background:var(--dsw-alias-state-business-primary,#4176e6);transition:width .35s cubic-bezier(.22,1,.36,1)}\n.dq-session-sub{font-size:11.5px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums;line-height:1.5}\n.dq-session-foot{margin:12px 0 0;font-size:11.5px;color:var(--dsw-alias-label-tertiary,#59636e)}\n.dq-rank{display:flex;flex-direction:column;gap:14px}\n.dq-rank-row{display:flex;flex-direction:column;gap:5px;min-width:0}\n.dq-rank-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px}\n.dq-rank-name{display:inline-flex;align-items:center;gap:7px;font-size:13px;font-weight:550;color:var(--dsw-alias-label-primary,#1f2328);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dq-rank-cost{display:inline-flex;align-items:baseline;gap:8px;font-size:14px;font-weight:650;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;flex:none}\n.dq-rank-share{font-size:11px;font-weight:500;color:var(--dsw-alias-label-tertiary,#59636e);min-width:30px;text-align:right}\n.dq-rank-track{height:6px;border-radius:999px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.12));overflow:hidden}\n.dq-rank-fill{height:100%;border-radius:999px;transition:width .35s cubic-bezier(.22,1,.36,1)}\n.dq-rank-sub{font-size:11.5px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums;line-height:1.5}\n.dq-alert{display:flex;align-items:flex-start;gap:10px;padding:12px 14px;border-radius:10px;font-size:12.5px;line-height:1.6;color:var(--dsw-alias-state-warning-primary,#7a5200);background:rgba(191,135,0,.12);border:1px solid rgba(191,135,0,.35)}\n.dq-alert-icon{flex:none;width:18px;height:18px;border-radius:50%;background:var(--dsw-alias-state-warning-primary,#bf8700);color:#fff;font-weight:700;font-size:12px;line-height:18px;text-align:center}\n.dq-alert strong{font-weight:650}\n.dq-alert-link{margin-left:8px;color:inherit;text-decoration:underline;text-underline-offset:2px;white-space:nowrap}\n.dq-setting{display:flex;align-items:flex-start;gap:12px;margin-top:14px;padding-top:14px;border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}\n.dq-setting-label{font-size:13px;color:var(--dsw-alias-label-primary,#1f2328);padding-top:6px;flex:none}\n.dq-setting-control{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-width:0}\n.dq-setting-hint{font-size:11.5px;color:var(--dsw-alias-label-secondary,#59636e);line-height:1.5}\n.dq-number{width:82px;padding:5px 8px;font-size:13px;border-radius:8px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.16));background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}\n.dq-number:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px;border-color:transparent}\n.dq-links{display:flex;flex-wrap:wrap;gap:8px}\n.dq-link{display:inline-flex;align-items:center;gap:6px;padding:7px 12px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.12));border-radius:8px;background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-state-business-primary,#0969da);text-decoration:none;font-size:13px;font-weight:500;cursor:pointer}\n.dq-link:hover{border-color:var(--dsw-alias-state-business-primary,#0969da);background:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.04))}\n.dq-toggle{display:flex;align-items:center;gap:10px;cursor:pointer;font-size:13px}\n.dq-toggle input{width:16px;height:16px;accent-color:var(--dsw-alias-state-business-primary,#0969da);cursor:pointer}\n.dq-toggle input:focus-visible,.dq-model-item input:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}\n.dq-link:focus-visible,.dq-model-btn:focus-visible,.dq-chart-switch-btn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}\n.dq-usage-totals{display:flex;flex-wrap:wrap;gap:12px 24px;margin-bottom:16px}\n.dq-chart-peak{margin-left:10px;font-size:11px;font-weight:400;color:var(--dsw-alias-label-tertiary,#59636e);font-variant-numeric:tabular-nums}\n.dq-chart-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary,#59636e);margin:18px 0 8px}\n.dq-chart-title:first-of-type{margin-top:0}\n.dq-chart-block-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:18px 0 8px}\n.dq-chart-block-head .dq-chart-title{margin:0}\n.dq-chart-controls{display:flex;align-items:center;gap:8px;flex:none}\n.dq-model-picker{position:relative}\n.dq-model-btn{border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.12));background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#59636e);border-radius:8px;padding:4px 10px;font-size:12px;cursor:pointer;display:inline-flex;align-items:center;gap:6px}\n.dq-model-btn:hover{border-color:var(--dsw-alias-state-business-primary,#0969da);color:var(--dsw-alias-state-business-primary,#0969da)}\n.dq-model-btn::after{content:\"\u25BE\";font-size:10px;opacity:.7}\n.dq-model-menu{position:absolute;right:0;top:calc(100% + 6px);z-index:30;min-width:190px;max-height:280px;overflow-y:auto;background:var(--dsw-alias-bg-overlay,#fff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.12));border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,.16);padding:6px;display:flex;flex-direction:column;gap:2px}\n.dq-model-item{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;font-size:12px;cursor:pointer;color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-model-item:hover{background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.06))}\n.dq-model-item input{width:14px;height:14px;accent-color:var(--dsw-alias-state-business-primary,#0969da);cursor:pointer;flex:none}\n.dq-model-item span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dq-model-item--all{border-bottom:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08));padding-bottom:8px;margin-bottom:2px;border-radius:6px}\n.dq-model-tag{color:var(--dsw-alias-label-tertiary,#59636e);font-size:11px;flex:none}\n.dq-bar-group{display:flex;align-items:flex-end;gap:2px;height:100%;width:100%}\n.dq-bar-group .dq-bar{flex:1 1 0;min-width:0}\n.dq-legend{display:flex;flex-wrap:wrap;gap:6px 14px;margin-top:8px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-legend-item{display:inline-flex;align-items:center;gap:6px}\n.dq-legend-swatch{width:10px;height:10px;border-radius:3px;flex:none}\n.dq-chart-switch{display:inline-flex;align-items:center;gap:2px;padding:2px;background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.06));border-radius:999px;flex:none}\n.dq-chart-switch-btn{border:none;background:transparent;color:var(--dsw-alias-label-secondary,#59636e);font-size:12px;line-height:1;padding:5px 12px;border-radius:999px;cursor:pointer;transition:background .15s ease,color .15s ease}\n.dq-chart-switch-btn:hover{color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-chart-switch-btn--on{background:var(--dsw-alias-bg-overlay,#fff);color:var(--dsw-alias-label-primary,#1f2328);box-shadow:0 1px 3px rgba(0,0,0,.14)}\n.dq-chart-wrap{position:relative}\n.dq-tip{position:absolute;transform:translate(-50%,14px);z-index:40;pointer-events:none;background:var(--dsw-alias-bg-inverse,#1f2328);color:var(--dsw-alias-label-inverse,#fff);border-radius:8px;padding:7px 10px;font-size:11.5px;line-height:1.55;white-space:nowrap;box-shadow:0 6px 20px rgba(0,0,0,.28);font-variant-numeric:tabular-nums}\n.dq-tip-head{font-weight:650;margin-bottom:2px}\n.dq-tip-row{opacity:.85}\n.dq-bars{display:flex;align-items:flex-end;gap:2px;width:100%}\n.dq-bar-col{flex:1 1 0;min-width:0;display:flex;flex-direction:column;justify-content:flex-end;align-items:stretch}\n.dq-bar{background:var(--dsw-alias-state-business-primary,#4176e6);border-radius:2px 2px 0 0;min-height:1px;transition:filter .12s ease}\n.dq-bar-col{cursor:default}\n.dq-bar-col:hover .dq-bar{filter:brightness(1.18) saturate(1.1)}\n.dq-heat-cell:not(.dq-heat-cell--pad):hover{outline:1.5px solid var(--dsw-alias-label-primary,#1f2328);outline-offset:1px}\n.dq-bar-label{font-size:9px;color:var(--dsw-alias-label-tertiary,#59636e);text-align:center;margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dq-heat{display:flex;flex-direction:column;gap:8px;max-width:100%}\n.dq-heat-grid{display:flex;gap:6px;overflow-x:auto;padding-bottom:2px}\n.dq-heat-dows{display:flex;flex-direction:column;gap:3px;padding-top:17px;flex:none}\n.dq-heat-dow{height:12px;line-height:12px;font-size:9px;color:var(--dsw-alias-label-tertiary,#59636e);text-align:right;width:12px}\n.dq-heat-cols{display:flex;flex-direction:column;gap:2px;min-width:0}\n.dq-heat-months{display:flex;gap:3px;height:12px}\n.dq-heat-month{width:12px;flex:none;font-size:9px;line-height:12px;color:var(--dsw-alias-label-tertiary,#59636e);white-space:nowrap;overflow:visible}\n.dq-heatmap{display:flex;gap:3px;width:max-content}\n.dq-heat-week{display:flex;flex-direction:column;gap:3px}\n.dq-heat-cell{width:12px;height:12px;border-radius:2px;flex:none}\n.dq-heat-cell--pad{background:transparent}\n.dq-heat-key{width:12px;height:12px;border-radius:2px;flex:none}\n.dq-heat-scale{display:flex;align-items:center;gap:3px;font-size:10px;color:var(--dsw-alias-label-tertiary,#59636e);align-self:flex-end}\n.dq-heat-scale>span:first-child{margin-right:2px}\n.dq-heat-scale>span:last-child{margin-left:2px}\n.dq-muted{color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-error{color:var(--dsw-alias-state-error-primary,#cf222e)}\n.dq-warn{color:var(--dsw-alias-state-warning-primary,#9a6700)}\n.dq-crash{margin:10px 0 14px;padding:10px 12px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.10));border-radius:8px;font-size:11.5px;line-height:1.5;color:var(--dsw-alias-state-error-primary,#cf222e);white-space:pre-wrap;word-break:break-word;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}\n.dq-empty{color:var(--dsw-alias-label-secondary,#59636e);font-size:12.5px;line-height:1.6;padding:6px 0}\n.dq-skel{background:linear-gradient(90deg,rgba(125,135,155,.10) 25%,rgba(125,135,155,.20) 37%,rgba(125,135,155,.10) 63%);background-size:400% 100%;border-radius:5px;animation:dq-shimmer 1.5s ease-in-out infinite}\n.dq-stat .dq-skel+.dq-skel{margin-top:6px}\n.dq-skel-bars{display:flex;align-items:flex-end;gap:2px;width:100%;height:120px;margin-top:10px}\n.dq-skel-bar{flex:1 1 0;min-width:0;border-radius:2px 2px 0 0}\n@keyframes dq-shimmer{0%{background-position:100% 50%}100%{background-position:0 50%}}\n@media (prefers-reduced-motion:reduce){.dq-skel{animation:none}.dq-refresh-icon--spin{animation:none}}\n.dq-status-row{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:20px}\n.dq-status-row .dq-muted,.dq-status-row .dq-error{font-size:12px}\n.dq-refresh-btn{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.12));background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#59636e);border-radius:8px;padding:5px 10px;font-size:12px;cursor:pointer;transition:border-color .15s ease,color .15s ease}\n.dq-refresh-btn:hover:not(:disabled){border-color:var(--dsw-alias-state-business-primary,#0969da);color:var(--dsw-alias-state-business-primary,#0969da)}\n.dq-refresh-btn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}\n.dq-refresh-btn:disabled{cursor:default;opacity:.6}\n.dq-refresh-icon{display:inline-block;line-height:1}\n.dq-refresh-icon--spin{animation:dq-spin .9s linear infinite}\n@keyframes dq-spin{to{transform:rotate(360deg)}}\n";
2
+ export declare const css = "\n.dsh-quota-root{position:absolute;right:16px;bottom:16px;z-index:2147483000;pointer-events:auto;opacity:1;visibility:visible;font-family:system-ui,-apple-system,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif;font-size:13px;line-height:1.45;color:var(--dsw-alias-label-primary,#1f2328);transition:left .28s cubic-bezier(.22,1,.36,1),top .28s cubic-bezier(.22,1,.36,1),opacity .16s ease-out,visibility 0s linear}\n.dsh-quota-root.dsh-quota-root--hidden{opacity:0;visibility:hidden;pointer-events:none;transition:opacity .14s ease-out,visibility 0s linear .14s}\n.dsh-quota-root.dsh-quota-dragging{transition:none}\n.dsh-quota-card,.dsh-quota-card *{box-sizing:border-box}\n.dsh-quota-card{background:var(--dsw-alias-bg-overlay,#ffffff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.12));border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.18);padding:12px 14px;min-width:208px;max-width:270px;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none}\n.dsh-quota-root.dsh-quota-dragging .dsh-quota-card{cursor:grabbing;box-shadow:0 12px 32px rgba(0,0,0,.28)}\n.dsh-quota-header{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px;min-width:0}\n.dsh-quota-title{font-weight:600;font-size:13px;color:var(--dsw-alias-label-primary,#1f2328);display:flex;align-items:center;gap:6px;min-width:0;overflow:hidden}\n.dsh-quota-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dsh-quota-grip{color:var(--dsw-alias-label-secondary,#59636e);opacity:.7;font-size:11px;letter-spacing:0;cursor:grab;flex:none}\n.dsh-quota-dot{width:8px;height:8px;border-radius:50%;background:var(--dsw-alias-state-success-primary,#2da44e);flex:none}\n.dsh-quota-dot--error{background:var(--dsw-alias-state-error-primary,#cf222e)}\n.dsh-quota-dot--warn{background:var(--dsw-alias-state-warning-primary,#bf8700)}\n.dsh-quota-total--low{color:var(--dsw-alias-state-warning-primary,#9a6700)!important}\n.dsh-quota-dot--idle{background:var(--dsw-alias-label-secondary,#59636e);opacity:.6}\n.dsh-quota-collapsed-total-row{margin-top:6px}\n.dsh-quota-collapsed-total{font-weight:700;font-size:15px;color:var(--dsw-alias-state-business-primary,#0969da);font-variant-numeric:tabular-nums}\n.dsh-quota-actions{display:flex;gap:2px;flex:none}\n.dsh-quota-btn{border:none;background:transparent;cursor:pointer;color:var(--dsw-alias-label-secondary,#59636e);padding:3px 7px;border-radius:6px;font-size:13px;line-height:1}\n.dsh-quota-btn:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.06));color:var(--dsw-alias-label-primary,#1f2328)}\n.dsh-quota-btn:active:not(:disabled){transform:scale(.92)}\n.dsh-quota-btn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px}\n.dsh-quota-btn:disabled{opacity:.5;cursor:default}\n.dsh-quota-body{color:var(--dsw-alias-label-secondary,#59636e)}\n.dsh-quota-remaining-label{font-size:11px;color:var(--dsw-alias-label-tertiary,#59636e);margin-bottom:2px}\n.dsh-quota-total{font-size:24px;font-weight:700;color:var(--dsw-alias-label-primary,#1f2328);letter-spacing:-.02em;font-variant-numeric:tabular-nums}\n.dsh-quota-currency{font-size:14px;font-weight:600;margin-left:3px;color:var(--dsw-alias-label-secondary,#59636e)}\n.dsh-quota-row{display:flex;justify-content:space-between;gap:12px;margin-top:6px;font-size:12px}\n.dsh-quota-label{color:var(--dsw-alias-label-secondary,#59636e)}\n.dsh-quota-value{color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}\n.dsh-quota-error{color:var(--dsw-alias-state-error-primary,#cf222e)}\n.dq-message-cost{position:relative;display:inline-flex;align-items:center;order:10;gap:10px;height:28px;color:var(--dsw-alias-label-tertiary,#59636e);font-size:12px;line-height:20px;font-variant-numeric:tabular-nums;white-space:nowrap;cursor:help}\n.dq-message-cost-separator{cursor:default}\n.dq-message-cost-amount{text-decoration-line:underline;text-decoration-style:dotted;text-decoration-color:currentColor;text-underline-offset:4px}\n.dq-message-cost:hover{color:var(--dsw-alias-label-secondary,#3f4852)}\n.dq-message-cost:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px;border-radius:4px}\n.dq-message-cost::after{content:attr(data-dq-tooltip);position:absolute;left:0;top:calc(100% + 6px);z-index:2147483001;width:max-content;max-width:min(240px,calc(100vw - 24px));padding:6px 9px;border-radius:8px;background:var(--dsw-alias-bg-inverse,#1f2328);color:var(--dsw-alias-label-inverse,#fff);box-shadow:0 6px 18px rgba(0,0,0,.22);font-size:12px;font-weight:400;line-height:1.45;text-align:left;white-space:normal;pointer-events:none;opacity:0;visibility:hidden;transform:translateY(-3px);transition:opacity .12s ease-out,transform .12s cubic-bezier(.22,1,.36,1),visibility 0s linear .12s}\n.dq-message-cost:hover::after,.dq-message-cost:focus-visible::after{opacity:1;visibility:visible;transform:translateY(0);transition:opacity .12s ease-out,transform .12s cubic-bezier(.22,1,.36,1),visibility 0s linear}\n@media (hover:hover){\n [data-time-hover-root] .dq-message-cost{opacity:0;transition:opacity 80ms ease}\n [data-time-hover-root]:hover .dq-message-cost,[data-time-hover-root]:focus-within .dq-message-cost{opacity:1}\n}\n/* \u5361\u7247\u95F4\u8DDD\uFF08\u6B64\u5904 gap\uFF09\u523B\u610F\u5927\u4E8E\u5361\u5185\u5C0F\u8282\u95F4\u8DDD\uFF08margin-top:12/14/16px \u90A3\u4E00\u6863\uFF09\uFF0C\u5236\u9020\"\u5361\u7247\u5916\u758F\u3001\u5361\u7247\u5185\u5BC6\"\u7684\n \u758F\u5BC6\u5BF9\u6BD4\uFF1A24px \u76F8\u5BF9\u5361\u5185\u6700\u5927\u6863 16px \u4ECD\u6709 1.5 \u500D\u7EA7\u5DEE\uFF0C\u76F8\u5BF9\u5E38\u89C1\u6863 12px \u6709 2 \u500D\u7EA7\u5DEE\uFF0C\u4E0D\u4E0E .dq-card \u7684\n padding\uFF0816px/20px\uFF0C\u5361\u7247\u5185\u90E8\u547C\u5438\u611F\uFF0C\u8F6E\u6B21 36 \u5DF2\u5B9A\uFF09\u6DF7\u540C\u3002 */\n.dq-balance{display:flex;flex-direction:column;gap:24px;padding:20px 24px 48px;max-width:860px;margin:0 auto;font-family:system-ui,-apple-system,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif;font-size:13px;line-height:1.5;color:var(--dsw-alias-label-primary,#1f2328)}\n@media (max-width:620px){.dq-balance{box-sizing:border-box;max-width:calc(100vw - 56px);padding:16px 16px calc(var(--dq-composer-h,126px) + 16px)}}\n.dq-card{background:var(--dsw-alias-bg-layer-1,#ffffff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08));border-radius:12px;padding:16px}\n.dq-card-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary,#59636e);margin:0 0 12px;letter-spacing:.02em}\n.dq-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px}\n.dq-card-head .dq-card-title{margin:0}\n.dq-card-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px;min-width:0}\n/* \u4E3B\u5361\u7247\uFF08\u4F59\u989D/\u5F53\u524D\u4F1A\u8BDD\u6D88\u8017/\u6D88\u8017\u6982\u89C8/\u7528\u91CF\u8D8B\u52BF\uFF0C\u8F6E\u6B21 45 \u65B0\u589E\u300C\u5F53\u524D\u4F1A\u8BDD\u6D88\u8017\u300D\uFF09\u89C6\u89C9\u6743\u91CD\u9AD8\u4E8E\u6B21\u7EA7\u5206\u6790\n \u5361\u7247\u4E0E\u5BFC\u822A\u7C7B\u5361\u7247\uFF1A\u53EA\u8C03\u6392\u7248\u5C5E\u6027\u2014\u2014\u5185\u8FB9\u8DDD\u3001\u6807\u9898\u5B57\u53F7\u5B57\u91CD\u4E0E\u53D6\u8272\u3001\u8FB9\u6846\u6DF1\u6D45\u2014\u2014\u4E0D\u5F15\u5165\u65B0\u914D\u8272\u4F53\u7CFB\u3002\u4E24\u6761\u89C4\u5219\n \u4E0E\u4E0A\u9762\u7684\u57FA\u7840\u89C4\u5219\u540C\u4E3A\u5355\u7C7B\u9009\u62E9\u5668\u4E14\u6E90\u7801\u987A\u5E8F\u66F4\u9760\u540E\uFF0C\u5929\u7136\u8986\u76D6\uFF0C\u4E0D\u9700\u8981 !important\u3002\u6B21\u7EA7\u5206\u6790\u5361\u7247\uFF08\u7528\u91CF\n \u70ED\u529B\u56FE/\u9AD8\u5CF0\u95F2\u65F6/\u7F13\u5B58\u547D\u4E2D/\u6A21\u578B\u6392\u884C/\u4F1A\u8BDD\u6392\u884C\uFF09\u4E0E\u5BFC\u822A\u7C7B\u5361\u7247\uFF08\u8BBE\u7F6E\uFF0C\u542B\u8F6E\u6B21 39 \u5E76\u5165\u7684\u5B98\u65B9\u5E73\u53F0\u94FE\u63A5\uFF09\u90FD\u4E0D\u52A0\n \u8FD9\u4E2A\u4FEE\u9970\u7C7B\uFF0C\u7EF4\u6301\u539F\u6709 .dq-card \u57FA\u7EBF\uFF0C\u5F62\u6210\u4E24\u6863\u6743\u91CD\u3002\u300C\u5F53\u524D\u4F1A\u8BDD\u6D88\u8017\u300D\u5347\u7EA7\u4E3A\u4E3B\u5361\u7247\u7684\u7406\u7531\uFF1A\u5B83\u548C\u4F59\u989D\u4E00\u6837\u662F\n \u6253\u5F00\u8FD9\u4E2A\u300C\u989D\u5EA6\u300Dtab \u65F6\u4E0A\u4E0B\u6587\u6700\u76F4\u63A5\u76F8\u5173\u7684\u6570\u5B57\uFF08\u8FD9\u4E2A tab \u6302\u5728\u5177\u4F53\u4F1A\u8BDD\u5185\u90E8\uFF0C\u89C1 DESIGN_NOTES\u300C\u4FE1\u606F\u5C42\u7EA7\u300D\uFF09\uFF0C\n \u4E0D\u5C5E\u4E8E\u539F\u6709\u8D26\u6237\u5168\u5C40\u5C42\u7EA7 1-3 \u7684\u4EFB\u4F55\u4E00\u7EA7\uFF0C\u800C\u662F\u4E0E\u4E4B\u6B63\u4EA4\u7684\u53E6\u4E00\u4E2A\u7EF4\u5EA6\uFF0C\u4F46\u540C\u6837\u662F\u9996\u5C4F\u5FC5\u8BFB\uFF0C\u56E0\u6B64\u540C\u6837\u7ED9\n primary \u6743\u91CD\uFF0C\u4E0D\u65B0\u5F00\u7B2C\u4E09\u6863\u3002 */\n.dq-card--primary{padding:20px;border-color:var(--dsw-alias-border-l2,rgba(0,0,0,.12))}\n.dq-card--primary .dq-card-title{font-size:13px;font-weight:700;color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-window-switch{display:inline-flex;align-items:center;gap:2px;padding:2px;border-radius:8px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.08))}\n.dq-window-btn{border:0;border-radius:6px;padding:4px 8px;background:transparent;color:var(--dsw-alias-label-secondary,#59636e);font-size:12px;white-space:nowrap;cursor:pointer;transition:background .15s ease,color .15s ease,box-shadow .15s ease}\n.dq-window-btn:hover{color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-window-btn--on{background:var(--dsw-alias-bg-overlay,#fff);color:var(--dsw-alias-label-primary,#1f2328);box-shadow:0 1px 3px rgba(0,0,0,.12)}\n.dq-window-btn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}\n@media (max-width:620px){.dq-card-head{align-items:flex-start;flex-wrap:wrap}.dq-card-actions{width:100%;justify-content:space-between}}\n.dq-export{position:relative;flex:none}\n.dq-export-btn{min-width:58px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.12));background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#59636e);border-radius:8px;padding:4px 10px;font-size:12px;cursor:pointer;transition:border-color .15s ease,color .15s ease,background .15s ease}\n.dq-export-btn:hover{border-color:var(--dsw-alias-state-business-primary,#0969da);color:var(--dsw-alias-state-business-primary,#0969da)}\n.dq-export-btn--done{border-color:rgba(45,164,78,.35);color:var(--dsw-alias-state-success-primary,#1a7f37);background:rgba(45,164,78,.08)}\n.dq-export-menu{position:absolute;right:0;top:calc(100% + 6px);z-index:30;min-width:180px;padding:6px;background:var(--dsw-alias-bg-overlay,#fff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.12));border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,.16);display:flex;flex-direction:column;gap:2px}\n.dq-export-menu button{display:flex;align-items:center;justify-content:space-between;gap:16px;width:100%;border:0;border-radius:6px;padding:7px 8px;background:transparent;color:var(--dsw-alias-label-primary,#1f2328);font-size:12px;text-align:left;cursor:pointer}\n.dq-export-menu button:hover,.dq-export-menu button:focus-visible{background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.06))}\n.dq-export-menu button:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:-1px}\n.dq-export-menu small{font-size:10.5px;font-weight:400;color:var(--dsw-alias-label-tertiary,#59636e);white-space:nowrap}\n/* Small-text tier system (\u8F6E\u6B21 41 \u6536\u655B): two whole-pixel tiers replace what used to be four values\n (11/11.5/12/12.5px) spaced only 0.5px apart \u2014 a gap browsers subpixel-round away, so it read as one\n size with extra maintenance cost, not an actual visual hierarchy. 11px = \"micro\" chrome the user\n scans rather than reads (dt-style stat/period labels, delta/status/coverage pills, share %, tags,\n the widget grip) \u2014 kept as-is. 12px = \"secondary text\" (section titles, hint/footnote/legend/sub\n prose, table cells, tooltip copy, alert/empty-state sentences, and filter/segmented-control button\n labels like .dq-window-btn/.dq-chart-switch-btn, which are the same control family and should share\n one size) \u2014 absorbed the old 11.5px and 12.5px selectors, all by rounding toward the nearer tier\n (11.5\u219212 grows slightly for legibility, safe because none of the affected containers are width-\n capped; 12.5\u219212 shrinks by 0.5px on two full-sentence blocks, imperceptible). Weight/color still do\n the job of separating titles from body text within the 12px tier, same as before this merge. Do not\n reintroduce a fractional-px value in this range; if a selector needs to stand apart from these two,\n it belongs in an already-established different tier (10px icon glyphs, 13px+ hero-adjacent text). */\n.dq-balance-grid{display:flex;flex-wrap:wrap;gap:12px 24px}\n.dq-stat{min-width:110px}\n.dq-stat-label{font-size:11px;color:var(--dsw-alias-label-tertiary,#59636e);margin-bottom:2px}\n.dq-stat-value{font-size:18px;font-weight:650;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}\n.dq-stat-value--ok{color:var(--dsw-alias-state-success-primary,#2da44e)}\n.dq-stat-value--bad{color:var(--dsw-alias-state-error-primary,#cf222e)}\n/* \u8F6E\u6B21 43: .dq-runway is a controlled <details> (see dashboard.tsx) \u2014 hover/toggle state\n drives the real open attribute now, so .dq-runway-detail only needs to react to [open];\n an unopened <details>'s non-summary children don't actually render in current Chromium no\n matter what display value author CSS gives them (:hover{display:block} alone is a dead end). */\n.dq-runway{position:relative}\n.dq-runway>summary{display:inline-block;list-style:none;border-radius:4px;cursor:pointer;text-decoration:underline dotted var(--dsw-alias-border-l2,rgba(0,0,0,.25));text-underline-offset:4px}\n.dq-runway>summary::-webkit-details-marker{display:none}\n.dq-runway>summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:3px}\n.dq-runway-detail{display:none;position:absolute;top:calc(100% + 6px);left:0;z-index:20;max-width:240px;padding:8px 10px;background:var(--dsw-alias-bg-overlay,#ffffff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.12));border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.15);white-space:normal;font-size:12px;font-weight:500;line-height:1.5;color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-runway[open] .dq-runway-detail{display:block}\n/* hero number for the balance, matching .dq-period-cost; relies on cascade order (declared after\n .dq-stat-value, same specificity) to win over the .dq-stat-value it's paired with in JSX \u2014 keep it below */\n/* \u8F6E\u6B21 47: .dq-remaining is a controlled <details> too now (see dashboard.tsx), same reason as\n .dq-runway above \u2014 an unopened <details>'s non-summary children don't actually render in current\n Chromium regardless of author display value, so the old :hover{display:flex} branch was dead code. */\n.dq-remaining{position:relative;font-size:22px;font-weight:680;letter-spacing:-.01em;line-height:1.25}\n.dq-remaining>summary{display:inline-block;list-style:none;border-radius:4px;cursor:pointer;text-decoration:underline dotted var(--dsw-alias-border-l2,rgba(0,0,0,.25));text-underline-offset:4px}\n.dq-remaining>summary::-webkit-details-marker{display:none}\n.dq-remaining>summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:3px}\n.dq-remaining-breakdown{display:none;position:absolute;top:calc(100% + 6px);left:0;z-index:20;flex-direction:column;gap:4px;padding:8px 10px;background:var(--dsw-alias-bg-overlay,#ffffff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.12));border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.15);white-space:nowrap;font-size:12px;font-weight:500;color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-remaining[open] .dq-remaining-breakdown{display:flex}\n.dq-remaining-granted{color:var(--dsw-alias-label-tertiary,#59636e);font-weight:400;font-size:11px}\n/* narrow screens: .dq-balance-grid wraps its 3 stats onto separate lines, so the absolutely-positioned\n .dq-remaining-breakdown/.dq-runway-detail popovers can float down over whichever stat now sits in the\n next row (e.g. \"\u4F59\u989D\u660E\u7EC6\" open covering \"\u9884\u8BA1\u53EF\u7528\"'s clickable summary) \u2014 force each stat onto its own\n full-width row and switch both popovers to normal in-flow layout so an open one pushes its own row\n taller instead of overlaying a sibling; desktop keeps the original hover-overlay behavior unchanged */\n@media (max-width:620px){\n .dq-balance-grid .dq-stat{flex:1 1 100%}\n .dq-remaining-breakdown,.dq-runway-detail{position:static;margin-top:6px;box-shadow:none;max-width:none;white-space:normal}\n}\n.dq-period-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0}\n.dq-period{min-width:0;padding:4px 16px}\n.dq-period:first-child{padding-left:0}\n.dq-period:last-child{padding-right:0}\n.dq-period+.dq-period{border-left:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}\n@media (max-width:620px){.dq-period-grid{grid-template-columns:1fr}.dq-period,.dq-period:first-child,.dq-period:last-child{padding:12px 0}.dq-period:first-child{padding-top:2px}.dq-period+.dq-period{border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08));border-left:0}}\n.dq-period-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:4px}\n.dq-period-label{font-size:11px;color:var(--dsw-alias-label-tertiary,#59636e)}\n.dq-period-cost{font-size:22px;font-weight:680;letter-spacing:-.01em;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;line-height:1.25}\n.dq-period-sub{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);margin-top:2px;font-variant-numeric:tabular-nums;line-height:1.45}\n.dq-budget{margin-top:12px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}\n.dq-budget--unset{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-budget-action{border:0;background:transparent;padding:3px 4px;border-radius:5px;color:var(--dsw-alias-state-business-primary,#0969da);font:inherit;font-weight:600;white-space:nowrap;cursor:pointer}\n.dq-budget-action:hover{text-decoration:underline;text-underline-offset:3px}\n.dq-budget-action:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px}\n.dq-budget-head,.dq-budget-meta{display:flex;align-items:center;justify-content:space-between;gap:12px}\n.dq-budget-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-budget-amount{font-size:12px;font-weight:650;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}\n.dq-budget-track{height:8px;margin-top:8px;border-radius:999px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.12));overflow:hidden}\n.dq-budget-fill{width:100%;height:100%;border-radius:999px;background:var(--dsw-alias-state-success-primary,#2da44e);transform-origin:left center;transition:transform .35s cubic-bezier(.22,1,.36,1)}\n.dq-budget--risk .dq-budget-fill{background:var(--dsw-alias-state-warning-primary,#bf8700)}\n.dq-budget--over .dq-budget-fill{background:var(--dsw-alias-state-error-primary,#cf222e)}\n.dq-budget-meta{margin-top:6px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}\n.dq-budget--risk .dq-budget-meta span:last-child{color:var(--dsw-alias-state-warning-primary,#9a6700);font-weight:600}\n.dq-budget--over .dq-budget-meta{color:var(--dsw-alias-state-error-primary,#cf222e);font-weight:600}\n@media (max-width:620px){.dq-budget-head,.dq-budget-meta,.dq-budget--unset{align-items:flex-start;flex-direction:column;gap:4px}}\n.dq-delta{display:inline-flex;align-items:center;gap:3px;font-size:11px;font-weight:600;padding:1px 6px;border-radius:999px;white-space:nowrap;cursor:help;font-variant-numeric:tabular-nums}\n.dq-delta--up{color:var(--dsw-alias-state-warning-primary,#9a6700);background:rgba(191,135,0,.14)}\n.dq-delta--down{color:var(--dsw-alias-state-success-primary,#1a7f37);background:rgba(45,164,78,.14)}\n.dq-delta--flat,.dq-delta--new{color:var(--dsw-alias-label-tertiary,#59636e);background:rgba(120,130,150,.14);font-weight:500}\n.dq-delta-label{font-weight:400;opacity:.8}\n.dq-pricing{margin-top:12px;border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08));padding-top:10px}\n.dq-pricing-summary{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);cursor:pointer;list-style:none;width:fit-content;border-radius:6px;padding:2px 4px;margin-left:-4px}\n.dq-pricing-summary::-webkit-details-marker{display:none}\n.dq-pricing-summary::before{content:\"\u25B8\";display:inline-block;font-size:10px;opacity:.7;transition:transform .15s ease}\n.dq-pricing[open] .dq-pricing-summary::before{transform:rotate(90deg)}\n.dq-pricing-summary:hover{color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-pricing-summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}\n.dq-pricing-now{font-size:11px;font-weight:600;padding:1px 7px;border-radius:999px;color:var(--dsw-alias-label-tertiary,#59636e);background:rgba(120,130,150,.14)}\n.dq-pricing-now--peak{color:var(--dsw-alias-state-warning-primary,#9a6700);background:rgba(191,135,0,.14)}\n.dq-pricing-body{margin-top:10px;overflow-x:auto}\n.dq-pricing-table{border-collapse:collapse;font-size:12px;font-variant-numeric:tabular-nums;min-width:100%}\n.dq-pricing-table th{text-align:left;font-weight:500;color:var(--dsw-alias-label-tertiary,#59636e);padding:4px 12px 4px 0;white-space:nowrap;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}\n.dq-pricing-table td{padding:4px 12px 4px 0;color:var(--dsw-alias-label-primary,#1f2328);white-space:nowrap;vertical-align:top}\n.dq-pricing-table tbody tr+tr td{border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.05))}\n.dq-pricing-foot{margin:8px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-coverage{margin-top:16px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}\n.dq-coverage-summary{display:flex;align-items:center;flex-wrap:wrap;gap:6px 9px;cursor:pointer;list-style:none;width:fit-content;max-width:100%;margin-left:-4px;padding:3px 4px;border-radius:6px;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-coverage-summary::-webkit-details-marker{display:none}\n.dq-coverage-summary::before{content:\"\u25B8\";display:inline-block;font-size:10px;opacity:.7;transition:transform .15s ease}\n.dq-coverage[open] .dq-coverage-summary::before{transform:rotate(90deg)}\n.dq-coverage-summary:hover{color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-coverage-summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}\n.dq-coverage-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-coverage-status{padding:1px 7px;border-radius:999px;background:rgba(45,164,78,.14);color:var(--dsw-alias-state-success-primary,#1a7f37);font-size:11px;font-weight:600}\n.dq-coverage--warn .dq-coverage-status{background:rgba(191,135,0,.14);color:var(--dsw-alias-state-warning-primary,#9a6700)}\n.dq-coverage-brief{font-size:12px;font-variant-numeric:tabular-nums}\n.dq-coverage-body{margin-top:10px;padding:11px 12px;border-radius:10px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.06))}\n.dq-coverage-metrics{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px 20px;margin:0}\n.dq-coverage-metrics div{min-width:0}\n.dq-coverage-metrics dt{font-size:11px;color:var(--dsw-alias-label-tertiary,#59636e)}\n.dq-coverage-metrics dd{margin:3px 0 0;font-size:13px;font-weight:650;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}\n.dq-coverage-range,.dq-coverage-note,.dq-coverage-warning{margin:9px 0 0;font-size:12px;line-height:1.55;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-coverage-range{font-variant-numeric:tabular-nums}\n.dq-coverage-warning{padding:8px 10px;border-radius:8px;background:rgba(191,135,0,.10);color:var(--dsw-alias-state-warning-primary,#7a5200)}\n@media (max-width:620px){.dq-coverage-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}.dq-coverage-brief{flex-basis:100%;margin-left:19px}}\n.dq-peak-track{height:8px;border-radius:999px;background:var(--dsw-alias-state-success-primary,#2da44e);opacity:.85;overflow:hidden}\n.dq-peak-fill{height:100%;border-radius:999px;background:var(--dsw-alias-state-warning-primary,#bf8700);transition:width .35s cubic-bezier(.22,1,.36,1)}\n.dq-peak-legend{display:flex;flex-wrap:wrap;gap:6px 20px;margin-top:8px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}\n.dq-peak-legend span{display:inline-flex;align-items:center;gap:6px}\n.dq-legend-swatch--peak{background:var(--dsw-alias-state-warning-primary,#bf8700)}\n.dq-legend-swatch--offpeak{background:var(--dsw-alias-state-success-primary,#2da44e);opacity:.85}\n.dq-peak-figures{display:flex;flex-wrap:wrap;gap:12px 32px;margin-top:14px}\n.dq-peak-delta{font-size:11px;font-weight:500;margin-left:8px;color:var(--dsw-alias-state-warning-primary,#9a6700)}\n.dq-peak-delta--save{color:var(--dsw-alias-state-success-primary,#1a7f37)}\n.dq-peak-foot{margin:10px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-cache-figures{display:flex;flex-wrap:wrap;gap:12px 32px;margin-bottom:12px}\n.dq-muted-value{color:var(--dsw-alias-label-secondary,#59636e)!important;font-weight:550}\n.dq-stat-value--warn{color:var(--dsw-alias-state-warning-primary,#9a6700)}\n.dq-cache-track{height:8px;border-radius:999px;background:var(--dsw-alias-state-warning-primary,#bf8700);overflow:hidden}\n.dq-cache-fill{height:100%;border-radius:999px;background:var(--dsw-alias-state-success-primary,#2da44e);transition:width .35s cubic-bezier(.22,1,.36,1)}\n.dq-cache-legend{display:flex;flex-wrap:wrap;gap:6px 18px;margin-top:8px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}\n.dq-cache-legend span{display:inline-flex;align-items:center;gap:6px}\n.dq-legend-swatch--hit{background:var(--dsw-alias-state-success-primary,#2da44e)}\n.dq-legend-swatch--miss{background:var(--dsw-alias-state-warning-primary,#bf8700)}\n.dq-cache-foot{margin:10px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-sessions{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:14px}\n.dq-session{display:flex;flex-direction:column;gap:5px;min-width:0}\n.dq-session-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px}\n.dq-session-title{font-size:13px;font-weight:550;color:var(--dsw-alias-label-primary,#1f2328);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dq-session-cost{font-size:14px;font-weight:650;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;flex:none}\n.dq-session-track{height:6px;border-radius:999px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.12));overflow:hidden}\n.dq-session-fill{height:100%;border-radius:999px;background:var(--dsw-alias-state-business-primary,#4176e6);transition:width .35s cubic-bezier(.22,1,.36,1)}\n.dq-session-sub{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums;line-height:1.5}\n/* The \u300C\u5F53\u524D\u4F1A\u8BDD\u6D88\u8017\u300Dcard uses this class on a bare <p> (no flex-gap parent\n to lean on, unlike the .dq-session usage above), so it needs its own\n explicit spacing rather than falling back to the browser's implicit <p>\n margin \u2014 this project always declares spacing explicitly. */\np.dq-session-sub{margin:8px 0}\n.dq-session-foot{margin:12px 0 0;font-size:12px;color:var(--dsw-alias-label-tertiary,#59636e)}\n/* \u8F6E\u6B21 46: each ranking row is now a <details> whose <summary> wraps the existing\n head/track/sub trio unchanged (in a flex-column body div) plus a leading chevron \u2014\n same disclosure grammar as .dq-pricing/.dq-coverage above (hidden native marker,\n rotating glyph, :focus-visible ring), just applied to a multi-line summary instead\n of a single line. .dq-session-details needs its own min-width:0 because it is now\n the flex item inside .dq-session that the ellipsis chain must shrink through. */\n.dq-session-details{min-width:0}\n.dq-session-details>summary{list-style:none;cursor:pointer}\n.dq-session-details>summary::-webkit-details-marker{display:none}\n.dq-session-summary{display:flex;align-items:flex-start;gap:8px;border-radius:8px;padding:4px;margin:-4px}\n.dq-session-summary:hover{background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.05))}\n.dq-session-summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}\n.dq-session-chevron{flex:none;width:12px;margin-top:4px;font-size:10px;line-height:1;color:var(--dsw-alias-label-tertiary,#59636e);transition:transform .15s ease}\n.dq-session-details[open] .dq-session-chevron{transform:rotate(90deg)}\n.dq-session-summary-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}\n/* Expanded body reuses the same shaded-inset language as .dq-coverage-body (10px\n gap from the summary, 11px/12px padding, 10px radius, bg-layer-2) rather than\n inventing a new \"nested panel\" look. SessionUsageCard renders inside unchanged. */\n.dq-session-expand{margin-top:10px;padding:11px 12px;border-radius:10px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.06))}\n.dq-rank{display:flex;flex-direction:column;gap:14px}\n.dq-rank-row{display:flex;flex-direction:column;gap:5px;min-width:0}\n.dq-rank-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px}\n.dq-rank-name{display:inline-flex;align-items:center;gap:7px;font-size:13px;font-weight:550;color:var(--dsw-alias-label-primary,#1f2328);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dq-rank-cost{display:inline-flex;align-items:baseline;gap:8px;font-size:14px;font-weight:650;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;flex:none}\n.dq-rank-share{font-size:11px;font-weight:500;color:var(--dsw-alias-label-tertiary,#59636e);min-width:30px;text-align:right}\n.dq-rank-track{height:6px;border-radius:999px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.12));overflow:hidden}\n.dq-rank-fill{height:100%;border-radius:999px;transition:width .35s cubic-bezier(.22,1,.36,1)}\n.dq-rank-sub{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums;line-height:1.5}\n.dq-alert{display:flex;align-items:flex-start;gap:10px;padding:12px 14px;border-radius:10px;font-size:12px;line-height:1.6;color:var(--dsw-alias-state-warning-primary,#7a5200);background:rgba(191,135,0,.12);border:1px solid rgba(191,135,0,.35)}\n.dq-alert-icon{flex:none;width:18px;height:18px;border-radius:50%;background:var(--dsw-alias-state-warning-primary,#bf8700);color:#fff;font-weight:700;font-size:12px;line-height:18px;text-align:center}\n.dq-alert strong{font-weight:650}\n.dq-alert-link{margin-left:8px;color:inherit;text-decoration:underline;text-underline-offset:2px;white-space:nowrap}\n.dq-setting{display:flex;align-items:flex-start;gap:12px;margin-top:14px;padding-top:14px;border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}\n.dq-setting-label{font-size:13px;color:var(--dsw-alias-label-primary,#1f2328);padding-top:6px;flex:none}\n.dq-setting-control{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-width:0}\n.dq-setting-hint{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);line-height:1.5}\n.dq-number{width:82px;padding:5px 8px;font-size:13px;border-radius:8px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.16));background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}\n.dq-number:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px;border-color:transparent}\n.dq-links-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);margin:0 0 8px}\n.dq-links{display:flex;flex-wrap:wrap;gap:8px}\n.dq-link{display:inline-flex;align-items:center;gap:6px;padding:7px 12px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.12));border-radius:8px;background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-state-business-primary,#0969da);text-decoration:none;font-size:13px;font-weight:500;cursor:pointer}\n.dq-link:hover{border-color:var(--dsw-alias-state-business-primary,#0969da);background:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.04))}\n/* .dq-toggle is the first settings control after the links row (\u8F6E\u6B21 39 merge) \u2014 its own\n border-top separates the \"\u5FEB\u6377\u5165\u53E3\" links (originally the standalone \u5B98\u65B9\u5E73\u53F0 card, renamed\n in \u8F6E\u6B21 39 fix-round-1 to read as part of \u8BBE\u7F6E's own navigation area) from \u8BBE\u7F6E controls\n inside the merged card, same 14px/14px/border-l1 recipe as .dq-setting so the two\n sub-sections read at equal weight. */\n.dq-toggle{display:flex;align-items:center;gap:10px;cursor:pointer;font-size:13px;margin-top:14px;padding-top:14px;border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}\n.dq-toggle input{width:16px;height:16px;accent-color:var(--dsw-alias-state-business-primary,#0969da);cursor:pointer}\n.dq-toggle-hint{margin:5px 0 0 26px;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-widget-tabs{align-items:flex-start;flex-direction:column;gap:7px}\n.dq-widget-tab-list{display:flex;align-items:center;flex-wrap:wrap;gap:6px 14px}\n.dq-widget-tab{display:inline-flex;align-items:center;gap:7px;min-height:28px;color:var(--dsw-alias-label-primary,#1f2328);font-size:12px;cursor:pointer}\n.dq-widget-tab input{width:14px;height:14px;margin:0;accent-color:var(--dsw-alias-state-business-primary,#0969da);cursor:pointer;flex:none}\n.dq-toggle input:focus-visible,.dq-model-item input:focus-visible,.dq-widget-tab input:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}\n.dq-link:focus-visible,.dq-model-btn:focus-visible,.dq-chart-switch-btn:focus-visible,.dq-export-btn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}\n.dq-usage-totals{display:flex;flex-wrap:wrap;gap:12px 24px;margin-bottom:16px}\n/* value itself (number+unit, e.g. \"9999.9\u4E07\") must never break across lines inside its own column \u2014\n nowrap+ellipsis is a defensive floor for all widths; the actual fix for the realistic 320px 2-col\n case is the font-size drop below, which keeps every measured stress value comfortably under the\n 83px column width without ever hitting the ellipsis fallback (see round 38 PROGRESS entry) */\n.dq-usage-totals .dq-stat-value{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n@media (max-width:620px){.dq-usage-totals{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 24px}.dq-usage-totals .dq-stat{min-width:0}.dq-usage-totals .dq-stat-value{font-size:13px}}\n.dq-chart-peak{margin-left:10px;font-size:11px;font-weight:400;color:var(--dsw-alias-label-tertiary,#59636e);font-variant-numeric:tabular-nums}\n.dq-chart-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary,#59636e);margin:16px 0 8px}\n.dq-chart-title:first-of-type{margin-top:0}\n.dq-chart-block-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:16px 0 8px}\n.dq-chart-block-head .dq-chart-title{margin:0}\n.dq-chart-controls{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex:none;flex-wrap:wrap}\n@media (max-width:620px){.dq-chart-block-head{align-items:flex-start;flex-direction:column}.dq-chart-controls{width:100%}}\n.dq-model-picker{position:relative}\n.dq-model-btn{border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.12));background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#59636e);border-radius:8px;padding:4px 10px;font-size:12px;cursor:pointer;display:inline-flex;align-items:center;gap:6px}\n.dq-model-btn:hover{border-color:var(--dsw-alias-state-business-primary,#0969da);color:var(--dsw-alias-state-business-primary,#0969da)}\n.dq-model-btn::after{content:\"\u25BE\";font-size:10px;opacity:.7}\n.dq-model-menu{position:absolute;right:0;top:calc(100% + 6px);z-index:30;min-width:190px;max-height:280px;overflow-y:auto;background:var(--dsw-alias-bg-overlay,#fff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.12));border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,.16);padding:6px;display:flex;flex-direction:column;gap:2px}\n.dq-model-item{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;font-size:12px;cursor:pointer;color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-model-item:hover{background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.06))}\n.dq-model-item input{width:14px;height:14px;accent-color:var(--dsw-alias-state-business-primary,#0969da);cursor:pointer;flex:none}\n.dq-model-item span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dq-model-item--all{border-bottom:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08));padding-bottom:8px;margin-bottom:2px;border-radius:6px}\n.dq-model-tag{color:var(--dsw-alias-label-tertiary,#59636e);font-size:11px;flex:none}\n.dq-bar-group{display:flex;flex-direction:column-reverse;width:100%}\n.dq-bar-group .dq-bar{flex:0 0 auto;width:100%;border-radius:0}\n.dq-bar-group .dq-bar:first-child{border-radius:0 0 2px 2px}\n.dq-bar-group .dq-bar:last-child{border-radius:2px 2px 0 0}\n.dq-bar-group .dq-bar:not(:last-child){box-shadow:inset 0 1px 0 rgba(0,0,0,.18)}\n.dq-legend{display:flex;flex-wrap:wrap;gap:6px 14px;margin-top:8px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-legend-item{display:inline-flex;align-items:center;gap:6px}\n.dq-legend-swatch{width:10px;height:10px;border-radius:3px;flex:none}\n.dq-chart-switch{display:inline-flex;align-items:center;gap:2px;padding:2px;background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.06));border-radius:999px;flex:none}\n.dq-chart-switch-btn{border:none;background:transparent;color:var(--dsw-alias-label-secondary,#59636e);font-size:12px;line-height:1;padding:5px 12px;border-radius:999px;cursor:pointer;transition:background .15s ease,color .15s ease}\n.dq-chart-switch-btn:hover{color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-chart-switch-btn--on{background:var(--dsw-alias-bg-overlay,#fff);color:var(--dsw-alias-label-primary,#1f2328);box-shadow:0 1px 3px rgba(0,0,0,.14)}\n.dq-chart-wrap{position:relative}\n.dq-bars-scroll{overflow-x:auto;overflow-y:hidden;padding-bottom:2px}\n.dq-tip{position:absolute;transform:translate(-50%,14px);z-index:40;pointer-events:none;background:var(--dsw-alias-bg-inverse,#1f2328);color:var(--dsw-alias-label-inverse,#fff);border-radius:8px;padding:7px 10px;font-size:12px;line-height:1.55;white-space:nowrap;box-shadow:0 6px 20px rgba(0,0,0,.28);font-variant-numeric:tabular-nums}\n.dq-tip--above{transform:translate(-50%,calc(-100% - 8px))}\n.dq-tip-head{font-weight:650;margin-bottom:2px}\n.dq-tip-row{opacity:.85}\n.dq-bars{display:flex;align-items:flex-end;gap:2px;width:100%}\n.dq-bar-col{flex:1 1 0;min-width:0;display:flex;flex-direction:column;justify-content:flex-end;align-items:stretch}\n.dq-bar{background:var(--dsw-alias-state-business-primary,#4176e6);border-radius:2px 2px 0 0;min-height:1px;transition:filter .12s ease}\n.dq-bar-col{cursor:default}\n.dq-bar-col,.dq-bar,.dq-heat-cell{scroll-margin-block-start:24px;scroll-margin-block-end:160px}\n.dq-bar-col:hover .dq-bar{filter:brightness(1.18) saturate(1.1)}\n.dq-bar-col:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:-2px;border-radius:3px}\n.dq-bar:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px;filter:brightness(1.18) saturate(1.1);position:relative;z-index:2}\n.dq-bar-col--pinned{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:-2px;border-radius:3px}\n.dq-bar-col--pinned .dq-bar{filter:brightness(1.18) saturate(1.1)}\n.dq-bar--pinned{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px;filter:brightness(1.18) saturate(1.1);position:relative;z-index:2}\n.dq-heat-cell:not(.dq-heat-cell--pad):hover{outline:1.5px solid var(--dsw-alias-label-primary,#1f2328);outline-offset:1px}\n.dq-heat-cell:not(.dq-heat-cell--pad):focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px;position:relative;z-index:2}\n.dq-heat-cell--pinned{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px;position:relative;z-index:2}\n.dq-bar-label{font-size:9px;color:var(--dsw-alias-label-tertiary,#59636e);text-align:center;margin-top:3px;overflow:visible;white-space:nowrap}\n.dq-heat{display:flex;flex-direction:column;gap:8px;max-width:100%}\n.dq-heat-scroll{overflow-x:auto;padding-bottom:2px}\n.dq-heatmap{display:flex;gap:3px}\n.dq-heat-week{display:flex;flex:1 1 0;min-width:6px;flex-direction:column;gap:3px}\n.dq-heat-cell{width:100%;aspect-ratio:1/1;border-radius:3px;flex:none}\n.dq-heat-cell--pad{background:transparent}\n.dq-heat-months{display:flex;gap:3px;margin-top:4px}\n.dq-heat-month{flex:1 1 0;min-width:6px;font-size:10px;line-height:14px;color:var(--dsw-alias-label-tertiary,#59636e);white-space:nowrap;overflow:visible}\n.dq-heat-key{width:12px;height:12px;border-radius:2px;flex:none}\n.dq-heat-scale{display:flex;align-items:center;gap:3px;font-size:10px;color:var(--dsw-alias-label-tertiary,#59636e);align-self:flex-end}\n.dq-heat-scale>span:first-child{margin-right:2px}\n.dq-heat-scale>span:last-child{margin-left:2px}\n.dq-muted{color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-error{color:var(--dsw-alias-state-error-primary,#cf222e)}\n.dq-warn{color:var(--dsw-alias-state-warning-primary,#9a6700)}\n.dq-crash{margin:10px 0 14px;padding:10px 12px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.10));border-radius:8px;font-size:12px;line-height:1.5;color:var(--dsw-alias-state-error-primary,#cf222e);white-space:pre-wrap;word-break:break-word;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}\n.dq-empty{color:var(--dsw-alias-label-secondary,#59636e);font-size:12px;line-height:1.6;padding:6px 0}\n/* Error-state modifier for a card body that has nothing else to show (mirrors the .dq-stat-value--ok/\n --bad/--warn pattern: same layout as .dq-empty, declared after it so this color wins at equal\n specificity). Used by the current-session card when its own fetch failed and there is no prior\n data to fall back to \u2014 the status-row .dq-error/.dq-warn spans are for the account-wide balance/\n usage fetch, this is the per-card equivalent. */\n.dq-empty--error{color:var(--dsw-alias-state-error-primary,#cf222e)}\n.dq-skel{background:linear-gradient(90deg,rgba(125,135,155,.10) 25%,rgba(125,135,155,.20) 37%,rgba(125,135,155,.10) 63%);background-size:400% 100%;border-radius:5px;animation:dq-shimmer 1.5s ease-in-out infinite}\n.dq-stat .dq-skel+.dq-skel{margin-top:6px}\n.dq-skel-bars{display:flex;align-items:flex-end;gap:2px;width:100%;height:120px;margin-top:10px}\n.dq-skel-bar{flex:1 1 0;min-width:0;border-radius:2px 2px 0 0}\n@keyframes dq-shimmer{0%{background-position:100% 50%}100%{background-position:0 50%}}\n.dq-status-row{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:20px}\n.dq-status-messages{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-width:0}\n.dq-status-row .dq-warn,.dq-status-row .dq-error{font-size:12px;line-height:1.45}\n.dq-sync{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}\n.dq-sync-dot{width:7px;height:7px;border-radius:50%;flex:none;background:var(--dsw-alias-label-tertiary,#8c959f)}\n.dq-sync--fresh .dq-sync-dot{background:var(--dsw-alias-state-success-primary,#2da44e)}\n.dq-sync--syncing .dq-sync-dot{background:var(--dsw-alias-state-business-primary,#4176e6);animation:dq-sync-pulse 1.2s ease-in-out infinite}\n.dq-sync--fallback{color:var(--dsw-alias-state-warning-primary,#9a6700)}\n.dq-sync--fallback .dq-sync-dot{background:var(--dsw-alias-state-warning-primary,#bf8700)}\n.dq-sync--error{color:var(--dsw-alias-state-error-primary,#cf222e)}\n.dq-sync--error .dq-sync-dot{background:var(--dsw-alias-state-error-primary,#cf222e)}\n@keyframes dq-sync-pulse{50%{opacity:.35;transform:scale(.8)}}\n.dq-refresh-btn{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.12));background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#59636e);border-radius:8px;padding:5px 10px;font-size:12px;cursor:pointer;transition:border-color .15s ease,color .15s ease}\n.dq-refresh-btn:hover:not(:disabled){border-color:var(--dsw-alias-state-business-primary,#0969da);color:var(--dsw-alias-state-business-primary,#0969da)}\n.dq-refresh-btn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}\n.dq-refresh-btn:disabled{cursor:default;opacity:.6}\n.dq-refresh-icon{display:inline-block;line-height:1}\n.dq-refresh-icon--spin{animation:dq-spin .9s linear infinite}\n@keyframes dq-spin{to{transform:rotate(360deg)}}\n@media (prefers-reduced-motion:reduce){\n .dsh-quota-root,.dsh-quota-root *,\n .dsh-quota-root *::before,.dsh-quota-root *::after,\n .dq-message-cost,.dq-message-cost::after,\n .dq-balance,.dq-balance *,\n .dq-balance *::before,.dq-balance *::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}\n}\n";
@@ -0,0 +1,23 @@
1
+ /** Live projection of the host's `conversation.view` slot ledger. */
2
+ export interface ConversationViewTab {
3
+ id: string;
4
+ label: string;
5
+ }
6
+ export interface ConversationViewsSource {
7
+ list(): ConversationViewTab[];
8
+ subscribe(fn: () => void): () => void;
9
+ }
10
+ export interface ConversationViewSlotEntry {
11
+ options: {
12
+ id?: string;
13
+ label?: string | (() => string);
14
+ };
15
+ }
16
+ export interface ConversationViewSlots {
17
+ entries(name: string): ConversationViewSlotEntry[];
18
+ subscribe(name: string, fn: () => void): () => void;
19
+ }
20
+ /** Build a source once at plugin apply-time. The ledger owns ordering, so the
21
+ * same index also maps to the host's rendered tab buttons without relying on
22
+ * hashed class names or translated labels. */
23
+ export declare function conversationViewsSource(slots: ConversationViewSlots): ConversationViewsSource;
@@ -6,4 +6,13 @@
6
6
  * sidebar collapse) instead of stranding itself at stale pixel coordinates.
7
7
  */
8
8
  import { type ReactElement } from 'react';
9
- export declare function QuotaWidget(): ReactElement | null;
9
+ import type { ConversationViewsSource } from './views.ts';
10
+ interface SessionListState {
11
+ current?: string;
12
+ }
13
+ export type UseSessionsHook = <T>(selector: (state: SessionListState) => T) => T;
14
+ export declare function QuotaWidget(props: {
15
+ useSessions: UseSessionsHook;
16
+ views: ConversationViewsSource;
17
+ }): ReactElement | null;
18
+ export {};
@@ -45,6 +45,13 @@ export interface SessionEventFace {
45
45
  model?: string;
46
46
  };
47
47
  };
48
+ /** Stable turn/step identity and the finalized message id carried by
49
+ * modern `assistant/message` events. Optional for legacy logs. */
50
+ turn?: number;
51
+ step?: number;
52
+ message?: {
53
+ id?: string;
54
+ };
48
55
  /** Payload of a `session/title` event. */
49
56
  title?: string;
50
57
  };