@cassius0924/dsh-usage-dashboard 0.7.0 → 0.8.1

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.
@@ -5,16 +5,30 @@ import type { ConversationViewSlotEntry } from './views.ts';
5
5
  export interface SlotOptions {
6
6
  name: string;
7
7
  id?: string;
8
+ /** Keyed slots (the global `main` panel roster) are addressed by `key`. */
9
+ key?: string;
8
10
  order?: number;
11
+ priority?: number;
9
12
  label?: string | (() => string);
10
13
  locale?: string;
11
14
  }
12
15
  export interface SlotsFace {
13
- inject(key: string, callback: () => unknown): unknown;
14
- register(options: SlotOptions, component: unknown): unknown;
16
+ inject(key: string, callback: () => unknown): () => void;
17
+ register(options: SlotOptions, component: unknown): () => void;
15
18
  entries(name: string): ConversationViewSlotEntry[];
16
19
  subscribe(name: string, fn: () => void): () => void;
17
20
  }
21
+ /** The layout controller's main-panel navigation (global panels such as
22
+ * 「插件」/「自动化任务」 and the account-wide 额度 panel). */
23
+ export interface LayoutFace {
24
+ panelInfo: {
25
+ getSnapshot(): {
26
+ activePanelId: string | null;
27
+ };
28
+ subscribe(fn: () => void): () => void;
29
+ };
30
+ selectPanel(panelId: string | null): void;
31
+ }
18
32
  export interface LocaleFace {
19
33
  register(namespace: string, dictionaries: {
20
34
  zh: Record<string, string>;
@@ -26,4 +40,5 @@ export interface LocaleFace {
26
40
  export interface ClientContext extends Context {
27
41
  slots: SlotsFace;
28
42
  locale: LocaleFace;
43
+ layout: LayoutFace;
29
44
  }
@@ -4,7 +4,7 @@ export declare const name = "dsh-usage-dashboard";
4
4
  /** Services required before load. */
5
5
  export declare const inject: string[];
6
6
  /**
7
- * Mount the two surfaces.
7
+ * Mount the plugin surfaces.
8
8
  * @param ctx - client Cordis context.
9
9
  */
10
10
  export declare function apply(ctx: ClientContext): void;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Layout preferences shared by the dashboard's Settings section and the
3
+ * client registration half (`./index.tsx`).
4
+ *
5
+ * These two sides must agree on two placement choices, and neither may import
6
+ * the other (the registration half mounts the dashboard, so the reverse import
7
+ * would be a cycle). Keeping the stores in their own module lets both read and
8
+ * write the same persisted values.
9
+ */
10
+ import { type Store } from './store.ts';
11
+ /** The global panel id shared by the `main` slot entry and the sidebar entry
12
+ * that selects it. Stable: it is only ever compared within this package. */
13
+ export declare const QUOTA_PANEL_ID = "quota";
14
+ /** Where the optional「额度」shortcut, if enabled, lives in the sidebar. */
15
+ export type SidebarEntryPlacement = 'off' | 'top' | 'bottom';
16
+ /**
17
+ * `off` keeps the host's sidebar untouched (the default, so updating the
18
+ * plugin never silently adds chrome). `top` joins the global-panel icon row;
19
+ * `bottom` sits beside Settings in the sidebar foot.
20
+ */
21
+ export declare const sidebarEntryStore: Store<SidebarEntryPlacement>;
22
+ /**
23
+ * Position of the「额度」tab among the registered conversation views, as an
24
+ * index in the live tab roster (0 = first). The registration half maps it onto
25
+ * a slot `order` relative to the neighbouring entries, so it survives host
26
+ * plugins arriving with their own orders. Default 2 reproduces the historical
27
+ * fixed position: 对话, 轨迹, 额度.
28
+ */
29
+ export declare const quotaTabIndexStore: Store<number>;
30
+ /** One `conversation.view` slot entry, as far as ordering needs to see it. */
31
+ export interface ViewOrderEntry {
32
+ options: {
33
+ id?: string;
34
+ order?: number;
35
+ };
36
+ }
37
+ /**
38
+ * Clamp a persisted roster index into `[0, count]`; `count` itself is the
39
+ * legal "end of the list" insertion position when there are `count` tabs.
40
+ */
41
+ export declare function clampTabIndex(index: number, count: number): number;
42
+ /**
43
+ * Turn a 0-based roster position into the `order` for our own view entry.
44
+ *
45
+ * The host sorts list entries by `order` (ties keep registration order), so
46
+ * the placement is expressed relative to the live neighbours rather than as an
47
+ * absolute number: the first/last positions step outside the current range,
48
+ * and an interior position lands between the two adjacent orders (including
49
+ * the degenerate equal-order case). Other entries are never touched.
50
+ * @param entries - live `conversation.view` entries.
51
+ * @param index - desired 0-based position in the roster *including* our tab.
52
+ * @param selfId - this plugin's entry id (excluded from the anchor list).
53
+ * @param fallback - order used while the host has no other view registered.
54
+ * @returns the slot `order` for our registration.
55
+ */
56
+ export declare function viewOrderForIndex(entries: readonly ViewOrderEntry[], index: number, selfId?: string, fallback?: number): number;
@@ -26,7 +26,7 @@ export declare const zh: {
26
26
  readonly 'delta.noBaseline': "无对比";
27
27
  readonly 'delta.flat': "持平";
28
28
  readonly 'period.volume': "{tokens} tokens · {calls}";
29
- readonly 'budget.unset': "还没设置月度预算,无法提前判断是否会超支。";
29
+ readonly 'budget.unset': "未设置月度预算。";
30
30
  readonly 'budget.configure': "设置预算";
31
31
  readonly 'budget.over': "已超预算 ¥{amount}";
32
32
  readonly 'budget.forecastOver': "照当前速度,预计超出 ¥{amount}";
@@ -49,7 +49,6 @@ export declare const zh: {
49
49
  readonly 'pricing.unit': "单位:{currency} / 百万 tokens。";
50
50
  readonly 'pricing.splitNote': "高峰时段为北京时间 {windows}(周一至周五),其余为闲时(价格减半);每条用量按发生时刻生效的官方价格估算。";
51
51
  readonly 'pricing.visionNote': "图片按尺寸折算 token,与文本一并计费。";
52
- readonly 'pricing.modelNote': "deepseek-v4-flash、deepseek-v4-flash-vision-exp 是旧模型名,现由 deepseek-flash 承接并按 Flash 价计费;2026-09-14 12:00 起 deepseek-v4-pro 的请求也会路由到 V4.1-Flash,按 Flash 价计费。";
53
52
  readonly 'pricing.unknown': "未知模型按 deepseek-v4-pro 计价。";
54
53
  readonly 'coverage.noRange': "暂无有效用量时间";
55
54
  readonly 'coverage.title': "统计范围";
@@ -70,23 +69,19 @@ export declare const zh: {
70
69
  readonly 'export.modelCsv': "逐模型 CSV";
71
70
  readonly 'export.fullJson': "完整 JSON";
72
71
  readonly 'export.jsonHint': "含图表与排行";
73
- readonly 'cache.empty': "还没有 prompt token 可统计缓存命中。";
72
+ readonly 'cache.empty': "暂无缓存命中数据。";
74
73
  readonly 'cache.rate': "缓存命中率";
75
74
  readonly 'cache.saved': "已节省费用(估算)";
76
75
  readonly 'cache.allMiss': "若全部未命中";
77
76
  readonly 'cache.aria': "缓存命中 {hit}%,未命中 {miss}%";
78
77
  readonly 'cache.hitLegend': "缓存命中 {tokens}";
79
78
  readonly 'cache.missLegend': "未命中 {tokens}(按未命中价计费)";
80
- readonly 'cache.lowHint': "命中率偏低:频繁改动 system prompt / 工具定义会让前缀缓存失效,把稳定内容放在对话最前面能提高命中率。";
81
- readonly 'cache.goodHint': "前缀缓存把重复的 prompt 前缀按命中价计费,是这份账单上最大的省钱杠杆。";
82
- readonly 'peak.empty': "还没有可按时段归类的用量。";
79
+ readonly 'peak.empty': "暂无用量。";
83
80
  readonly 'peak.aria': "高峰时段 {peak}%,闲时 {offPeak}%";
84
81
  readonly 'peak.peakLegend': "高峰 {share}% · {tokens} tokens · {calls}";
85
82
  readonly 'peak.offPeakLegend': "闲时 {share}% · {tokens} tokens · {calls}";
86
83
  readonly 'peak.shift': "若高峰用量都挪到闲时";
87
84
  readonly 'peak.saving': "可省 ¥{amount}";
88
- readonly 'peak.schedule': "高峰时段为北京时间 {windows}(周一至周五),闲时价格减半。";
89
- readonly 'peak.activeHint': "把批量、可延后的任务放到闲时跑,同样的 token 只要一半的钱。";
90
85
  readonly 'vision.empty': "{window}没有图片输入。";
91
86
  readonly 'vision.title': "图片 / 多模态用量";
92
87
  readonly 'vision.images': "图片张数";
@@ -94,7 +89,7 @@ export declare const zh: {
94
89
  readonly 'vision.cost': "估算费用";
95
90
  readonly 'vision.tokensShare': "占输入 {percent}%";
96
91
  readonly 'vision.costShare': "占费用 {percent}%";
97
- readonly 'vision.note': "图片按官方换算规则估算:先按比例缩放(上限 ~800×800、下限 384×384),token 与缩放后面积成正比、每张上限 384;图片归属到随后一次模型调用,按该调用的时段与模型单价估算,实际以接口返回的用量为准。";
92
+ readonly 'vision.note': "按官方规则估算,实际以接口返回的用量为准。";
98
93
  readonly 'vision.sessionsTitle': "图片最多的会话";
99
94
  readonly 'vision.sessionRow': "{images} 张 · ¥{cost}";
100
95
  readonly 'vision.dailyTitle': "{window} · 每天图片数";
@@ -103,7 +98,7 @@ export declare const zh: {
103
98
  readonly 'sessions.empty': "还没有产生费用的会话。";
104
99
  readonly 'sessions.detail': "{tokens} tokens · {calls} · {ago}";
105
100
  readonly 'sessions.share': "占 {percent}%";
106
- readonly 'sessions.more': "共 {count} 个会话有用量,上面是最贵的 {shown} 个。";
101
+ readonly 'sessions.more': "共 {count} 个会话,显示最贵的 {shown} 个。";
107
102
  readonly 'sessions.fallbackTitle': "会话 {id}";
108
103
  readonly 'models.empty': "还没有可归类的模型用量。";
109
104
  readonly 'models.shareAria': "{name} 占总费用 {percent}%";
@@ -130,9 +125,9 @@ export declare const zh: {
130
125
  readonly 'chart.dimensionLabel': "切换图表维度";
131
126
  readonly 'chart.daily': "逐天";
132
127
  readonly 'chart.hourly': "逐小时";
133
- readonly 'chart.noWindowData': "{window}没有用量记录,换个更长周期看看。";
128
+ readonly 'chart.noWindowData': "{window}没有用量记录。";
134
129
  readonly 'chart.heatmapTitle': "近一年 · 每日";
135
- readonly 'chart.empty': "还没有用量记录。在 DSH 里跑一轮对话,这里会出现逐天 / 逐小时统计与费用估算。";
130
+ readonly 'chart.empty': "还没有用量记录。";
136
131
  readonly 'chart.hourPoint': "{hour} 点";
137
132
  readonly 'chart.tooltip': "{head} · {tokens} tokens · ¥{cost} · {calls}";
138
133
  readonly 'chart.less': "少";
@@ -198,7 +193,7 @@ export declare const zh: {
198
193
  readonly 'balance.overYear': "> 365 天";
199
194
  readonly 'balance.noRunway': "近 {days} 天没有用量,无法估算";
200
195
  readonly 'balance.runwayTitle': "按近 {days} 天日均 ¥{cost} 估算(含无用量的日子;今天尚未过完)";
201
- readonly 'balance.empty': "读不到余额。请确认账号已登录,或在「设置 → 模型」中填写 DEEPSEEK_API_KEY,然后点右上角刷新。";
196
+ readonly 'balance.empty': "读不到余额,请检查账号登录或 API Key 后刷新。";
202
197
  readonly 'sessionUsage.title': "当前会话消耗";
203
198
  readonly 'common.estimated': "费用为估算";
204
199
  readonly 'sessionUsage.cost': "费用";
@@ -206,7 +201,7 @@ export declare const zh: {
206
201
  readonly 'sessionUsage.calls': "调用次数";
207
202
  readonly 'sessionUsage.range': "活跃时间 {range}";
208
203
  readonly 'sessionUsage.single': "{model} · 输入 {input} / 输出 {output} / 缓存 {cache}";
209
- readonly 'sessionUsage.empty': "这个会话还没有产生用量。发一条消息后,这里会显示这个会话专属的费用与模型明细。";
204
+ readonly 'sessionUsage.empty': "这个会话还没有用量。";
210
205
  readonly 'overview.title': "消耗概览";
211
206
  readonly 'overview.today': "今日";
212
207
  readonly 'overview.month': "本月";
@@ -228,9 +223,9 @@ export declare const zh: {
228
223
  readonly 'links.status': "服务状态";
229
224
  readonly 'settings.title': "设置";
230
225
  readonly 'settings.widget': "在其他页面显示右下角悬浮额度窗口";
231
- readonly 'settings.widgetHint': "额度页会自动隐藏浮窗;其他页面是否展示由下方选择决定。";
226
+ readonly 'settings.widgetHint': "额度页自动隐藏;其他页面按下方选择显示。";
232
227
  readonly 'settings.widgetTabs': "展示浮窗的页面";
233
- readonly 'settings.widgetTabsHint': "页面列表来自 DSH 的实时 Tab 注册表;其他插件新增的 Tab 也会自动出现在这里。";
228
+ readonly 'settings.widgetTabsHint': "列表会随已安装的页面自动更新。";
234
229
  readonly 'settings.widgetTabsEmpty': "当前没有可配置的会话页面。";
235
230
  readonly 'settings.lowBalance': "余额预警线";
236
231
  readonly 'settings.lowBalanceOn': "余额低于 {amount} {currency} 时,这里和悬浮窗都会转为警示色。填 0 关闭。";
@@ -238,6 +233,18 @@ export declare const zh: {
238
233
  readonly 'settings.monthlyBudget': "月度预算";
239
234
  readonly 'settings.monthlyBudgetOn': "按北京时间自然月跟踪 {amount} CNY 预算,并在消耗概览预测月底花费。填 0 关闭。";
240
235
  readonly 'settings.monthlyBudgetOff': "填一个大于 0 的金额,消耗概览会显示进度与月底预测。";
236
+ readonly 'settings.sidebarEntry': "侧边栏额度入口";
237
+ readonly 'settings.sidebarEntryHint': "在侧边栏顶部或底部放一个「额度」入口,打开账户级额度页。";
238
+ readonly 'settings.sidebarEntryOff': "关闭";
239
+ readonly 'settings.sidebarEntryTop': "顶部";
240
+ readonly 'settings.sidebarEntryBottom': "底部";
241
+ readonly 'settings.tabPosition': "「额度」标签位置";
242
+ readonly 'settings.tabPositionHint': "拖动「额度」调整标签位置。";
243
+ readonly 'settings.tabDragAria': "拖动「额度」调整标签位置";
244
+ readonly 'settings.tabMoveEarlier': "前移";
245
+ readonly 'settings.tabMoveLater': "后移";
246
+ readonly 'panel.caption': "账户级 · 跨全部会话";
247
+ readonly 'panel.openAria': "打开额度页";
241
248
  readonly 'widget.updatedNow': "刚刚更新";
242
249
  readonly 'widget.stale': "{minutes} 分钟前的数据,点 ↻ 更新";
243
250
  readonly 'widget.loading': "查询中…";
@@ -255,6 +262,9 @@ export declare const zh: {
255
262
  readonly 'widget.expandAria': "展开额度窗口";
256
263
  readonly 'widget.collapseAria': "收起额度窗口";
257
264
  readonly 'messageCost.label': "本轮费用";
265
+ readonly 'sessionCost.title': "会话费用";
266
+ readonly 'sessionCost.aria': "本会话估算费用 {amount}";
267
+ readonly 'sessionCost.active': "活跃时间";
258
268
  readonly 'messageCost.tooltip': "由 dsh-usage-dashboard 提供 · 本轮对话费用为估算值";
259
269
  readonly 'messageCost.aria': "{amount},本轮对话估算费用,由 dsh-usage-dashboard 提供";
260
270
  readonly 'boundary.title': "额度面板出错了";
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Session cost pill in the composer dock (next to the host's「会话统计」and
3
+ * 「Token 用量」pills). It shows the estimated spend of the whole conversation
4
+ * and opens a small detail dialog above the dock — the same pill/dialog skin
5
+ * the host uses for its own composer statistics, so the three read as one row.
6
+ *
7
+ * The figure comes from the plugin's own session-usage API (the same endpoint
8
+ * the 「额度」tab's current-session card and the per-turn chip use), not from
9
+ * host projections: cost has to follow this plugin's pricing table.
10
+ */
11
+ import { type ReactElement } from 'react';
12
+ /** One session cost reading plus its click-open breakdown. */
13
+ export declare function SessionCostPill({ sessionId }: {
14
+ sessionId?: string;
15
+ }): ReactElement | null;
@@ -3,6 +3,7 @@ export interface Store<T> {
3
3
  set(value: T): void;
4
4
  subscribe(fn: () => void): () => void;
5
5
  }
6
+ export declare function createStore<T>(key: string, isValid: (value: unknown) => boolean, fallback: T): Store<T>;
6
7
  /** Whether the floating balance widget is shown. */
7
8
  export declare const widgetVisibleStore: Store<boolean>;
8
9
  /** Conversation view ids on which the widget is allowed to appear. `null`
@@ -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{-webkit-text-size-adjust:100%;text-size-adjust:100%;position:absolute;right:16px;bottom:16px;z-index:2147483000;pointer-events:auto;opacity:1;visibility:visible;font-family:var(--dsw-font-family,-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Hiragino Sans GB\",\"Microsoft YaHei\",\"Helvetica Neue\",Helvetica,Arial,sans-serif);font-size:13px;line-height:1.45;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary,#1f2328);--dq-text-success:#1a7f37;--dq-text-success:color-mix(in oklab,var(--dsw-alias-state-success-primary,#2da44e) 52%,var(--dsw-alias-label-primary,#1f2328) 48%);--dq-text-warn:#9a6700;--dq-text-warn:color-mix(in oklab,var(--dsw-alias-state-warn-primary,#bf8700) 52%,var(--dsw-alias-label-primary,#1f2328) 48%);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:12px;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(--dq-text-warn)!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:13px;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:12px;color:var(--dsw-alias-label-secondary,#59636e);margin-bottom:2px}\n.dsh-quota-total{font-size:18px;font-weight:700;color:var(--dsw-alias-label-primary,#1f2328);letter-spacing:-.02em;line-height:1.2;font-variant-numeric:tabular-nums}\n.dsh-quota-currency{font-size:13px;font-weight:500;margin-left:4px;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{-webkit-text-size-adjust:100%;text-size-adjust:100%;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-tooltip-bg,#1f2328);color:var(--dsw-static-neutral-bluish-00,#fff);box-shadow:0 6px 18px rgba(0,0,0,.22);font-size:12px;font-weight:400;line-height:1.5;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/* Width parity with the host composer: the dashboard column reserves the\n same max-width as the conversation reading column (860px, \u8F6E\u6B21 42 kept it\n deliberately), but on narrower viewports the fixed 860px would overhang\n the input box \u2014 measured in dashboard.tsx as --dq-composer-w, capped at\n the reading-column width so wide viewports are unchanged. */\n.dq-balance{-webkit-text-size-adjust:100%;text-size-adjust:100%;box-sizing:border-box;width:100%;min-width:0;display:flex;flex-direction:column;gap:32px;padding:20px 24px 48px;max-width:min(860px,var(--dq-composer-w,860px));margin:0 auto;font-family:var(--dsw-font-family,-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Hiragino Sans GB\",\"Microsoft YaHei\",\"Helvetica Neue\",Helvetica,Arial,sans-serif);font-size:13px;line-height:1.5;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary,#1f2328);--dq-text-success:#1a7f37;--dq-text-success:color-mix(in oklab,var(--dsw-alias-state-success-primary,#2da44e) 52%,var(--dsw-alias-label-primary,#1f2328) 48%);--dq-text-warn:#9a6700;--dq-text-warn:color-mix(in oklab,var(--dsw-alias-state-warn-primary,#bf8700) 52%,var(--dsw-alias-label-primary,#1f2328) 48%);}\n@media (max-width:620px){.dq-balance{max-width:100%;gap:24px;padding:16px 12px calc(var(--dq-composer-h,126px) + 16px)}.dq-card,.dq-card--hero,.dq-status-row{padding:0 16px}.dq-card--primary{padding:16px}}\n/* \u8F6E\u6B21 55\uFF1A\u53EA\u6709\u4E3B\u5361\u7247\u5E26\u6846\u3002\u6B21\u7EA7\u5206\u6790\u4E0E\u8BBE\u7F6E\u662F\u65E0\u6846\u5C0F\u8282\uFF0C\u9760 32px \u6BB5\u8DDD\u548C 13px \u4E3B\u8272\u6807\u9898\u5206\u7EC4\uFF1B\n \u5DE6\u53F3 20px \u5185\u8FB9\u8DDD\u8BA9\u5B83\u4EEC\u7684\u6587\u5B57\u8FB9\u4E0E\u4E3B\u5361\u7247\u5185\u6587\u5BF9\u9F50\uFF0C\u6574\u9875\u53EA\u6709\u4E00\u6761\u6587\u5B57\u5DE6\u8FB9\u7EBF\u3002 */\n.dq-card{box-sizing:border-box;min-width:0;max-width:100%;padding:0 20px}\n.dq-card-title{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 8px;font-size:15px;font-weight:600;line-height:1.4;color:var(--dsw-alias-label-primary,#1f2328);margin:0 0 16px;letter-spacing:0;text-wrap:balance}\n.dq-card-caption{font-size:12px;font-weight:400;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:16px}\n.dq-card-head .dq-card-title{margin:0}\n.dq-card-actions{display:flex;flex-wrap:wrap;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;background:var(--dsw-alias-bg-layer-1,#ffffff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.1));border-radius:12px}\n/* \u4F59\u989D\u662F\u6574\u9875\u552F\u4E00\u7684 hero\uFF1A\u4E0D\u5957\u6846\uFF0C32px \u6570\u5B57\u72EC\u5360\u4E00\u6863\uFF0C\u8BA9\u5B83\u5728\u906E\u4F4F\u6587\u5B57\u65F6\u4ECD\u662F\u7B2C\u4E00\u773C\u3002 */\n.dq-card--hero{padding:0 20px}\n.dq-card--hero .dq-stat-label{font-size:13px;margin-bottom:2px}\n.dq-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n.dq-card--hero .dq-balance-grid{align-items:stretch;gap:12px 48px}\n.dq-card--hero .dq-stat{display:flex;flex-direction:column;justify-content:space-between}\n/* hero \u6570\u5B57\u4E0D\u753B\u70B9\u72B6\u4E0B\u5212\u7EBF\uFF0840px \u4E0B\u592A\u91CD\uFF09\uFF1B\u53EF\u70B9\u6027\u9760\u60AC\u505C\u5E95\u8272\u548C title \u63D0\u793A\u3002 */\n.dq-card--hero details>summary{text-decoration:none;margin:-2px -6px;padding:2px 6px;border-radius:8px;transition:background .15s ease}\n.dq-card--hero details>summary:hover,.dq-card--hero details[open]>summary{background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.05))}\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:12px;font-weight:400;color:var(--dsw-alias-label-secondary,#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:12px;color:var(--dsw-alias-label-secondary,#59636e);margin-bottom:4px}\n.dq-stat-value{font-size:18px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}\n.dq-stat-value--ok{color:var(--dq-text-success)}\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.6;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:32px;font-weight:700;letter-spacing:-.025em;line-height:1.1}\n.dq-hero-unit{font-size:13px;font-weight:500;letter-spacing:0;margin-left:4px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}\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;line-height:1.5;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-secondary,#59636e);font-weight:400;font-size:12px}\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-card--hero .dq-balance-grid{gap:12px 32px}\n .dq-card--primary .dq-balance-grid,.dq-session-expand .dq-balance-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px 16px}\n .dq-card--primary .dq-balance-grid .dq-stat,.dq-session-expand .dq-balance-grid .dq-stat{min-width:0}\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:16px 32px}\n.dq-period{min-width:0}\n/* \u7A84\u5C4F\uFF1A\u4E09\u4E2A\u5468\u671F\u6539\u6210\u5217\u8868\u884C\u2014\u2014\u6807\u7B7E\u4E0E\u6DA8\u8DCC\u5728\u5DE6\u3001\u91D1\u989D\u53F3\u5BF9\u9F50\u3001\u660E\u7EC6\u5360\u7B2C\u4E8C\u884C\uFF0C\u4E09\u6BB5\u53EA\u5360\u7EA6 150px\u3002 */\n@media (max-width:620px){.dq-period-grid{grid-template-columns:1fr;gap:16px}.dq-period{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:12px;align-items:center}.dq-period-head{margin:0}.dq-period-cost{grid-column:2;grid-row:1}.dq-period-sub{grid-column:1/-1;margin-top:2px}}\n.dq-period-head{display:flex;align-items:center;flex-wrap:wrap;gap:4px 8px;margin-bottom:8px}\n.dq-period-label{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-period-cost{font-size:18px;font-weight:700;letter-spacing:-.01em;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;line-height:1.2}\n.dq-period-sub{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);margin-top:4px;font-variant-numeric:tabular-nums;line-height:1.5}\n.dq-budget{margin-top:24px}\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:13px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-budget-amount{font-size:13px;font-weight:600;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(--dq-text-warn);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}.dq-budget-action{margin-left:-4px}}\n.dq-delta{display:inline-flex;align-items:center;gap:3px;font-size:12px;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(--dq-text-warn);background:rgba(191,135,0,.14)}\n.dq-delta--down{color:var(--dq-text-success);background:rgba(45,164,78,.14)}\n.dq-delta--flat,.dq-delta--new{color:var(--dsw-alias-label-secondary,#59636e);background:rgba(120,130,150,.14);font-weight:500}\n.dq-delta-label{font-weight:400;opacity:.8}\n.dq-pricing{margin-top:16px}\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:\"\";display:inline-block;flex:none;width:14px;height:14px;background:currentColor;-webkit-mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E\") center/contain no-repeat;mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E\") center/contain no-repeat;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:12px;font-weight:600;padding:1px 7px;border-radius:999px;color:var(--dsw-alias-label-secondary,#59636e);background:rgba(120,130,150,.14)}\n.dq-pricing-now--peak{color:var(--dq-text-warn);background:rgba(191,135,0,.14)}\n.dq-pricing-body{margin-top:8px;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-secondary,#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 th:nth-child(n+3),.dq-pricing-table td:nth-child(n+3){text-align:right}\n.dq-pricing-table th:last-child,.dq-pricing-table td:last-child{padding-right:0}\n.dq-pricing-table tbody td:first-child{font-weight:500}\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);text-wrap:pretty}\n.dq-coverage{margin-top:24px}\n.dq-coverage-summary{display:flex;align-items:center;flex-wrap:wrap;gap:4px 8px;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:\"\";display:inline-block;flex:none;width:14px;height:14px;background:currentColor;-webkit-mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E\") center/contain no-repeat;mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E\") center/contain no-repeat;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-secondary,#59636e)}\n.dq-coverage-status{padding:1px 7px;border-radius:999px;background:rgba(45,164,78,.14);color:var(--dq-text-success);font-size:12px;font-weight:600}\n.dq-coverage--warn .dq-coverage-status{background:rgba(191,135,0,.14);color:var(--dq-text-warn)}\n.dq-coverage-brief{font-size:12px;font-variant-numeric:tabular-nums}\n.dq-coverage-body{margin-top:8px;padding: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:12px 24px;margin:0}\n.dq-coverage-metrics div{min-width:0}\n.dq-coverage-metrics dt{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-coverage-metrics dd{margin:3px 0 0;font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}\n.dq-coverage-range,.dq-coverage-note,.dq-coverage-warning{margin:8px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e);text-wrap:pretty}\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(--dq-text-warn)}\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:4px 16px;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:16px}\n.dq-peak-delta{font-size:12px;font-weight:500;margin-left:8px;color:var(--dq-text-warn)}\n.dq-peak-delta--save{color:var(--dq-text-success)}\n.dq-peak-foot{margin:12px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e);text-wrap:pretty}\n.dq-cache-figures{display:flex;flex-wrap:wrap;gap:12px 32px;margin-bottom:12px}\n@media (max-width:620px){.dq-cache-figures{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px 16px}.dq-cache-figures .dq-stat{min-width:0}}\n.dq-muted-value{color:var(--dsw-alias-label-secondary,#59636e)!important;font-weight:500}\n.dq-stat-value--warn{color:var(--dq-text-warn)}\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:4px 16px;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:12px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e);text-wrap:pretty}\n.dq-sessions{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:16px}\n.dq-session{display:flex;flex-direction:column;gap:4px;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:500;color:var(--dsw-alias-label-primary,#1f2328);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dq-session-cost{font-size:13px;font-weight:600;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. */\n.dq-session-meta{margin:12px 0 0;display:flex;flex-direction:column;gap:2px}\n.dq-session-meta p.dq-session-sub{margin:0}\n.dq-session-meta+.dq-rank{margin-top:16px}\n.dq-session-foot{margin:12px 0 0;font-size:12px;color:var(--dsw-alias-label-secondary,#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/* \u5C55\u5F00\u7BAD\u5934\uFF1A14px \u7EBF\u6761\u56FE\u6807\uFF08mask \u53D6 currentColor\uFF09\uFF0C\u66FF\u4EE3\u539F\u6765 10px \u7684\u300C\u25B8\u300D\u5B57\u7B26\u2014\u2014\u90A3\u4E2A\u5B57\u5F62\u592A\u5C0F\u3001\u592A\u6D45\uFF0C\u70B9\u51FB\u76EE\u6807\u4E5F\u96BE\u627E\u3002 */\n.dq-session-chevron{display:inline-block;flex:none;width:14px;height:14px;background:currentColor;-webkit-mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E\") center/contain no-repeat;mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E\") center/contain no-repeat;transition:transform .15s ease;margin-top:3px;color:var(--dsw-alias-label-secondary,#59636e)}\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:4px}\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:8px;padding: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:16px}\n.dq-rank-row{display:flex;flex-direction:column;gap:4px;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:500;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:13px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;flex:none}\n.dq-rank-share{font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary,#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(--dq-text-warn);background:rgba(191,135,0,.12);border:1px solid rgba(191,135,0,.35);text-wrap:pretty}\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:600}\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:16px;margin-top:24px}\n@media (max-width:620px){.dq-setting{flex-direction:column;gap:8px}.dq-setting-label{width:auto;padding-top:0}}\n.dq-setting-label{width:128px;font-size:13px;font-weight:500;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/* Page footer: the package name + version, injected at build time from\n package.json (see build.mjs) so it can never drift from the release. */\n.dq-footer{margin:16px 0 0;font-size:12px;text-align:center;color:var(--dsw-alias-label-tertiary,#59636e)}\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:13px;font-weight:500;color:var(--dsw-alias-label-primary,#1f2328);margin:0 0 12px}\n.dq-links{display:flex;flex-wrap:wrap;gap:8px}\n.dq-link{display:inline-flex;align-items:center;gap:4px;padding:8px 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-label-primary,#1f2328);text-decoration:none;font-size:13px;font-weight:500;cursor:pointer}\n.dq-link::after{content:\"\u2197\";font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-link:hover{border-color:var(--dsw-alias-label-secondary,#59636e);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;font-weight:500;margin-top:24px}\n.dq-toggle input{width:16px;height:16px;accent-color:var(--dsw-alias-state-business-primary,#0969da);cursor:pointer}\n.dq-toggle-hint{margin:4px 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:8px}\n.dq-widget-tab-list{display:flex;align-items:center;flex-wrap:wrap;gap:4px 16px}\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;font-weight:500;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:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px 24px;margin-bottom:20px}\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.dq-vision-share{display:inline-block;margin-left:6px;font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-vision-sessions{margin-top:12px;display:flex;flex-direction:column;gap:8px;min-width:0}\n/* The vision card's session rows reuse .dq-session-head, but \u2014 unlike the\n ranking card's rows \u2014 they sit directly under .dq-session with no\n .dq-session-summary-body wrapper to carry min-width:0. Without the chain\n below, a long session title (nowrap) sets the row's min-content width and\n can stretch the card past its siblings / the container. */\n.dq-vision-sessions .dq-session{min-width:0}\n.dq-vision-sessions .dq-session-head{min-width:0}\n.dq-vision-sessions .dq-session-title{flex:1 1 auto;min-width:0}\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:8px;font-size:12px;font-weight:400;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}\n.dq-chart-title{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);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:0 0 12px}\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%;justify-content:flex-start}}\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-secondary,#59636e);font-size:12px;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:4px 16px;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-tooltip-bg,#1f2328);color:var(--dsw-static-neutral-bluish-00,#fff);border-radius:8px;padding:7px 10px;font-size:12px;line-height:1.5;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:600;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:12px;color:var(--dsw-alias-label-secondary,#59636e);text-align:center;margin-top:4px;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:12px;line-height:15px;color:var(--dsw-alias-label-secondary,#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:12px;color:var(--dsw-alias-label-secondary,#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(--dq-text-warn)}\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.6;color:var(--dsw-alias-state-error-primary,#cf222e);white-space:pre-wrap;word-break:break-word;font-family:var(--ds-font-family-code,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;text-wrap:pretty}\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:160px;margin-top:12px}\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;padding:0 20px;margin-bottom:-12px}\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.5}\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(--dq-text-warn)}\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";
2
+ export declare const css = "\n.dsh-quota-root{-webkit-text-size-adjust:100%;text-size-adjust:100%;position:absolute;right:16px;bottom:16px;z-index:2147483000;pointer-events:auto;opacity:1;visibility:visible;font-family:var(--dsw-font-family,-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Hiragino Sans GB\",\"Microsoft YaHei\",\"Helvetica Neue\",Helvetica,Arial,sans-serif);font-size:13px;line-height:1.45;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary,#1f2328);--dq-text-success:#1a7f37;--dq-text-success:color-mix(in oklab,var(--dsw-alias-state-success-primary,#2da44e) 52%,var(--dsw-alias-label-primary,#1f2328) 48%);--dq-text-warn:#9a6700;--dq-text-warn:color-mix(in oklab,var(--dsw-alias-state-warn-primary,#bf8700) 52%,var(--dsw-alias-label-primary,#1f2328) 48%);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:12px;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(--dq-text-warn)!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:13px;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:12px;color:var(--dsw-alias-label-secondary,#59636e);margin-bottom:2px}\n.dsh-quota-total{font-size:18px;font-weight:700;color:var(--dsw-alias-label-primary,#1f2328);letter-spacing:-.02em;line-height:1.2;font-variant-numeric:tabular-nums}\n.dsh-quota-currency{font-size:13px;font-weight:500;margin-left:4px;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{-webkit-text-size-adjust:100%;text-size-adjust:100%;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;bottom:calc(100% + 6px);top:auto;z-index:2147483001;width:max-content;max-width:min(240px,calc(100vw - 24px));padding:6px 9px;border-radius:8px;background:var(--dsw-alias-tooltip-bg,#1f2328);color:var(--dsw-static-neutral-bluish-00,#fff);box-shadow:0 6px 18px rgba(0,0,0,.22);font-size:12px;font-weight:400;line-height:1.5;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/* Composer-dock session cost pill: one more reading beside the host's own\n \u300C\u4F1A\u8BDD\u7EDF\u8BA1\u300D/\u300CToken \u7528\u91CF\u300Dpills (same slot, same compact skin). */\n.dq-cost-anchor{display:inline-flex;min-width:0;font-size:calc(var(--dsh-content-font-size-secondary,13px) - 1px);line-height:calc(20px + var(--dsh-content-font-delta-secondary,0px))}\n.dq-cost-pill{display:inline-flex;align-items:center;gap:6px;box-sizing:border-box;max-width:100%;padding:1px 8px;border:0;border-radius:var(--dsw-radius-sm,8px);background:transparent;color:var(--dsw-alias-label-tertiary,#59636e);font:inherit;font-variant-numeric:tabular-nums;line-height:inherit;white-space:nowrap;cursor:pointer}\n.dq-cost-pill:hover,.dq-cost-pill[aria-expanded=\"true\"]{background:var(--dsw-alias-interactive-bg-hover,rgba(120,130,150,.12));color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-cost-pill:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}\n.dq-cost-pill svg{flex:none}\n.dq-cost-pill-label{min-width:0;overflow:hidden;text-overflow:ellipsis}\n/* Click-open breakdown: the host stat-dialog skin (menu surface, prominent\n elevation, 12/18 rows), portaled to the body and placed above the pill. */\n.dq-cost-panel{position:fixed;z-index:1100;box-sizing:border-box;width:max-content;min-width:min(300px,calc(100vw - 24px));max-width:min(440px,calc(100vw - 24px));padding:16px;border:0;border-radius:var(--dsw-radius-lg,16px);background:var(--dsw-specific-menu,var(--dsw-alias-bg-overlay,#fff));-webkit-backdrop-filter:var(--dsw-menu-backdrop-filter,blur(40px) saturate(150%));backdrop-filter:var(--dsw-menu-backdrop-filter,blur(40px) saturate(150%));box-shadow:var(--dsw-elevation-prominent,0 12px 32px rgba(0,0,0,.24));font-family:var(--dsw-font-family,-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Hiragino Sans GB\",\"Microsoft YaHei\",\"Helvetica Neue\",Helvetica,Arial,sans-serif);font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary,#59636e);cursor:default}\n.dq-cost-panel-title{display:flex;justify-content:space-between;gap:16px;margin-bottom:8px;color:var(--dsw-alias-label-primary,#1f2328);font-weight:500}\n.dq-cost-panel-title-label{display:inline-flex;align-items:center;gap:6px;min-width:0}\n.dq-cost-panel-title-label svg{flex:none}\n.dq-cost-panel-value{font-variant-numeric:tabular-nums}\n.dq-cost-panel-rule{margin-bottom:10px;border-top:.5px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1))}\n.dq-cost-details{display:grid;grid-template-columns:minmax(76px,auto) minmax(0,1fr);gap:6px 16px;margin:0;color:var(--dsw-alias-label-tertiary,#59636e)}\n.dq-cost-details dt,.dq-cost-details dd{min-width:0;margin:0}\n.dq-cost-details dd{color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums;text-align:right}\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/* Width parity with the host composer: the dashboard column reserves the\n same max-width as the conversation reading column (860px, \u8F6E\u6B21 42 kept it\n deliberately), but on narrower viewports the fixed 860px would overhang\n the input box \u2014 measured in dashboard.tsx as --dq-composer-w, capped at\n the reading-column width so wide viewports are unchanged. */\n.dq-balance{-webkit-text-size-adjust:100%;text-size-adjust:100%;box-sizing:border-box;width:100%;min-width:0;display:flex;flex-direction:column;gap:32px;padding:20px 24px 48px;max-width:min(860px,var(--dq-composer-w,860px));margin:0 auto;font-family:var(--dsw-font-family,-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Hiragino Sans GB\",\"Microsoft YaHei\",\"Helvetica Neue\",Helvetica,Arial,sans-serif);font-size:13px;line-height:1.5;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary,#1f2328);--dq-text-success:#1a7f37;--dq-text-success:color-mix(in oklab,var(--dsw-alias-state-success-primary,#2da44e) 52%,var(--dsw-alias-label-primary,#1f2328) 48%);--dq-text-warn:#9a6700;--dq-text-warn:color-mix(in oklab,var(--dsw-alias-state-warn-primary,#bf8700) 52%,var(--dsw-alias-label-primary,#1f2328) 48%);}\n@media (max-width:620px){.dq-balance{max-width:100%;gap:24px;padding:16px 12px calc(var(--dq-composer-h,126px) + 16px)}.dq-card{padding:16px}.dq-card--hero{padding:0 16px}.dq-status-row{padding:0 16px}}\n/* \u8F6E\u6B21 55\uFF1A\u53EA\u6709\u4E3B\u5361\u7247\u5E26\u6846\u3002\u6B21\u7EA7\u5206\u6790\u4E0E\u8BBE\u7F6E\u662F\u65E0\u6846\u5C0F\u8282\uFF0C\u9760 32px \u6BB5\u8DDD\u548C 13px \u4E3B\u8272\u6807\u9898\u5206\u7EC4\uFF1B\n \u5DE6\u53F3 20px \u5185\u8FB9\u8DDD\u8BA9\u5B83\u4EEC\u7684\u6587\u5B57\u8FB9\u4E0E\u4E3B\u5361\u7247\u5185\u6587\u5BF9\u9F50\uFF0C\u6574\u9875\u53EA\u6709\u4E00\u6761\u6587\u5B57\u5DE6\u8FB9\u7EBF\u3002 */\n.dq-card{box-sizing:border-box;min-width:0;max-width:100%;padding:20px;background:var(--dsw-alias-bg-layer-1,#ffffff);border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.10));border-radius:12px}\n.dq-card-title{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 8px;font-size:15px;font-weight:600;line-height:1.4;color:var(--dsw-alias-label-primary,#1f2328);margin:0 0 16px;letter-spacing:0;text-wrap:balance}\n.dq-card-caption{font-size:12px;font-weight:400;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:16px}\n.dq-card-head .dq-card-title{margin:0}\n.dq-card-actions{display:flex;flex-wrap:wrap;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-l3,rgba(0,0,0,.12))}\n/* \u4F59\u989D\u662F\u6574\u9875\u552F\u4E00\u7684 hero\uFF1A\u4E0D\u5957\u6846\uFF0C32px \u6570\u5B57\u72EC\u5360\u4E00\u6863\uFF0C\u8BA9\u5B83\u5728\u906E\u4F4F\u6587\u5B57\u65F6\u4ECD\u662F\u7B2C\u4E00\u773C\u3002 */\n.dq-card--hero{padding:0 20px;background:transparent;border:0;border-radius:0}\n.dq-card-pair{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(340px,100%),1fr));gap:24px;min-width:0}\n.dq-card--hero .dq-stat-label{font-size:13px;margin-bottom:2px}\n.dq-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n.dq-card--hero .dq-balance-grid{align-items:stretch;gap:12px 48px}\n.dq-card--hero .dq-stat{display:flex;flex-direction:column;justify-content:space-between}\n/* hero \u6570\u5B57\u4E0D\u753B\u70B9\u72B6\u4E0B\u5212\u7EBF\uFF0840px \u4E0B\u592A\u91CD\uFF09\uFF1B\u53EF\u70B9\u6027\u9760\u60AC\u505C\u5E95\u8272\u548C title \u63D0\u793A\u3002 */\n.dq-card--hero details>summary{text-decoration:none;margin:-2px -6px;padding:2px 6px;border-radius:8px;transition:background .15s ease}\n.dq-card--hero details>summary:hover,.dq-card--hero details[open]>summary{background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.05))}\n@media (max-width:620px){.dq-card{padding:16px}.dq-card--hero{padding:0 16px}}\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:12px;font-weight:400;color:var(--dsw-alias-label-secondary,#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:12px;color:var(--dsw-alias-label-secondary,#59636e);margin-bottom:4px}\n.dq-stat-value{font-size:18px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}\n.dq-stat-value--ok{color:var(--dq-text-success)}\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.6;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:32px;font-weight:700;letter-spacing:-.025em;line-height:1.1}\n.dq-hero-unit{font-size:13px;font-weight:500;letter-spacing:0;margin-left:4px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}\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;line-height:1.5;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-secondary,#59636e);font-weight:400;font-size:12px}\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-card--hero .dq-balance-grid{gap:12px 32px}\n .dq-card--primary .dq-balance-grid,.dq-session-expand .dq-balance-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px 16px}\n .dq-card--primary .dq-balance-grid .dq-stat,.dq-session-expand .dq-balance-grid .dq-stat{min-width:0}\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:16px 32px}\n.dq-period{min-width:0}\n/* \u7A84\u5C4F\uFF1A\u4E09\u4E2A\u5468\u671F\u6539\u6210\u5217\u8868\u884C\u2014\u2014\u6807\u7B7E\u4E0E\u6DA8\u8DCC\u5728\u5DE6\u3001\u91D1\u989D\u53F3\u5BF9\u9F50\u3001\u660E\u7EC6\u5360\u7B2C\u4E8C\u884C\uFF0C\u4E09\u6BB5\u53EA\u5360\u7EA6 150px\u3002 */\n@media (max-width:620px){.dq-period-grid{grid-template-columns:1fr;gap:16px}.dq-period{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:12px;align-items:center}.dq-period-head{margin:0}.dq-period-cost{grid-column:2;grid-row:1}.dq-period-sub{grid-column:1/-1;margin-top:2px}}\n.dq-period-head{display:flex;align-items:center;flex-wrap:wrap;gap:4px 8px;margin-bottom:8px}\n.dq-period-label{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-period-cost{font-size:18px;font-weight:700;letter-spacing:-.01em;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;line-height:1.2}\n.dq-period-sub{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);margin-top:4px;font-variant-numeric:tabular-nums;line-height:1.5}\n.dq-budget{margin-top:24px}\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:13px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-budget-amount{font-size:13px;font-weight:600;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(--dq-text-warn);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}.dq-budget-action{margin-left:-4px}}\n.dq-delta{display:inline-flex;align-items:center;gap:3px;font-size:12px;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(--dq-text-warn);background:rgba(191,135,0,.14)}\n.dq-delta--down{color:var(--dq-text-success);background:rgba(45,164,78,.14)}\n.dq-delta--flat,.dq-delta--new{color:var(--dsw-alias-label-secondary,#59636e);background:rgba(120,130,150,.14);font-weight:500}\n.dq-delta-label{font-weight:400;opacity:.8}\n.dq-pricing{margin-top:16px}\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:\"\";display:inline-block;flex:none;width:14px;height:14px;background:currentColor;-webkit-mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E\") center/contain no-repeat;mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E\") center/contain no-repeat;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:12px;font-weight:600;padding:1px 7px;border-radius:999px;color:var(--dsw-alias-label-secondary,#59636e);background:rgba(120,130,150,.14)}\n.dq-pricing-now--peak{color:var(--dq-text-warn);background:rgba(191,135,0,.14)}\n.dq-pricing-body{margin-top:8px;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-secondary,#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 th:nth-child(n+3),.dq-pricing-table td:nth-child(n+3){text-align:right}\n.dq-pricing-table th:last-child,.dq-pricing-table td:last-child{padding-right:0}\n.dq-pricing-table tbody td:first-child{font-weight:500}\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);text-wrap:pretty}\n.dq-coverage{margin-top:24px}\n.dq-coverage-summary{display:flex;align-items:center;flex-wrap:wrap;gap:4px 8px;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:\"\";display:inline-block;flex:none;width:14px;height:14px;background:currentColor;-webkit-mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E\") center/contain no-repeat;mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E\") center/contain no-repeat;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-secondary,#59636e)}\n.dq-coverage-status{padding:1px 7px;border-radius:999px;background:rgba(45,164,78,.14);color:var(--dq-text-success);font-size:12px;font-weight:600}\n.dq-coverage--warn .dq-coverage-status{background:rgba(191,135,0,.14);color:var(--dq-text-warn)}\n.dq-coverage-brief{font-size:12px;font-variant-numeric:tabular-nums}\n.dq-coverage-body{margin-top:8px;padding: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:12px 24px;margin:0}\n.dq-coverage-metrics div{min-width:0}\n.dq-coverage-metrics dt{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-coverage-metrics dd{margin:3px 0 0;font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}\n.dq-coverage-range,.dq-coverage-note,.dq-coverage-warning{margin:8px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e);text-wrap:pretty}\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(--dq-text-warn)}\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:4px 16px;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:16px}\n.dq-peak-delta{font-size:12px;font-weight:500;margin-left:8px;color:var(--dq-text-warn)}\n.dq-peak-delta--save{color:var(--dq-text-success)}\n.dq-cache-figures{display:flex;flex-wrap:wrap;gap:12px 32px;margin-bottom:12px}\n@media (max-width:620px){.dq-cache-figures{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px 16px}.dq-cache-figures .dq-stat{min-width:0}}\n.dq-muted-value{color:var(--dsw-alias-label-secondary,#59636e)!important;font-weight:500}\n.dq-stat-value--warn{color:var(--dq-text-warn)}\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:4px 16px;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:12px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e);text-wrap:pretty}\n.dq-sessions{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:16px}\n.dq-session{display:flex;flex-direction:column;gap:4px;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:500;color:var(--dsw-alias-label-primary,#1f2328);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dq-session-cost{font-size:13px;font-weight:600;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. */\n.dq-session-meta{margin:12px 0 0;display:flex;flex-direction:column;gap:2px}\n.dq-session-meta p.dq-session-sub{margin:0}\n.dq-session-meta+.dq-rank{margin-top:16px}\n.dq-session-foot{margin:12px 0 0;font-size:12px;color:var(--dsw-alias-label-secondary,#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/* \u5C55\u5F00\u7BAD\u5934\uFF1A14px \u7EBF\u6761\u56FE\u6807\uFF08mask \u53D6 currentColor\uFF09\uFF0C\u66FF\u4EE3\u539F\u6765 10px \u7684\u300C\u25B8\u300D\u5B57\u7B26\u2014\u2014\u90A3\u4E2A\u5B57\u5F62\u592A\u5C0F\u3001\u592A\u6D45\uFF0C\u70B9\u51FB\u76EE\u6807\u4E5F\u96BE\u627E\u3002 */\n.dq-session-chevron{display:inline-block;flex:none;width:14px;height:14px;background:currentColor;-webkit-mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E\") center/contain no-repeat;mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E\") center/contain no-repeat;transition:transform .15s ease;margin-top:3px;color:var(--dsw-alias-label-secondary,#59636e)}\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:4px}\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:8px;padding: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:16px}\n.dq-rank-row{display:flex;flex-direction:column;gap:4px;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:500;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:13px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;flex:none}\n.dq-rank-share{font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary,#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(--dq-text-warn);background:rgba(191,135,0,.12);border:1px solid rgba(191,135,0,.35);text-wrap:pretty}\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:600}\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:16px;margin-top:24px}\n@media (max-width:620px){.dq-setting{flex-direction:column;gap:8px}.dq-setting-label{width:auto;padding-top:0}}\n.dq-setting-label{width:128px;font-size:13px;font-weight:500;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/* Page footer: the package name + version, injected at build time from\n package.json (see build.mjs) so it can never drift from the release. */\n.dq-footer{margin:16px 0 0;font-size:12px;text-align:center;color:var(--dsw-alias-label-tertiary,#59636e)}\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:13px;font-weight:500;color:var(--dsw-alias-label-primary,#1f2328);margin:0 0 12px}\n.dq-links{display:flex;flex-wrap:wrap;gap:8px}\n.dq-link{display:inline-flex;align-items:center;gap:4px;padding:8px 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-label-primary,#1f2328);text-decoration:none;font-size:13px;font-weight:500;cursor:pointer}\n.dq-link::after{content:\"\u2197\";font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-link:hover{border-color:var(--dsw-alias-label-secondary,#59636e);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;font-weight:500;margin-top:24px}\n.dq-toggle input{width:16px;height:16px;accent-color:var(--dsw-alias-state-business-primary,#0969da);cursor:pointer}\n.dq-toggle-hint{margin:4px 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:8px}\n.dq-widget-tab-list{display:flex;align-items:center;flex-wrap:wrap;gap:4px 16px}\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;font-weight:500;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:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px 24px;margin-bottom:20px}\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.dq-vision-share{display:inline-block;margin-left:6px;font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-vision-sessions{margin-top:12px;display:flex;flex-direction:column;gap:8px;min-width:0}\n/* The vision card's session rows reuse .dq-session-head, but \u2014 unlike the\n ranking card's rows \u2014 they sit directly under .dq-session with no\n .dq-session-summary-body wrapper to carry min-width:0. Without the chain\n below, a long session title (nowrap) sets the row's min-content width and\n can stretch the card past its siblings / the container. */\n.dq-vision-sessions .dq-session{min-width:0}\n.dq-vision-sessions .dq-session-head{min-width:0}\n.dq-vision-sessions .dq-session-title{flex:1 1 auto;min-width:0}\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:8px;font-size:12px;font-weight:400;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}\n.dq-chart-title{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);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:0 0 12px}\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%;justify-content:flex-start}}\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-secondary,#59636e);font-size:12px;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:4px 16px;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-tooltip-bg,#1f2328);color:var(--dsw-static-neutral-bluish-00,#fff);border-radius:8px;padding:7px 10px;font-size:12px;line-height:1.5;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:600;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:12px;color:var(--dsw-alias-label-secondary,#59636e);text-align:center;margin-top:4px;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:12px;line-height:15px;color:var(--dsw-alias-label-secondary,#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:12px;color:var(--dsw-alias-label-secondary,#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(--dq-text-warn)}\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.6;color:var(--dsw-alias-state-error-primary,#cf222e);white-space:pre-wrap;word-break:break-word;font-family:var(--ds-font-family-code,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;text-wrap:pretty}\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:160px;margin-top:12px}\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;padding:0 20px;margin-bottom:-12px}\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.5}\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(--dq-text-warn)}\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/* ============================================================================\n Host chrome: the \u300C\u989D\u5EA6\u300Dconversation view does not use the chat composer.\n The attribute is set by index.tsx only when the dashboard is mounted inside\n the conversation scrollport, so the account-wide panel never hides it.\n '!important' because the composer's slot anchor is a \"display:contents\"\n wrapper whose display we must beat regardless of host rule order.\n ============================================================================ */\nhtml[data-dq-quota-view] [data-slot=\"conversation.composer\"]{display:none!important}\n/* The narrow-viewport rule pads for the fixed composer; with it hidden there\n is nothing to clear, so fall back to the page's own bottom breathing room. */\nhtml[data-dq-quota-view] .dq-balance{padding-bottom:48px}\n/* ============================================================================\n Account-wide \u300C\u989D\u5EA6\u300Dpanel (the optional sidebar entry opens this main\n keyed panel). The dashboard keeps its own width/padding; the panel only\n supplies the page title row and the scrolling box the main column lacks.\n ============================================================================ */\n/* Account-wide page frame: mirrors DSH's first-level pages (Plugins /\n Scheduled tasks) \u2014 full-height scroll box, 28px top inset on the heading,\n a 960px centred column, clamp(24px,4vw,48px) inline + 48px bottom insets and\n a 20px/28px/500 page title, so the three sibling entries line up. */\n.dq-panel{box-sizing:border-box;height:100%;min-height:0;overflow-y:auto;overflow-x:hidden;padding:0 clamp(24px,4vw,48px) 48px;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary,#1f2328);font-family:var(--dsw-font-family,-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Hiragino Sans GB\",\"Microsoft YaHei\",\"Helvetica Neue\",Helvetica,Arial,sans-serif);font-size:13px;line-height:1.5}\n.dq-panel-head{box-sizing:border-box;display:flex;flex-direction:column;align-items:flex-start;gap:4px;width:100%;max-width:960px;margin:0 auto 32px;padding-top:28px}\n.dq-panel-title{margin:0;font-size:20px;font-weight:500;line-height:28px;color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-panel-caption{font-size:13px;line-height:20px;color:var(--dsw-alias-label-secondary,#59636e)}\n.dq-panel .dq-balance{box-sizing:border-box;width:100%;max-width:960px;padding:0}\n/* macOS hiddenInset titlebar: the frame's top clearance keeps the heading\n below the window's top strip, matching the host's sibling pages. */\n[data-platform=\"darwin\"] .dq-panel-head{padding-top:calc(28px + var(--dsh-frame-top-clearance,0px))}\n@media (max-width:620px){\n .dq-panel-head{padding-top:24px;margin-bottom:24px}\n .dq-panel .dq-balance{max-width:100%;padding:0}\n}\n/* Optional sidebar entry. Top placement joins the host's global-panel icon\n row (only the glyph is ours); bottom placement renders a row beside\n Settings, collapsing to a square rail button with the sidebar. */\n/* The glyph is an SVG matching the host's 16px stroke icons; color inherits\n from the sidebar row so selected/hover states stay the host's business. */\n.dq-side-icon{flex:none;display:block}\n.dq-side-entry{display:flex;align-items:center;gap:8px;box-sizing:border-box;width:100%;border:0;border-radius:8px;padding:7px 8px;background:transparent;color:var(--dsw-alias-label-secondary,#59636e);font:inherit;font-size:13px;line-height:1.3;text-align:left;cursor:pointer}\n.dq-side-entry:hover{background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.10));color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-side-entry:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px}\n.dq-side-entry[aria-pressed=\"true\"]{color:var(--dsw-alias-label-primary,#1f2328)}\n.dq-side-entry--rail{justify-content:center;width:32px;height:32px;margin:0 auto;padding:0}\n.dq-side-entry-icon{flex:none;display:inline-flex;align-items:center;justify-content:center}\n.dq-side-entry-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n/* ============================================================================\n Settings controls for the two layout preferences: a compact select and the\n draggable tab-order strip.\n ============================================================================ */\n.dq-select{font:inherit;font-size:13px;line-height:1.3;color:var(--dsw-alias-label-primary,#1f2328);background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.16));border-radius:8px;padding:5px 8px;min-width:96px;cursor:pointer}\n.dq-select:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px}\n.dq-tab-order{display:flex;flex-wrap:wrap;align-items:center;gap:6px;box-sizing:border-box;max-width:100%;min-height:32px;padding:4px;border:1px dashed var(--dsw-alias-border-l2,rgba(0,0,0,.16));border-radius:8px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.06))}\n.dq-tab-chip{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08));border-radius:999px;background:var(--dsw-alias-bg-overlay,#fff);color:var(--dsw-alias-label-secondary,#59636e);font-size:12px;line-height:1.4;white-space:nowrap}\n.dq-tab-chip--current{cursor:grab;color:var(--dsw-alias-label-primary,#1f2328);border-color:var(--dsw-alias-state-business-primary,#0969da);font-weight:600;user-select:none;-webkit-user-select:none;touch-action:none}\n.dq-tab-chip--current:active{cursor:grabbing}\n.dq-tab-chip--current:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px}\n.dq-tab-chip--dragging{opacity:.55}\n.dq-tab-chip--drop-target{border-style:dashed;border-color:var(--dsw-alias-state-business-primary,#0969da)}\n/* ============================================================================\n \u300C\u56FE\u7247 / \u591A\u6A21\u6001\u7528\u91CF\u300Dlives inside the usage-trend card. The grid-rows 0fr\u21921fr\n trick animates the section's real height as a window range makes it appear\n or disappear; opacity/translate make the change read as a reveal rather\n than a reflow. The body keeps 14px of top room in both states (clipped by\n the 0fr row when closed) so opening never jumps.\n ============================================================================ */\n.dq-vision-inline{display:grid;grid-template-rows:0fr;margin-top:0;opacity:0;transform:translateY(-3px);overflow:hidden;transition:grid-template-rows .32s cubic-bezier(.22,1,.36,1),margin-top .32s cubic-bezier(.22,1,.36,1),opacity .2s ease,transform .32s cubic-bezier(.22,1,.36,1)}\n.dq-vision-inline[data-open=\"true\"]{grid-template-rows:1fr;margin-top:24px;opacity:1;transform:none}\n.dq-vision-inline-body{min-height:0;overflow:hidden}\n.dq-vision-inline-body>.dq-chart-title{margin-top:0}\n.dq-vision-inline-body>.dq-chart-title{margin-top:0}\n\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";
@@ -10,6 +10,7 @@ export interface ConversationViewsSource {
10
10
  export interface ConversationViewSlotEntry {
11
11
  options: {
12
12
  id?: string;
13
+ order?: number;
13
14
  label?: string | (() => string);
14
15
  };
15
16
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cassius0924/dsh-usage-dashboard",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "DeepSeek 额度与用量仪表盘 —— DSH (DeepSeek Harness) Web 插件:余额还能撑几天、今日/本月花了多少、哪个模型和哪个会话最贵、图片/多模态用量、缓存省了多少、高峰挪到闲时能省多少",
5
5
  "keywords": [
6
6
  "deepseek",
@@ -74,6 +74,7 @@
74
74
  "@deepseek-ai/cordis": "^4.0.1",
75
75
  "@types/node": "^24.0.0",
76
76
  "@types/react": "^18.2.0",
77
+ "@types/react-dom": "^18.3.7",
77
78
  "esbuild": "^0.25.0",
78
79
  "react": "^18.2.0",
79
80
  "typescript": "^5.6.0"