@cassius0924/dsh-usage-dashboard 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -422,7 +422,7 @@ var zh = {
422
422
  "chart.daily": "\u9010\u5929",
423
423
  "chart.hourly": "\u9010\u5C0F\u65F6",
424
424
  "chart.noWindowData": "{window}\u6CA1\u6709\u7528\u91CF\u8BB0\u5F55\uFF0C\u6362\u4E2A\u66F4\u957F\u5468\u671F\u770B\u770B\u3002",
425
- "chart.heatmapTitle": "\u8FD1\u4E00\u5E74 \xB7 \u6BCF\u65E5\u7528\u91CF\u70ED\u529B\u56FE",
425
+ "chart.heatmapTitle": "\u8FD1\u4E00\u5E74 \xB7 \u6BCF\u65E5",
426
426
  "chart.empty": "\u8FD8\u6CA1\u6709\u7528\u91CF\u8BB0\u5F55\u3002\u5728 DSH \u91CC\u8DD1\u4E00\u8F6E\u5BF9\u8BDD\uFF0C\u8FD9\u91CC\u4F1A\u51FA\u73B0\u9010\u5929 / \u9010\u5C0F\u65F6\u7EDF\u8BA1\u4E0E\u8D39\u7528\u4F30\u7B97\u3002",
427
427
  "chart.hourPoint": "{hour} \u70B9",
428
428
  "chart.tooltip": "{head} \xB7 {tokens} tokens \xB7 \xA5{cost} \xB7 {calls}",
@@ -467,6 +467,7 @@ var zh = {
467
467
  "error.credentialsUnavailable": "\u51ED\u8BC1\u670D\u52A1\u4E0D\u53EF\u7528",
468
468
  "error.credentialRead": "\u8BFB\u53D6 API Key \u5931\u8D25\uFF1A{detail}",
469
469
  "error.noApiKey": "\u672A\u914D\u7F6E DEEPSEEK_API_KEY\uFF08\u53EF\u5728\u300C\u8BBE\u7F6E \u2192 \u6A21\u578B\u300D\u4E2D\u586B\u5199\uFF09",
470
+ "error.accountBalanceUnavailable": "\u8D26\u53F7\u4F59\u989D\u63A5\u53E3\u4E0D\u53EF\u7528\uFF0C\u4E14\u672A\u914D\u7F6E DEEPSEEK_API_KEY",
470
471
  "error.balanceRequest": "\u8BF7\u6C42\u4F59\u989D\u63A5\u53E3\u5931\u8D25\uFF1A{detail}",
471
472
  "error.balanceHttp": "\u4F59\u989D\u63A5\u53E3\u8FD4\u56DE\u9519\u8BEF\uFF08HTTP {status}\uFF09",
472
473
  "error.balanceParse": "\u89E3\u6790\u4F59\u989D\u54CD\u5E94\u5931\u8D25",
@@ -488,28 +489,30 @@ var zh = {
488
489
  "balance.overYear": "> 365 \u5929",
489
490
  "balance.noRunway": "\u8FD1 {days} \u5929\u6CA1\u6709\u7528\u91CF\uFF0C\u65E0\u6CD5\u4F30\u7B97",
490
491
  "balance.runwayTitle": "\u6309\u8FD1 {days} \u5929\u65E5\u5747 \xA5{cost} \u4F30\u7B97\uFF08\u542B\u65E0\u7528\u91CF\u7684\u65E5\u5B50\uFF1B\u4ECA\u5929\u5C1A\u672A\u8FC7\u5B8C\uFF09",
491
- "balance.empty": "\u8BFB\u4E0D\u5230\u4F59\u989D\u3002\u8BF7\u786E\u8BA4\u300C\u8BBE\u7F6E \u2192 \u6A21\u578B\u300D\u91CC\u5DF2\u586B DEEPSEEK_API_KEY\uFF0C\u7136\u540E\u70B9\u53F3\u4E0A\u89D2\u5237\u65B0\u3002",
492
- "sessionUsage.title": "\u5F53\u524D\u4F1A\u8BDD\u6D88\u8017\uFF08\u8D39\u7528\u4E3A\u4F30\u7B97\uFF09",
493
- "sessionUsage.cost": "\u672C\u4F1A\u8BDD\u8D39\u7528",
494
- "sessionUsage.tokens": "\u672C\u4F1A\u8BDD tokens",
495
- "sessionUsage.calls": "\u672C\u4F1A\u8BDD\u8C03\u7528",
492
+ "balance.empty": "\u8BFB\u4E0D\u5230\u4F59\u989D\u3002\u8BF7\u786E\u8BA4\u8D26\u53F7\u5DF2\u767B\u5F55\uFF0C\u6216\u5728\u300C\u8BBE\u7F6E \u2192 \u6A21\u578B\u300D\u4E2D\u586B\u5199 DEEPSEEK_API_KEY\uFF0C\u7136\u540E\u70B9\u53F3\u4E0A\u89D2\u5237\u65B0\u3002",
493
+ "sessionUsage.title": "\u5F53\u524D\u4F1A\u8BDD\u6D88\u8017",
494
+ "common.estimated": "\u8D39\u7528\u4E3A\u4F30\u7B97",
495
+ "sessionUsage.cost": "\u8D39\u7528",
496
+ "sessionUsage.tokens": "Tokens",
497
+ "sessionUsage.calls": "\u8C03\u7528\u6B21\u6570",
496
498
  "sessionUsage.range": "\u6D3B\u8DC3\u65F6\u95F4 {range}",
499
+ "sessionUsage.single": "{model} \xB7 \u8F93\u5165 {input} / \u8F93\u51FA {output} / \u7F13\u5B58 {cache}",
497
500
  "sessionUsage.empty": "\u8FD9\u4E2A\u4F1A\u8BDD\u8FD8\u6CA1\u6709\u4EA7\u751F\u7528\u91CF\u3002\u53D1\u4E00\u6761\u6D88\u606F\u540E\uFF0C\u8FD9\u91CC\u4F1A\u663E\u793A\u8FD9\u4E2A\u4F1A\u8BDD\u4E13\u5C5E\u7684\u8D39\u7528\u4E0E\u6A21\u578B\u660E\u7EC6\u3002",
498
- "overview.title": "\u6D88\u8017\u6982\u89C8\uFF08\u8D39\u7528\u4E3A\u4F30\u7B97\uFF09",
501
+ "overview.title": "\u6D88\u8017\u6982\u89C8",
499
502
  "overview.today": "\u4ECA\u65E5",
500
503
  "overview.month": "\u672C\u6708",
501
504
  "overview.total": "\u7D2F\u8BA1",
502
505
  "overview.vsYesterday": "\u8F83\u6628\u65E5",
503
506
  "overview.vsLastMonth": "\u8F83\u4E0A\u6708\u540C\u671F",
504
507
  "overview.empty": "\u8FD8\u6CA1\u6709\u53EF\u7EDF\u8BA1\u7684\u6D88\u8017\u3002",
505
- "usage.trendTitle": "\u7528\u91CF\u8D8B\u52BF\uFF08tokens\uFF09",
508
+ "usage.trendTitle": "\u7528\u91CF\u8D8B\u52BF",
506
509
  "usage.windowInput": "{window}\u8F93\u5165",
507
510
  "usage.modelCalls": "\u6A21\u578B\u8C03\u7528",
508
511
  "heatmap.title": "\u7528\u91CF\u70ED\u529B\u56FE",
509
512
  "peak.title": "\u9AD8\u5CF0 / \u95F2\u65F6\u5206\u5E03",
510
513
  "cache.title": "\u7F13\u5B58\u547D\u4E2D\u4E0E\u8282\u7701",
511
- "models.title": "\u6A21\u578B\u6210\u672C\u6392\u884C \xB7 {window}",
512
- "sessions.title": "\u4F1A\u8BDD\u6210\u672C\u6392\u884C \xB7 {window}",
514
+ "models.title": "\u6A21\u578B\u6210\u672C\u6392\u884C",
515
+ "sessions.title": "\u4F1A\u8BDD\u6210\u672C\u6392\u884C",
513
516
  "links.title": "\u5FEB\u6377\u5165\u53E3",
514
517
  "links.usage": "\u67E5\u770B\u989D\u5EA6 / \u7528\u91CF",
515
518
  "links.apiKey": "\u751F\u6210 API Key",
@@ -680,7 +683,7 @@ var en = {
680
683
  "chart.daily": "Daily",
681
684
  "chart.hourly": "Hourly",
682
685
  "chart.noWindowData": "No usage in {window}. Try a longer range.",
683
- "chart.heatmapTitle": "Last year \xB7 daily usage heatmap",
686
+ "chart.heatmapTitle": "Last 12 months \xB7 daily",
684
687
  "chart.empty": "No usage yet. Run a conversation in DSH to see daily and hourly totals with cost estimates.",
685
688
  "chart.hourPoint": "{hour}:00",
686
689
  "chart.tooltip": "{head} \xB7 {tokens} tokens \xB7 \xA5{cost} \xB7 {calls}",
@@ -725,6 +728,7 @@ var en = {
725
728
  "error.credentialsUnavailable": "Credential service is unavailable",
726
729
  "error.credentialRead": "Could not read the API key: {detail}",
727
730
  "error.noApiKey": "DEEPSEEK_API_KEY is not configured (add it under Settings \u2192 Models)",
731
+ "error.accountBalanceUnavailable": "The account balance endpoint is unavailable and DEEPSEEK_API_KEY is not configured",
728
732
  "error.balanceRequest": "Balance request failed: {detail}",
729
733
  "error.balanceHttp": "Balance endpoint returned HTTP {status}",
730
734
  "error.balanceParse": "Could not parse the balance response",
@@ -746,28 +750,30 @@ var en = {
746
750
  "balance.overYear": "> 365 days",
747
751
  "balance.noRunway": "No usage in the last {days} days, so runway cannot be estimated",
748
752
  "balance.runwayTitle": "Based on \xA5{cost} average daily spend over the last {days} days (including idle days; today is incomplete)",
749
- "balance.empty": "Balance is unavailable. Add DEEPSEEK_API_KEY under Settings \u2192 Models, then refresh.",
750
- "sessionUsage.title": "Current session spend (estimated)",
751
- "sessionUsage.cost": "This session",
752
- "sessionUsage.tokens": "Session tokens",
753
- "sessionUsage.calls": "Session calls",
753
+ "balance.empty": "Balance is unavailable. Sign in to your account or add DEEPSEEK_API_KEY under Settings \u2192 Models, then refresh.",
754
+ "sessionUsage.title": "Current session spend",
755
+ "common.estimated": "Estimated cost",
756
+ "sessionUsage.cost": "Cost",
757
+ "sessionUsage.tokens": "Tokens",
758
+ "sessionUsage.calls": "Calls",
754
759
  "sessionUsage.range": "Active {range}",
760
+ "sessionUsage.single": "{model} \xB7 input {input} / output {output} / cache {cache}",
755
761
  "sessionUsage.empty": "No usage in this session yet. Send a message and this session\u2019s own cost and model breakdown will show up here.",
756
- "overview.title": "Spend overview (estimated)",
762
+ "overview.title": "Spend overview",
757
763
  "overview.today": "Today",
758
764
  "overview.month": "This month",
759
765
  "overview.total": "All time",
760
766
  "overview.vsYesterday": "vs yesterday",
761
767
  "overview.vsLastMonth": "vs same period last month",
762
768
  "overview.empty": "No spend to summarize yet.",
763
- "usage.trendTitle": "Usage trend (tokens)",
769
+ "usage.trendTitle": "Usage trend",
764
770
  "usage.windowInput": "{window} input",
765
771
  "usage.modelCalls": "Model calls",
766
772
  "heatmap.title": "Usage heatmap",
767
773
  "peak.title": "Peak / off-peak distribution",
768
774
  "cache.title": "Cache hits and savings",
769
- "models.title": "Model cost ranking \xB7 {window}",
770
- "sessions.title": "Session cost ranking \xB7 {window}",
775
+ "models.title": "Model cost ranking",
776
+ "sessions.title": "Session cost ranking",
771
777
  "links.title": "Quick Links",
772
778
  "links.usage": "View balance / usage",
773
779
  "links.apiKey": "Create API key",
@@ -830,6 +836,7 @@ function localizeApiError(message, t, fallback) {
830
836
  if (message === "\u4F59\u989D\u52A0\u8F7D\u5931\u8D25") return t("error.balanceLoad");
831
837
  if (message === "\u7528\u91CF\u52A0\u8F7D\u5931\u8D25") return t("error.usageLoad");
832
838
  if (message === "\u672A\u914D\u7F6E DEEPSEEK_API_KEY\uFF08\u53EF\u5728\u300C\u8BBE\u7F6E \u2192 \u6A21\u578B\u300D\u4E2D\u586B\u5199\uFF09") return t("error.noApiKey");
839
+ if (message === "\u8D26\u53F7\u4F59\u989D\u63A5\u53E3\u4E0D\u53EF\u7528\uFF0C\u4E14\u672A\u914D\u7F6E DEEPSEEK_API_KEY") return t("error.accountBalanceUnavailable");
833
840
  if (message === "\u89E3\u6790\u4F59\u989D\u54CD\u5E94\u5931\u8D25") return t("error.balanceParse");
834
841
  if (message === "\u4F1A\u8BDD\u6301\u4E45\u5316\u670D\u52A1\u4E0D\u53EF\u7528") return t("error.persistenceUnavailable");
835
842
  if (message === "\u7F3A\u5C11\u4F1A\u8BDD id") return t("error.missingSessionId");
@@ -1423,7 +1430,7 @@ function Period(props) {
1423
1430
  previous !== void 0 && compare !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Delta, { current: period.cost, previous: previous.cost, label: compare })
1424
1431
  ] }),
1425
1432
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-period-cost", children: [
1426
- "\xA5 ",
1433
+ "\xA5",
1427
1434
  fmt(period.cost)
1428
1435
  ] }),
1429
1436
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-period-sub", children: t("period.volume", {
@@ -1448,9 +1455,9 @@ function BudgetMeter(props) {
1448
1455
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-budget-head", children: [
1449
1456
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-budget-title", children: t("budget.title") }),
1450
1457
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "dq-budget-amount", children: [
1451
- "\xA5 ",
1458
+ "\xA5",
1452
1459
  fmt(snapshot.spent),
1453
- " / \xA5 ",
1460
+ " / \xA5",
1454
1461
  fmt(snapshot.budget)
1455
1462
  ] })
1456
1463
  ] }),
@@ -1562,6 +1569,12 @@ function CoverageDiagnostics(props) {
1562
1569
  ] })
1563
1570
  ] });
1564
1571
  }
1572
+ function CardTitle(props) {
1573
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("h2", { className: `dq-card-title${props.srOnly === true ? " dq-sr-only" : ""}`, children: [
1574
+ props.children,
1575
+ props.caption !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-card-caption", children: props.caption })
1576
+ ] });
1577
+ }
1565
1578
  function Stat(props) {
1566
1579
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat", children: [
1567
1580
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-stat-label", children: props.label }),
@@ -1670,14 +1683,22 @@ function SessionUsageCard(props) {
1670
1683
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1671
1684
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-balance-grid", children: [
1672
1685
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("sessionUsage.cost"), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat-value", children: [
1673
- "\xA5 ",
1686
+ "\xA5",
1674
1687
  fmt(data.cost)
1675
1688
  ] }) }),
1676
1689
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("sessionUsage.tokens"), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-stat-value", children: fmtCompact(data.total, locale) }) }),
1677
1690
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("sessionUsage.calls"), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-stat-value", children: fmtInt(data.calls) }) })
1678
1691
  ] }),
1679
- range !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "dq-session-sub", children: t("sessionUsage.range", { range }) }),
1680
- data.models.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-rank", children: data.models.map((m, index) => {
1692
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-session-meta", children: [
1693
+ range !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "dq-session-sub", children: t("sessionUsage.range", { range }) }),
1694
+ data.models.length === 1 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "dq-session-sub", children: t("sessionUsage.single", {
1695
+ model: data.models[0].model !== "" ? data.models[0].model : t("common.unknownModel"),
1696
+ input: fmtCompact(data.models[0].input, locale),
1697
+ output: fmtCompact(data.models[0].output, locale),
1698
+ cache: fmtCompact(data.models[0].cache, locale)
1699
+ }) })
1700
+ ] }),
1701
+ data.models.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-rank", children: data.models.map((m, index) => {
1681
1702
  const key = m.provider !== "" ? `${m.provider}/${m.model}` : m.model !== "" ? m.model : `model-${index}`;
1682
1703
  const name2 = m.model !== "" ? m.model : t("common.unknownModel");
1683
1704
  const color = MODEL_COLORS[index % MODEL_COLORS.length];
@@ -1689,7 +1710,7 @@ function SessionUsageCard(props) {
1689
1710
  name2
1690
1711
  ] }),
1691
1712
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "dq-rank-cost", children: [
1692
- "\xA5 ",
1713
+ "\xA5",
1693
1714
  fmt(m.cost),
1694
1715
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "dq-rank-share", children: [
1695
1716
  (share * 100).toFixed(1),
@@ -1737,14 +1758,14 @@ function CacheCard(props) {
1737
1758
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat", children: [
1738
1759
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-stat-label", children: t("cache.saved") }),
1739
1760
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat-value", children: [
1740
- "\xA5 ",
1761
+ "\xA5",
1741
1762
  fmt(totals.cacheSavings)
1742
1763
  ] })
1743
1764
  ] }),
1744
1765
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat", children: [
1745
1766
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-stat-label", children: t("cache.allMiss") }),
1746
1767
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat-value dq-muted-value", children: [
1747
- "\xA5 ",
1768
+ "\xA5",
1748
1769
  fmt(wouldHaveCost)
1749
1770
  ] })
1750
1771
  ] })
@@ -1783,7 +1804,7 @@ function VisionCard(props) {
1783
1804
  tokensShare > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-vision-share", children: t("vision.tokensShare", { percent: tokensShare.toFixed(1) }) })
1784
1805
  ] }) }),
1785
1806
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("vision.cost"), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat-value", children: [
1786
- "\xA5 ",
1807
+ "\xA5",
1787
1808
  fmt(vision.cost),
1788
1809
  costShare > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-vision-share", children: t("vision.costShare", { percent: costShare.toFixed(1) }) })
1789
1810
  ] }) })
@@ -1838,7 +1859,7 @@ function PeakCard(props) {
1838
1859
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-peak-figures", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat", children: [
1839
1860
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-stat-label", children: t("peak.shift") }),
1840
1861
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat-value", children: [
1841
- "\xA5 ",
1862
+ "\xA5",
1842
1863
  fmt(split.offPeakEraCost),
1843
1864
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-peak-delta dq-peak-delta--save", children: t("peak.saving", { amount: fmt(shiftSaving) }) })
1844
1865
  ] })
@@ -1895,13 +1916,13 @@ function SessionRanking(props) {
1895
1916
  },
1896
1917
  children: [
1897
1918
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("summary", { className: "dq-session-summary", children: [
1898
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-session-chevron", "aria-hidden": "true", children: "\u25B8" }),
1919
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-session-chevron", "aria-hidden": "true" }),
1899
1920
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-session-summary-body", children: [
1900
1921
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-session-head", children: [
1901
1922
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-session-title", title: `${s.title}
1902
1923
  ${s.id}`, children: s.title || t("sessions.fallbackTitle", { id: s.id }) }),
1903
1924
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "dq-session-cost", children: [
1904
- "\xA5 ",
1925
+ "\xA5",
1905
1926
  fmt(s.cost)
1906
1927
  ] })
1907
1928
  ] }),
@@ -1940,7 +1961,7 @@ function ModelRanking(props) {
1940
1961
  modelNameOf(m, t)
1941
1962
  ] }),
1942
1963
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "dq-rank-cost", children: [
1943
- "\xA5 ",
1964
+ "\xA5",
1944
1965
  fmt(m.cost),
1945
1966
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "dq-rank-share", children: [
1946
1967
  (share * 100).toFixed(1),
@@ -2407,8 +2428,8 @@ function BalanceDashboard(props) {
2407
2428
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { className: "dq-alert-link", href: "https://platform.deepseek.com/top_up", target: "_blank", rel: "noreferrer", children: t("alert.topUp") })
2408
2429
  ] })
2409
2430
  ] }),
2410
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card dq-card--primary", children: [
2411
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-card-title", children: t("balance.title") }),
2431
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card dq-card--hero", children: [
2432
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { srOnly: true, children: t("balance.title") }),
2412
2433
  primary !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-balance-grid", children: [
2413
2434
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat", children: [
2414
2435
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-stat-label", children: t("balance.remaining") }),
@@ -2424,14 +2445,14 @@ function BalanceDashboard(props) {
2424
2445
  "summary",
2425
2446
  {
2426
2447
  title: t("balance.breakdownTitle"),
2448
+ "aria-label": `${fmt(primary.total)} ${primary.currency}`,
2427
2449
  onClick: (e) => {
2428
2450
  e.preventDefault();
2429
2451
  setRemainingManuallyOpened((v) => !v);
2430
2452
  },
2431
2453
  children: [
2432
2454
  fmt(primary.total),
2433
- " ",
2434
- primary.currency
2455
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-hero-unit", children: primary.currency })
2435
2456
  ]
2436
2457
  }
2437
2458
  ),
@@ -2469,15 +2490,15 @@ function BalanceDashboard(props) {
2469
2490
  }
2470
2491
  )
2471
2492
  ] }),
2472
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("common.status"), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `dq-stat-value${balance?.isAvailable === false ? " dq-stat-value--bad" : " dq-stat-value--ok"}`, children: balance?.isAvailable === false ? t("common.unavailable") : t("common.available") }) })
2493
+ balance?.isAvailable === false && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("common.status"), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-stat-value dq-stat-value--bad", children: t("common.unavailable") }) })
2473
2494
  ] }) : loadingBalance ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BalanceSkeleton, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("balance.empty") })
2474
2495
  ] }),
2475
2496
  props.sessionId !== void 0 && props.sessionId !== "" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card dq-card--primary", children: [
2476
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-card-title", children: t("sessionUsage.title") }),
2497
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { caption: t("common.estimated"), children: t("sessionUsage.title") }),
2477
2498
  sessionUsage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SessionUsageCard, { data: sessionUsage }) : loadingSessionUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SessionUsageSkeleton, {}) : sessionUsageError !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty dq-empty--error", children: localizeApiError(sessionUsageError, t, "error.query") }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("sessionUsage.empty") })
2478
2499
  ] }),
2479
2500
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card dq-card--primary", children: [
2480
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-card-title", children: t("overview.title") }),
2501
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { caption: t("common.estimated"), children: t("overview.title") }),
2481
2502
  usage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-period-grid", children: [
2482
2503
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Period, { label: t("overview.today"), period: usage.summary.today, previous: usage.summary.yesterday, compare: t("overview.vsYesterday") }),
2483
2504
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Period, { label: t("overview.month"), period: usage.summary.month, previous: usage.summary.lastMonthToDate, compare: t("overview.vsLastMonth") }),
@@ -2503,21 +2524,24 @@ function BalanceDashboard(props) {
2503
2524
  ),
2504
2525
  usage !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PricingNote, { pricing: usage.pricing })
2505
2526
  ] }),
2506
- usage !== null && activeWindow !== null && activeWindow.vision !== void 0 && Array.isArray(activeWindow.visionDaily) && Array.isArray(activeWindow.visionSessions) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
2507
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-card-title", children: t("vision.title") }),
2508
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2509
- VisionCard,
2510
- {
2511
- vision: activeWindow.vision,
2512
- daily: activeWindow.visionDaily,
2513
- sessions: activeWindow.visionSessions,
2514
- windowLabel: activeWindowName,
2515
- inputTokens: activeWindow.totals.input,
2516
- costTotal: activeWindow.totals.cost
2517
- }
2518
- )
2519
- ] }) : usage === null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
2520
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-card-title", children: t("vision.title") }),
2527
+ usage !== null && activeWindow !== null && activeWindow.vision !== void 0 && Array.isArray(activeWindow.visionDaily) && Array.isArray(activeWindow.visionSessions) ? (
2528
+ // 窗口内没有图片时整张卡不出现:一行「没有图片输入」不值得一个小节的位置。
2529
+ activeWindow.vision.images === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
2530
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { caption: activeWindowName, children: t("vision.title") }),
2531
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2532
+ VisionCard,
2533
+ {
2534
+ vision: activeWindow.vision,
2535
+ daily: activeWindow.visionDaily,
2536
+ sessions: activeWindow.visionSessions,
2537
+ windowLabel: activeWindowName,
2538
+ inputTokens: activeWindow.totals.input,
2539
+ costTotal: activeWindow.totals.cost
2540
+ }
2541
+ )
2542
+ ] })
2543
+ ) : usage === null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
2544
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { caption: activeWindowName, children: t("vision.title") }),
2521
2545
  loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-usage-totals", children: [64, 88, 72].map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat", children: [
2522
2546
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w, h: 11 }),
2523
2547
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w: 72, h: 20 })
@@ -2530,7 +2554,7 @@ function BalanceDashboard(props) {
2530
2554
  ),
2531
2555
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card dq-card--primary", children: [
2532
2556
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card-head", children: [
2533
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-card-title", children: t("usage.trendTitle") }),
2557
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { children: t("usage.trendTitle") }),
2534
2558
  usage !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card-actions", children: [
2535
2559
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(UsageWindowPicker, { value: windowDays, onChange: changeWindowDays }),
2536
2560
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ExportMenu, { usage })
@@ -2582,7 +2606,7 @@ function BalanceDashboard(props) {
2582
2606
  GroupedBars,
2583
2607
  {
2584
2608
  series: grouped,
2585
- height: barMode === "daily" ? 120 : 100,
2609
+ height: barMode === "daily" ? 160 : 140,
2586
2610
  labelEvery: barMode === "daily" ? dailyLabelEvery : 3,
2587
2611
  minWidth: barMode === "daily" ? dailyMinWidth : void 0
2588
2612
  }
@@ -2591,19 +2615,16 @@ function BalanceDashboard(props) {
2591
2615
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-legend-swatch", style: { background: s.color } }),
2592
2616
  s.name
2593
2617
  ] }, s.key)) })
2594
- ] }) : barMode === "daily" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Bars, { data: dailyBars, height: 120, labelEvery: dailyLabelEvery, minWidth: dailyMinWidth }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Bars, { data: hourlyBars, height: 100, labelEvery: 3 }),
2618
+ ] }) : barMode === "daily" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Bars, { data: dailyBars, height: 160, labelEvery: dailyLabelEvery, minWidth: dailyMinWidth }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Bars, { data: hourlyBars, height: 140, labelEvery: 3 }),
2595
2619
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CoverageDiagnostics, { coverage: usage.coverage })
2596
2620
  ] }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(UsageSkeleton, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("chart.empty") })
2597
2621
  ] }),
2598
2622
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
2599
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-card-title", children: t("heatmap.title") }),
2600
- usage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
2601
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-chart-title", children: t("chart.heatmapTitle") }),
2602
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Heatmap, { data: usage.heatmap })
2603
- ] }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HeatmapSkeleton, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("chart.empty") })
2623
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { caption: t("chart.heatmapTitle"), children: t("heatmap.title") }),
2624
+ usage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Heatmap, { data: usage.heatmap }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HeatmapSkeleton, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("chart.empty") })
2604
2625
  ] }),
2605
2626
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
2606
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-card-title", children: t("peak.title") }),
2627
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { children: t("peak.title") }),
2607
2628
  usage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PeakCard, { split: usage.peakSplit, pricing: usage.pricing }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
2608
2629
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-peak-track" }),
2609
2630
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-peak-figures", children: [
@@ -2613,14 +2634,14 @@ function BalanceDashboard(props) {
2613
2634
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("peak.empty") })
2614
2635
  ] }),
2615
2636
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
2616
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-card-title", children: t("cache.title") }),
2637
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { children: t("cache.title") }),
2617
2638
  usage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CacheCard, { totals: usage.totals }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-cache-figures", children: [60, 96, 72].map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat", children: [
2618
2639
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w, h: 11 }),
2619
2640
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w: 72, h: 20 })
2620
2641
  ] }, i)) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("cache.empty") })
2621
2642
  ] }),
2622
2643
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
2623
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-card-title", children: t("models.title", { window: activeWindowName }) }),
2644
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { caption: activeWindowName, children: t("models.title") }),
2624
2645
  activeWindow !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ModelRanking, { models: modelList, totalCost: modelCostTotal, colorOf }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-rank", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-rank-row", children: [
2625
2646
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w: 148, h: 13 }),
2626
2647
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-rank-track" }),
@@ -2628,7 +2649,7 @@ function BalanceDashboard(props) {
2628
2649
  ] }, i)) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("models.empty") })
2629
2650
  ] }),
2630
2651
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
2631
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-card-title", children: t("sessions.title", { window: activeWindowName }) }),
2652
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { caption: activeWindowName, children: t("sessions.title") }),
2632
2653
  activeWindow !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SessionRanking, { sessions: activeWindow.sessions, count: activeWindow.sessionCount, totalCost: activeWindow.totals.cost }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-sessions", children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-session", children: [
2633
2654
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w: 200, h: 13 }),
2634
2655
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-session-track" }),
@@ -2636,7 +2657,7 @@ function BalanceDashboard(props) {
2636
2657
  ] }, i)) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("sessions.empty") })
2637
2658
  ] }),
2638
2659
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
2639
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-card-title", children: t("settings.title") }),
2660
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { children: t("settings.title") }),
2640
2661
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-links-title", children: t("links.title") }),
2641
2662
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-links", children: [
2642
2663
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Link, { href: "https://platform.deepseek.com/usage", children: t("links.usage") }),
@@ -2704,7 +2725,7 @@ function BalanceDashboard(props) {
2704
2725
  ] })
2705
2726
  ] })
2706
2727
  ] }),
2707
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "dq-footer", children: "@cassius0924/dsh-usage-dashboard v0.6.0" })
2728
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "dq-footer", children: "@cassius0924/dsh-usage-dashboard v0.7.0" })
2708
2729
  ] });
2709
2730
  }
2710
2731
 
@@ -2731,7 +2752,7 @@ function MessageCost({ sessionId, messageId }) {
2731
2752
  }, [messageId, sessionId]);
2732
2753
  const turn = data?.turns.find((candidate) => candidate.messageId === messageId);
2733
2754
  if (turn === void 0) return null;
2734
- const amount = `\xA5 ${fmtTurnCost(turn.cost)}`;
2755
+ const amount = `\xA5${fmtTurnCost(turn.cost)}`;
2735
2756
  const tooltip = t("messageCost.tooltip");
2736
2757
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2737
2758
  "span",
@@ -2750,7 +2771,7 @@ function MessageCost({ sessionId, messageId }) {
2750
2771
 
2751
2772
  // src/client/styles.ts
2752
2773
  var css = `
2753
- .dsh-quota-root{position:absolute;right:16px;bottom:16px;z-index:2147483000;pointer-events:auto;opacity:1;visibility:visible;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:13px;line-height:1.45;color:var(--dsw-alias-label-primary,#1f2328);transition:left .28s cubic-bezier(.22,1,.36,1),top .28s cubic-bezier(.22,1,.36,1),opacity .16s ease-out,visibility 0s linear}
2774
+ .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}
2754
2775
  .dsh-quota-root.dsh-quota-root--hidden{opacity:0;visibility:hidden;pointer-events:none;transition:opacity .14s ease-out,visibility 0s linear .14s}
2755
2776
  .dsh-quota-root.dsh-quota-dragging{transition:none}
2756
2777
  .dsh-quota-card,.dsh-quota-card *{box-sizing:border-box}
@@ -2759,14 +2780,14 @@ var css = `
2759
2780
  .dsh-quota-header{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px;min-width:0}
2760
2781
  .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}
2761
2782
  .dsh-quota-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
2762
- .dsh-quota-grip{color:var(--dsw-alias-label-secondary,#59636e);opacity:.7;font-size:11px;letter-spacing:0;cursor:grab;flex:none}
2783
+ .dsh-quota-grip{color:var(--dsw-alias-label-secondary,#59636e);opacity:.7;font-size:12px;letter-spacing:0;cursor:grab;flex:none}
2763
2784
  .dsh-quota-dot{width:8px;height:8px;border-radius:50%;background:var(--dsw-alias-state-success-primary,#2da44e);flex:none}
2764
2785
  .dsh-quota-dot--error{background:var(--dsw-alias-state-error-primary,#cf222e)}
2765
2786
  .dsh-quota-dot--warn{background:var(--dsw-alias-state-warning-primary,#bf8700)}
2766
- .dsh-quota-total--low{color:var(--dsw-alias-state-warning-primary,#9a6700)!important}
2787
+ .dsh-quota-total--low{color:var(--dq-text-warn)!important}
2767
2788
  .dsh-quota-dot--idle{background:var(--dsw-alias-label-secondary,#59636e);opacity:.6}
2768
2789
  .dsh-quota-collapsed-total-row{margin-top:6px}
2769
- .dsh-quota-collapsed-total{font-weight:700;font-size:15px;color:var(--dsw-alias-state-business-primary,#0969da);font-variant-numeric:tabular-nums}
2790
+ .dsh-quota-collapsed-total{font-weight:700;font-size:13px;color:var(--dsw-alias-state-business-primary,#0969da);font-variant-numeric:tabular-nums}
2770
2791
  .dsh-quota-actions{display:flex;gap:2px;flex:none}
2771
2792
  .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}
2772
2793
  .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)}
@@ -2774,19 +2795,19 @@ var css = `
2774
2795
  .dsh-quota-btn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px}
2775
2796
  .dsh-quota-btn:disabled{opacity:.5;cursor:default}
2776
2797
  .dsh-quota-body{color:var(--dsw-alias-label-secondary,#59636e)}
2777
- .dsh-quota-remaining-label{font-size:11px;color:var(--dsw-alias-label-tertiary,#59636e);margin-bottom:2px}
2778
- .dsh-quota-total{font-size:24px;font-weight:700;color:var(--dsw-alias-label-primary,#1f2328);letter-spacing:-.02em;font-variant-numeric:tabular-nums}
2779
- .dsh-quota-currency{font-size:14px;font-weight:600;margin-left:3px;color:var(--dsw-alias-label-secondary,#59636e)}
2798
+ .dsh-quota-remaining-label{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);margin-bottom:2px}
2799
+ .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}
2800
+ .dsh-quota-currency{font-size:13px;font-weight:500;margin-left:4px;color:var(--dsw-alias-label-secondary,#59636e)}
2780
2801
  .dsh-quota-row{display:flex;justify-content:space-between;gap:12px;margin-top:6px;font-size:12px}
2781
2802
  .dsh-quota-label{color:var(--dsw-alias-label-secondary,#59636e)}
2782
2803
  .dsh-quota-value{color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}
2783
2804
  .dsh-quota-error{color:var(--dsw-alias-state-error-primary,#cf222e)}
2784
- .dq-message-cost{position:relative;display:inline-flex;align-items:center;order:10;gap:10px;height:28px;color:var(--dsw-alias-label-tertiary,#59636e);font-size:12px;line-height:20px;font-variant-numeric:tabular-nums;white-space:nowrap;cursor:help}
2805
+ .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}
2785
2806
  .dq-message-cost-separator{cursor:default}
2786
2807
  .dq-message-cost-amount{text-decoration-line:underline;text-decoration-style:dotted;text-decoration-color:currentColor;text-underline-offset:4px}
2787
2808
  .dq-message-cost:hover{color:var(--dsw-alias-label-secondary,#3f4852)}
2788
2809
  .dq-message-cost:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px;border-radius:4px}
2789
- .dq-message-cost::after{content:attr(data-dq-tooltip);position:absolute;left:0;top:calc(100% + 6px);z-index:2147483001;width:max-content;max-width:min(240px,calc(100vw - 24px));padding:6px 9px;border-radius:8px;background:var(--dsw-alias-bg-inverse,#1f2328);color:var(--dsw-alias-label-inverse,#fff);box-shadow:0 6px 18px rgba(0,0,0,.22);font-size:12px;font-weight:400;line-height:1.45;text-align:left;white-space:normal;pointer-events:none;opacity:0;visibility:hidden;transform:translateY(-3px);transition:opacity .12s ease-out,transform .12s cubic-bezier(.22,1,.36,1),visibility 0s linear .12s}
2810
+ .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}
2790
2811
  .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}
2791
2812
  @media (hover:hover){
2792
2813
  [data-time-hover-root] .dq-message-cost{opacity:0;transition:opacity 80ms ease}
@@ -2800,13 +2821,16 @@ var css = `
2800
2821
  deliberately), but on narrower viewports the fixed 860px would overhang
2801
2822
  the input box \u2014 measured in dashboard.tsx as --dq-composer-w, capped at
2802
2823
  the reading-column width so wide viewports are unchanged. */
2803
- .dq-balance{display:flex;flex-direction:column;gap:24px;padding:20px 24px 48px;max-width:min(860px,var(--dq-composer-w,860px));margin:0 auto;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:13px;line-height:1.5;color:var(--dsw-alias-label-primary,#1f2328)}
2804
- @media (max-width:620px){.dq-balance{box-sizing:border-box;max-width:calc(100vw - 56px);padding:16px 16px calc(var(--dq-composer-h,126px) + 16px)}}
2805
- .dq-card{background:var(--dsw-alias-bg-layer-1,#ffffff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08));border-radius:12px;padding:16px;min-width:0;max-width:100%}
2806
- .dq-card-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary,#59636e);margin:0 0 12px;letter-spacing:.02em}
2807
- .dq-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px}
2824
+ .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%);}
2825
+ @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}}
2826
+ /* \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
2827
+ \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 */
2828
+ .dq-card{box-sizing:border-box;min-width:0;max-width:100%;padding:0 20px}
2829
+ .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}
2830
+ .dq-card-caption{font-size:12px;font-weight:400;color:var(--dsw-alias-label-secondary,#59636e)}
2831
+ .dq-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:16px}
2808
2832
  .dq-card-head .dq-card-title{margin:0}
2809
- .dq-card-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px;min-width:0}
2833
+ .dq-card-actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px;min-width:0}
2810
2834
  /* \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
2811
2835
  \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
2812
2836
  \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
@@ -2815,8 +2839,16 @@ var css = `
2815
2839
  \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
2816
2840
  \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
2817
2841
  primary \u6743\u91CD\uFF0C\u4E0D\u65B0\u5F00\u7B2C\u4E09\u6863\u3002 */
2818
- .dq-card--primary{padding:20px;border-color:var(--dsw-alias-border-l2,rgba(0,0,0,.12))}
2819
- .dq-card--primary .dq-card-title{font-size:13px;font-weight:700;color:var(--dsw-alias-label-primary,#1f2328)}
2842
+ .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}
2843
+ /* \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 */
2844
+ .dq-card--hero{padding:0 20px}
2845
+ .dq-card--hero .dq-stat-label{font-size:13px;margin-bottom:2px}
2846
+ .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}
2847
+ .dq-card--hero .dq-balance-grid{align-items:stretch;gap:12px 48px}
2848
+ .dq-card--hero .dq-stat{display:flex;flex-direction:column;justify-content:space-between}
2849
+ /* 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 */
2850
+ .dq-card--hero details>summary{text-decoration:none;margin:-2px -6px;padding:2px 6px;border-radius:8px;transition:background .15s ease}
2851
+ .dq-card--hero details>summary:hover,.dq-card--hero details[open]>summary{background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.05))}
2820
2852
  .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))}
2821
2853
  .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}
2822
2854
  .dq-window-btn:hover{color:var(--dsw-alias-label-primary,#1f2328)}
@@ -2831,7 +2863,7 @@ var css = `
2831
2863
  .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}
2832
2864
  .dq-export-menu button:hover,.dq-export-menu button:focus-visible{background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.06))}
2833
2865
  .dq-export-menu button:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:-1px}
2834
- .dq-export-menu small{font-size:10.5px;font-weight:400;color:var(--dsw-alias-label-tertiary,#59636e);white-space:nowrap}
2866
+ .dq-export-menu small{font-size:12px;font-weight:400;color:var(--dsw-alias-label-secondary,#59636e);white-space:nowrap}
2835
2867
  /* Small-text tier system (\u8F6E\u6B21 41 \u6536\u655B): two whole-pixel tiers replace what used to be four values
2836
2868
  (11/11.5/12/12.5px) spaced only 0.5px apart \u2014 a gap browsers subpixel-round away, so it read as one
2837
2869
  size with extra maintenance cost, not an actual visual hierarchy. 11px = "micro" chrome the user
@@ -2847,9 +2879,9 @@ var css = `
2847
2879
  it belongs in an already-established different tier (10px icon glyphs, 13px+ hero-adjacent text). */
2848
2880
  .dq-balance-grid{display:flex;flex-wrap:wrap;gap:12px 24px}
2849
2881
  .dq-stat{min-width:110px}
2850
- .dq-stat-label{font-size:11px;color:var(--dsw-alias-label-tertiary,#59636e);margin-bottom:2px}
2851
- .dq-stat-value{font-size:18px;font-weight:650;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}
2852
- .dq-stat-value--ok{color:var(--dsw-alias-state-success-primary,#2da44e)}
2882
+ .dq-stat-label{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);margin-bottom:4px}
2883
+ .dq-stat-value{font-size:18px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}
2884
+ .dq-stat-value--ok{color:var(--dq-text-success)}
2853
2885
  .dq-stat-value--bad{color:var(--dsw-alias-state-error-primary,#cf222e)}
2854
2886
  /* \u8F6E\u6B21 43: .dq-runway is a controlled <details> (see dashboard.tsx) \u2014 hover/toggle state
2855
2887
  drives the real open attribute now, so .dq-runway-detail only needs to react to [open];
@@ -2859,120 +2891,125 @@ var css = `
2859
2891
  .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}
2860
2892
  .dq-runway>summary::-webkit-details-marker{display:none}
2861
2893
  .dq-runway>summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:3px}
2862
- .dq-runway-detail{display:none;position:absolute;top:calc(100% + 6px);left:0;z-index:20;max-width:240px;padding:8px 10px;background:var(--dsw-alias-bg-overlay,#ffffff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.12));border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.15);white-space:normal;font-size:12px;font-weight:500;line-height:1.5;color:var(--dsw-alias-label-primary,#1f2328)}
2894
+ .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)}
2863
2895
  .dq-runway[open] .dq-runway-detail{display:block}
2864
2896
  /* hero number for the balance, matching .dq-period-cost; relies on cascade order (declared after
2865
2897
  .dq-stat-value, same specificity) to win over the .dq-stat-value it's paired with in JSX \u2014 keep it below */
2866
2898
  /* \u8F6E\u6B21 47: .dq-remaining is a controlled <details> too now (see dashboard.tsx), same reason as
2867
2899
  .dq-runway above \u2014 an unopened <details>'s non-summary children don't actually render in current
2868
2900
  Chromium regardless of author display value, so the old :hover{display:flex} branch was dead code. */
2869
- .dq-remaining{position:relative;font-size:22px;font-weight:680;letter-spacing:-.01em;line-height:1.25}
2901
+ .dq-remaining{position:relative;font-size:32px;font-weight:700;letter-spacing:-.025em;line-height:1.1}
2902
+ .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}
2870
2903
  .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}
2871
2904
  .dq-remaining>summary::-webkit-details-marker{display:none}
2872
2905
  .dq-remaining>summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:3px}
2873
- .dq-remaining-breakdown{display:none;position:absolute;top:calc(100% + 6px);left:0;z-index:20;flex-direction:column;gap:4px;padding:8px 10px;background:var(--dsw-alias-bg-overlay,#ffffff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.12));border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.15);white-space:nowrap;font-size:12px;font-weight:500;color:var(--dsw-alias-label-primary,#1f2328)}
2906
+ .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)}
2874
2907
  .dq-remaining[open] .dq-remaining-breakdown{display:flex}
2875
- .dq-remaining-granted{color:var(--dsw-alias-label-tertiary,#59636e);font-weight:400;font-size:11px}
2908
+ .dq-remaining-granted{color:var(--dsw-alias-label-secondary,#59636e);font-weight:400;font-size:12px}
2876
2909
  /* narrow screens: .dq-balance-grid wraps its 3 stats onto separate lines, so the absolutely-positioned
2877
2910
  .dq-remaining-breakdown/.dq-runway-detail popovers can float down over whichever stat now sits in the
2878
2911
  next row (e.g. "\u4F59\u989D\u660E\u7EC6" open covering "\u9884\u8BA1\u53EF\u7528"'s clickable summary) \u2014 force each stat onto its own
2879
2912
  full-width row and switch both popovers to normal in-flow layout so an open one pushes its own row
2880
2913
  taller instead of overlaying a sibling; desktop keeps the original hover-overlay behavior unchanged */
2881
2914
  @media (max-width:620px){
2882
- .dq-balance-grid .dq-stat{flex:1 1 100%}
2915
+ .dq-card--hero .dq-balance-grid{gap:12px 32px}
2916
+ .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}
2917
+ .dq-card--primary .dq-balance-grid .dq-stat,.dq-session-expand .dq-balance-grid .dq-stat{min-width:0}
2883
2918
  .dq-remaining-breakdown,.dq-runway-detail{position:static;margin-top:6px;box-shadow:none;max-width:none;white-space:normal}
2884
2919
  }
2885
- .dq-period-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0}
2886
- .dq-period{min-width:0;padding:4px 16px}
2887
- .dq-period:first-child{padding-left:0}
2888
- .dq-period:last-child{padding-right:0}
2889
- .dq-period+.dq-period{border-left:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}
2890
- @media (max-width:620px){.dq-period-grid{grid-template-columns:1fr}.dq-period,.dq-period:first-child,.dq-period:last-child{padding:12px 0}.dq-period:first-child{padding-top:2px}.dq-period+.dq-period{border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08));border-left:0}}
2891
- .dq-period-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:4px}
2892
- .dq-period-label{font-size:11px;color:var(--dsw-alias-label-tertiary,#59636e)}
2893
- .dq-period-cost{font-size:22px;font-weight:680;letter-spacing:-.01em;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;line-height:1.25}
2894
- .dq-period-sub{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);margin-top:2px;font-variant-numeric:tabular-nums;line-height:1.45}
2895
- .dq-budget{margin-top:12px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}
2920
+ .dq-period-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px 32px}
2921
+ .dq-period{min-width:0}
2922
+ /* \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 */
2923
+ @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}}
2924
+ .dq-period-head{display:flex;align-items:center;flex-wrap:wrap;gap:4px 8px;margin-bottom:8px}
2925
+ .dq-period-label{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}
2926
+ .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}
2927
+ .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}
2928
+ .dq-budget{margin-top:24px}
2896
2929
  .dq-budget--unset{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}
2897
2930
  .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}
2898
2931
  .dq-budget-action:hover{text-decoration:underline;text-underline-offset:3px}
2899
2932
  .dq-budget-action:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px}
2900
2933
  .dq-budget-head,.dq-budget-meta{display:flex;align-items:center;justify-content:space-between;gap:12px}
2901
- .dq-budget-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328)}
2902
- .dq-budget-amount{font-size:12px;font-weight:650;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}
2934
+ .dq-budget-title{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328)}
2935
+ .dq-budget-amount{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}
2903
2936
  .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}
2904
2937
  .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)}
2905
2938
  .dq-budget--risk .dq-budget-fill{background:var(--dsw-alias-state-warning-primary,#bf8700)}
2906
2939
  .dq-budget--over .dq-budget-fill{background:var(--dsw-alias-state-error-primary,#cf222e)}
2907
2940
  .dq-budget-meta{margin-top:6px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}
2908
- .dq-budget--risk .dq-budget-meta span:last-child{color:var(--dsw-alias-state-warning-primary,#9a6700);font-weight:600}
2941
+ .dq-budget--risk .dq-budget-meta span:last-child{color:var(--dq-text-warn);font-weight:600}
2909
2942
  .dq-budget--over .dq-budget-meta{color:var(--dsw-alias-state-error-primary,#cf222e);font-weight:600}
2910
- @media (max-width:620px){.dq-budget-head,.dq-budget-meta,.dq-budget--unset{align-items:flex-start;flex-direction:column;gap:4px}}
2911
- .dq-delta{display:inline-flex;align-items:center;gap:3px;font-size:11px;font-weight:600;padding:1px 6px;border-radius:999px;white-space:nowrap;cursor:help;font-variant-numeric:tabular-nums}
2912
- .dq-delta--up{color:var(--dsw-alias-state-warning-primary,#9a6700);background:rgba(191,135,0,.14)}
2913
- .dq-delta--down{color:var(--dsw-alias-state-success-primary,#1a7f37);background:rgba(45,164,78,.14)}
2914
- .dq-delta--flat,.dq-delta--new{color:var(--dsw-alias-label-tertiary,#59636e);background:rgba(120,130,150,.14);font-weight:500}
2943
+ @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}}
2944
+ .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}
2945
+ .dq-delta--up{color:var(--dq-text-warn);background:rgba(191,135,0,.14)}
2946
+ .dq-delta--down{color:var(--dq-text-success);background:rgba(45,164,78,.14)}
2947
+ .dq-delta--flat,.dq-delta--new{color:var(--dsw-alias-label-secondary,#59636e);background:rgba(120,130,150,.14);font-weight:500}
2915
2948
  .dq-delta-label{font-weight:400;opacity:.8}
2916
- .dq-pricing{margin-top:12px;border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08));padding-top:10px}
2949
+ .dq-pricing{margin-top:16px}
2917
2950
  .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}
2918
2951
  .dq-pricing-summary::-webkit-details-marker{display:none}
2919
- .dq-pricing-summary::before{content:"\u25B8";display:inline-block;font-size:10px;opacity:.7;transition:transform .15s ease}
2952
+ .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}
2920
2953
  .dq-pricing[open] .dq-pricing-summary::before{transform:rotate(90deg)}
2921
2954
  .dq-pricing-summary:hover{color:var(--dsw-alias-label-primary,#1f2328)}
2922
2955
  .dq-pricing-summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}
2923
- .dq-pricing-now{font-size:11px;font-weight:600;padding:1px 7px;border-radius:999px;color:var(--dsw-alias-label-tertiary,#59636e);background:rgba(120,130,150,.14)}
2924
- .dq-pricing-now--peak{color:var(--dsw-alias-state-warning-primary,#9a6700);background:rgba(191,135,0,.14)}
2925
- .dq-pricing-body{margin-top:10px;overflow-x:auto}
2956
+ .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)}
2957
+ .dq-pricing-now--peak{color:var(--dq-text-warn);background:rgba(191,135,0,.14)}
2958
+ .dq-pricing-body{margin-top:8px;overflow-x:auto}
2926
2959
  .dq-pricing-table{border-collapse:collapse;font-size:12px;font-variant-numeric:tabular-nums;min-width:100%}
2927
- .dq-pricing-table th{text-align:left;font-weight:500;color:var(--dsw-alias-label-tertiary,#59636e);padding:4px 12px 4px 0;white-space:nowrap;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}
2960
+ .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))}
2928
2961
  .dq-pricing-table td{padding:4px 12px 4px 0;color:var(--dsw-alias-label-primary,#1f2328);white-space:nowrap;vertical-align:top}
2962
+ .dq-pricing-table th:nth-child(n+3),.dq-pricing-table td:nth-child(n+3){text-align:right}
2963
+ .dq-pricing-table th:last-child,.dq-pricing-table td:last-child{padding-right:0}
2964
+ .dq-pricing-table tbody td:first-child{font-weight:500}
2929
2965
  .dq-pricing-table tbody tr+tr td{border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.05))}
2930
- .dq-pricing-foot{margin:8px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e)}
2931
- .dq-coverage{margin-top:16px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}
2932
- .dq-coverage-summary{display:flex;align-items:center;flex-wrap:wrap;gap:6px 9px;cursor:pointer;list-style:none;width:fit-content;max-width:100%;margin-left:-4px;padding:3px 4px;border-radius:6px;color:var(--dsw-alias-label-secondary,#59636e)}
2966
+ .dq-pricing-foot{margin:8px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e);text-wrap:pretty}
2967
+ .dq-coverage{margin-top:24px}
2968
+ .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)}
2933
2969
  .dq-coverage-summary::-webkit-details-marker{display:none}
2934
- .dq-coverage-summary::before{content:"\u25B8";display:inline-block;font-size:10px;opacity:.7;transition:transform .15s ease}
2970
+ .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}
2935
2971
  .dq-coverage[open] .dq-coverage-summary::before{transform:rotate(90deg)}
2936
2972
  .dq-coverage-summary:hover{color:var(--dsw-alias-label-primary,#1f2328)}
2937
2973
  .dq-coverage-summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}
2938
- .dq-coverage-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328)}
2939
- .dq-coverage-status{padding:1px 7px;border-radius:999px;background:rgba(45,164,78,.14);color:var(--dsw-alias-state-success-primary,#1a7f37);font-size:11px;font-weight:600}
2940
- .dq-coverage--warn .dq-coverage-status{background:rgba(191,135,0,.14);color:var(--dsw-alias-state-warning-primary,#9a6700)}
2974
+ .dq-coverage-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary,#59636e)}
2975
+ .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}
2976
+ .dq-coverage--warn .dq-coverage-status{background:rgba(191,135,0,.14);color:var(--dq-text-warn)}
2941
2977
  .dq-coverage-brief{font-size:12px;font-variant-numeric:tabular-nums}
2942
- .dq-coverage-body{margin-top:10px;padding:11px 12px;border-radius:10px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.06))}
2943
- .dq-coverage-metrics{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px 20px;margin:0}
2978
+ .dq-coverage-body{margin-top:8px;padding:12px;border-radius:10px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.06))}
2979
+ .dq-coverage-metrics{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px 24px;margin:0}
2944
2980
  .dq-coverage-metrics div{min-width:0}
2945
- .dq-coverage-metrics dt{font-size:11px;color:var(--dsw-alias-label-tertiary,#59636e)}
2946
- .dq-coverage-metrics dd{margin:3px 0 0;font-size:13px;font-weight:650;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums}
2947
- .dq-coverage-range,.dq-coverage-note,.dq-coverage-warning{margin:9px 0 0;font-size:12px;line-height:1.55;color:var(--dsw-alias-label-secondary,#59636e)}
2981
+ .dq-coverage-metrics dt{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}
2982
+ .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}
2983
+ .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}
2948
2984
  .dq-coverage-range{font-variant-numeric:tabular-nums}
2949
- .dq-coverage-warning{padding:8px 10px;border-radius:8px;background:rgba(191,135,0,.10);color:var(--dsw-alias-state-warning-primary,#7a5200)}
2985
+ .dq-coverage-warning{padding:8px 10px;border-radius:8px;background:rgba(191,135,0,.10);color:var(--dq-text-warn)}
2950
2986
  @media (max-width:620px){.dq-coverage-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}.dq-coverage-brief{flex-basis:100%;margin-left:19px}}
2951
2987
  .dq-peak-track{height:8px;border-radius:999px;background:var(--dsw-alias-state-success-primary,#2da44e);opacity:.85;overflow:hidden}
2952
2988
  .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)}
2953
- .dq-peak-legend{display:flex;flex-wrap:wrap;gap:6px 20px;margin-top:8px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}
2989
+ .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}
2954
2990
  .dq-peak-legend span{display:inline-flex;align-items:center;gap:6px}
2955
2991
  .dq-legend-swatch--peak{background:var(--dsw-alias-state-warning-primary,#bf8700)}
2956
2992
  .dq-legend-swatch--offpeak{background:var(--dsw-alias-state-success-primary,#2da44e);opacity:.85}
2957
- .dq-peak-figures{display:flex;flex-wrap:wrap;gap:12px 32px;margin-top:14px}
2958
- .dq-peak-delta{font-size:11px;font-weight:500;margin-left:8px;color:var(--dsw-alias-state-warning-primary,#9a6700)}
2959
- .dq-peak-delta--save{color:var(--dsw-alias-state-success-primary,#1a7f37)}
2960
- .dq-peak-foot{margin:10px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e)}
2993
+ .dq-peak-figures{display:flex;flex-wrap:wrap;gap:12px 32px;margin-top:16px}
2994
+ .dq-peak-delta{font-size:12px;font-weight:500;margin-left:8px;color:var(--dq-text-warn)}
2995
+ .dq-peak-delta--save{color:var(--dq-text-success)}
2996
+ .dq-peak-foot{margin:12px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e);text-wrap:pretty}
2961
2997
  .dq-cache-figures{display:flex;flex-wrap:wrap;gap:12px 32px;margin-bottom:12px}
2962
- .dq-muted-value{color:var(--dsw-alias-label-secondary,#59636e)!important;font-weight:550}
2963
- .dq-stat-value--warn{color:var(--dsw-alias-state-warning-primary,#9a6700)}
2998
+ @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}}
2999
+ .dq-muted-value{color:var(--dsw-alias-label-secondary,#59636e)!important;font-weight:500}
3000
+ .dq-stat-value--warn{color:var(--dq-text-warn)}
2964
3001
  .dq-cache-track{height:8px;border-radius:999px;background:var(--dsw-alias-state-warning-primary,#bf8700);overflow:hidden}
2965
3002
  .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)}
2966
- .dq-cache-legend{display:flex;flex-wrap:wrap;gap:6px 18px;margin-top:8px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}
3003
+ .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}
2967
3004
  .dq-cache-legend span{display:inline-flex;align-items:center;gap:6px}
2968
3005
  .dq-legend-swatch--hit{background:var(--dsw-alias-state-success-primary,#2da44e)}
2969
3006
  .dq-legend-swatch--miss{background:var(--dsw-alias-state-warning-primary,#bf8700)}
2970
- .dq-cache-foot{margin:10px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e)}
2971
- .dq-sessions{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:14px}
2972
- .dq-session{display:flex;flex-direction:column;gap:5px;min-width:0}
3007
+ .dq-cache-foot{margin:12px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e);text-wrap:pretty}
3008
+ .dq-sessions{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:16px}
3009
+ .dq-session{display:flex;flex-direction:column;gap:4px;min-width:0}
2973
3010
  .dq-session-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
2974
- .dq-session-title{font-size:13px;font-weight:550;color:var(--dsw-alias-label-primary,#1f2328);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
2975
- .dq-session-cost{font-size:14px;font-weight:650;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;flex:none}
3011
+ .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}
3012
+ .dq-session-cost{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;flex:none}
2976
3013
  .dq-session-track{height:6px;border-radius:999px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.12));overflow:hidden}
2977
3014
  .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)}
2978
3015
  .dq-session-sub{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums;line-height:1.5}
@@ -2980,8 +3017,10 @@ var css = `
2980
3017
  to lean on, unlike the .dq-session usage above), so it needs its own
2981
3018
  explicit spacing rather than falling back to the browser's implicit <p>
2982
3019
  margin \u2014 this project always declares spacing explicitly. */
2983
- p.dq-session-sub{margin:8px 0}
2984
- .dq-session-foot{margin:12px 0 0;font-size:12px;color:var(--dsw-alias-label-tertiary,#59636e)}
3020
+ .dq-session-meta{margin:12px 0 0;display:flex;flex-direction:column;gap:2px}
3021
+ .dq-session-meta p.dq-session-sub{margin:0}
3022
+ .dq-session-meta+.dq-rank{margin-top:16px}
3023
+ .dq-session-foot{margin:12px 0 0;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}
2985
3024
  /* \u8F6E\u6B21 46: each ranking row is now a <details> whose <summary> wraps the existing
2986
3025
  head/track/sub trio unchanged (in a flex-column body div) plus a leading chevron \u2014
2987
3026
  same disclosure grammar as .dq-pricing/.dq-coverage above (hidden native marker,
@@ -2994,60 +3033,63 @@ p.dq-session-sub{margin:8px 0}
2994
3033
  .dq-session-summary{display:flex;align-items:flex-start;gap:8px;border-radius:8px;padding:4px;margin:-4px}
2995
3034
  .dq-session-summary:hover{background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.05))}
2996
3035
  .dq-session-summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}
2997
- .dq-session-chevron{flex:none;width:12px;margin-top:4px;font-size:10px;line-height:1;color:var(--dsw-alias-label-tertiary,#59636e);transition:transform .15s ease}
3036
+ /* \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 */
3037
+ .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)}
2998
3038
  .dq-session-details[open] .dq-session-chevron{transform:rotate(90deg)}
2999
- .dq-session-summary-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}
3039
+ .dq-session-summary-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}
3000
3040
  /* Expanded body reuses the same shaded-inset language as .dq-coverage-body (10px
3001
3041
  gap from the summary, 11px/12px padding, 10px radius, bg-layer-2) rather than
3002
3042
  inventing a new "nested panel" look. SessionUsageCard renders inside unchanged. */
3003
- .dq-session-expand{margin-top:10px;padding:11px 12px;border-radius:10px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.06))}
3004
- .dq-rank{display:flex;flex-direction:column;gap:14px}
3005
- .dq-rank-row{display:flex;flex-direction:column;gap:5px;min-width:0}
3043
+ .dq-session-expand{margin-top:8px;padding:12px;border-radius:10px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.06))}
3044
+ .dq-rank{display:flex;flex-direction:column;gap:16px}
3045
+ .dq-rank-row{display:flex;flex-direction:column;gap:4px;min-width:0}
3006
3046
  .dq-rank-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
3007
- .dq-rank-name{display:inline-flex;align-items:center;gap:7px;font-size:13px;font-weight:550;color:var(--dsw-alias-label-primary,#1f2328);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
3008
- .dq-rank-cost{display:inline-flex;align-items:baseline;gap:8px;font-size:14px;font-weight:650;color:var(--dsw-alias-label-primary,#1f2328);font-variant-numeric:tabular-nums;flex:none}
3009
- .dq-rank-share{font-size:11px;font-weight:500;color:var(--dsw-alias-label-tertiary,#59636e);min-width:30px;text-align:right}
3047
+ .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}
3048
+ .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}
3049
+ .dq-rank-share{font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary,#59636e);min-width:30px;text-align:right}
3010
3050
  .dq-rank-track{height:6px;border-radius:999px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.12));overflow:hidden}
3011
3051
  .dq-rank-fill{height:100%;border-radius:999px;transition:width .35s cubic-bezier(.22,1,.36,1)}
3012
3052
  .dq-rank-sub{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums;line-height:1.5}
3013
- .dq-alert{display:flex;align-items:flex-start;gap:10px;padding:12px 14px;border-radius:10px;font-size:12px;line-height:1.6;color:var(--dsw-alias-state-warning-primary,#7a5200);background:rgba(191,135,0,.12);border:1px solid rgba(191,135,0,.35)}
3053
+ .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}
3014
3054
  .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}
3015
- .dq-alert strong{font-weight:650}
3055
+ .dq-alert strong{font-weight:600}
3016
3056
  .dq-alert-link{margin-left:8px;color:inherit;text-decoration:underline;text-underline-offset:2px;white-space:nowrap}
3017
- .dq-setting{display:flex;align-items:flex-start;gap:12px;margin-top:14px;padding-top:14px;border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}
3018
- .dq-setting-label{font-size:13px;color:var(--dsw-alias-label-primary,#1f2328);padding-top:6px;flex:none}
3057
+ .dq-setting{display:flex;align-items:flex-start;gap:16px;margin-top:24px}
3058
+ @media (max-width:620px){.dq-setting{flex-direction:column;gap:8px}.dq-setting-label{width:auto;padding-top:0}}
3059
+ .dq-setting-label{width:128px;font-size:13px;font-weight:500;color:var(--dsw-alias-label-primary,#1f2328);padding-top:6px;flex:none}
3019
3060
  .dq-setting-control{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-width:0}
3020
3061
  .dq-setting-hint{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);line-height:1.5}
3021
3062
  /* Page footer: the package name + version, injected at build time from
3022
3063
  package.json (see build.mjs) so it can never drift from the release. */
3023
- .dq-footer{margin:18px 0 0;font-size:12px;text-align:center;color:var(--dsw-alias-label-tertiary,#59636e)}
3064
+ .dq-footer{margin:16px 0 0;font-size:12px;text-align:center;color:var(--dsw-alias-label-tertiary,#59636e)}
3024
3065
  .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}
3025
3066
  .dq-number:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px;border-color:transparent}
3026
- .dq-links-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);margin:0 0 8px}
3067
+ .dq-links-title{font-size:13px;font-weight:500;color:var(--dsw-alias-label-primary,#1f2328);margin:0 0 12px}
3027
3068
  .dq-links{display:flex;flex-wrap:wrap;gap:8px}
3028
- .dq-link{display:inline-flex;align-items:center;gap:6px;padding:7px 12px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.12));border-radius:8px;background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-state-business-primary,#0969da);text-decoration:none;font-size:13px;font-weight:500;cursor:pointer}
3029
- .dq-link:hover{border-color:var(--dsw-alias-state-business-primary,#0969da);background:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.04))}
3069
+ .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}
3070
+ .dq-link::after{content:"\u2197";font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}
3071
+ .dq-link:hover{border-color:var(--dsw-alias-label-secondary,#59636e);background:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.04))}
3030
3072
  /* .dq-toggle is the first settings control after the links row (\u8F6E\u6B21 39 merge) \u2014 its own
3031
3073
  border-top separates the "\u5FEB\u6377\u5165\u53E3" links (originally the standalone \u5B98\u65B9\u5E73\u53F0 card, renamed
3032
3074
  in \u8F6E\u6B21 39 fix-round-1 to read as part of \u8BBE\u7F6E's own navigation area) from \u8BBE\u7F6E controls
3033
3075
  inside the merged card, same 14px/14px/border-l1 recipe as .dq-setting so the two
3034
3076
  sub-sections read at equal weight. */
3035
- .dq-toggle{display:flex;align-items:center;gap:10px;cursor:pointer;font-size:13px;margin-top:14px;padding-top:14px;border-top:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08))}
3077
+ .dq-toggle{display:flex;align-items:center;gap:10px;cursor:pointer;font-size:13px;font-weight:500;margin-top:24px}
3036
3078
  .dq-toggle input{width:16px;height:16px;accent-color:var(--dsw-alias-state-business-primary,#0969da);cursor:pointer}
3037
- .dq-toggle-hint{margin:5px 0 0 26px;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-secondary,#59636e)}
3038
- .dq-widget-tabs{align-items:flex-start;flex-direction:column;gap:7px}
3039
- .dq-widget-tab-list{display:flex;align-items:center;flex-wrap:wrap;gap:6px 14px}
3040
- .dq-widget-tab{display:inline-flex;align-items:center;gap:7px;min-height:28px;color:var(--dsw-alias-label-primary,#1f2328);font-size:12px;cursor:pointer}
3079
+ .dq-toggle-hint{margin:4px 0 0 26px;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-secondary,#59636e)}
3080
+ .dq-widget-tabs{align-items:flex-start;flex-direction:column;gap:8px}
3081
+ .dq-widget-tab-list{display:flex;align-items:center;flex-wrap:wrap;gap:4px 16px}
3082
+ .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}
3041
3083
  .dq-widget-tab input{width:14px;height:14px;margin:0;accent-color:var(--dsw-alias-state-business-primary,#0969da);cursor:pointer;flex:none}
3042
3084
  .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}
3043
3085
  .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}
3044
- .dq-usage-totals{display:flex;flex-wrap:wrap;gap:12px 24px;margin-bottom:16px}
3086
+ .dq-usage-totals{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px 24px;margin-bottom:20px}
3045
3087
  /* value itself (number+unit, e.g. "9999.9\u4E07") must never break across lines inside its own column \u2014
3046
3088
  nowrap+ellipsis is a defensive floor for all widths; the actual fix for the realistic 320px 2-col
3047
3089
  case is the font-size drop below, which keeps every measured stress value comfortably under the
3048
3090
  83px column width without ever hitting the ellipsis fallback (see round 38 PROGRESS entry) */
3049
3091
  .dq-usage-totals .dq-stat-value{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
3050
- .dq-vision-share{display:inline-block;margin-left:6px;font-size:11px;font-weight:550;color:var(--dsw-alias-label-tertiary,#59636e)}
3092
+ .dq-vision-share{display:inline-block;margin-left:6px;font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary,#59636e)}
3051
3093
  .dq-vision-sessions{margin-top:12px;display:flex;flex-direction:column;gap:8px;min-width:0}
3052
3094
  /* The vision card's session rows reuse .dq-session-head, but \u2014 unlike the
3053
3095
  ranking card's rows \u2014 they sit directly under .dq-session with no
@@ -3058,13 +3100,13 @@ p.dq-session-sub{margin:8px 0}
3058
3100
  .dq-vision-sessions .dq-session-head{min-width:0}
3059
3101
  .dq-vision-sessions .dq-session-title{flex:1 1 auto;min-width:0}
3060
3102
  @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}}
3061
- .dq-chart-peak{margin-left:10px;font-size:11px;font-weight:400;color:var(--dsw-alias-label-tertiary,#59636e);font-variant-numeric:tabular-nums}
3062
- .dq-chart-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary,#59636e);margin:16px 0 8px}
3103
+ .dq-chart-peak{margin-left:8px;font-size:12px;font-weight:400;color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums}
3104
+ .dq-chart-title{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary,#1f2328);margin:16px 0 8px}
3063
3105
  .dq-chart-title:first-of-type{margin-top:0}
3064
- .dq-chart-block-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:16px 0 8px}
3106
+ .dq-chart-block-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:0 0 12px}
3065
3107
  .dq-chart-block-head .dq-chart-title{margin:0}
3066
3108
  .dq-chart-controls{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex:none;flex-wrap:wrap}
3067
- @media (max-width:620px){.dq-chart-block-head{align-items:flex-start;flex-direction:column}.dq-chart-controls{width:100%}}
3109
+ @media (max-width:620px){.dq-chart-block-head{align-items:flex-start;flex-direction:column}.dq-chart-controls{width:100%;justify-content:flex-start}}
3068
3110
  .dq-model-picker{position:relative}
3069
3111
  .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}
3070
3112
  .dq-model-btn:hover{border-color:var(--dsw-alias-state-business-primary,#0969da);color:var(--dsw-alias-state-business-primary,#0969da)}
@@ -3075,13 +3117,13 @@ p.dq-session-sub{margin:8px 0}
3075
3117
  .dq-model-item input{width:14px;height:14px;accent-color:var(--dsw-alias-state-business-primary,#0969da);cursor:pointer;flex:none}
3076
3118
  .dq-model-item span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
3077
3119
  .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}
3078
- .dq-model-tag{color:var(--dsw-alias-label-tertiary,#59636e);font-size:11px;flex:none}
3120
+ .dq-model-tag{color:var(--dsw-alias-label-secondary,#59636e);font-size:12px;flex:none}
3079
3121
  .dq-bar-group{display:flex;flex-direction:column-reverse;width:100%}
3080
3122
  .dq-bar-group .dq-bar{flex:0 0 auto;width:100%;border-radius:0}
3081
3123
  .dq-bar-group .dq-bar:first-child{border-radius:0 0 2px 2px}
3082
3124
  .dq-bar-group .dq-bar:last-child{border-radius:2px 2px 0 0}
3083
3125
  .dq-bar-group .dq-bar:not(:last-child){box-shadow:inset 0 1px 0 rgba(0,0,0,.18)}
3084
- .dq-legend{display:flex;flex-wrap:wrap;gap:6px 14px;margin-top:8px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}
3126
+ .dq-legend{display:flex;flex-wrap:wrap;gap:4px 16px;margin-top:8px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e)}
3085
3127
  .dq-legend-item{display:inline-flex;align-items:center;gap:6px}
3086
3128
  .dq-legend-swatch{width:10px;height:10px;border-radius:3px;flex:none}
3087
3129
  .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}
@@ -3090,9 +3132,9 @@ p.dq-session-sub{margin:8px 0}
3090
3132
  .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)}
3091
3133
  .dq-chart-wrap{position:relative}
3092
3134
  .dq-bars-scroll{overflow-x:auto;overflow-y:hidden;padding-bottom:2px}
3093
- .dq-tip{position:absolute;transform:translate(-50%,14px);z-index:40;pointer-events:none;background:var(--dsw-alias-bg-inverse,#1f2328);color:var(--dsw-alias-label-inverse,#fff);border-radius:8px;padding:7px 10px;font-size:12px;line-height:1.55;white-space:nowrap;box-shadow:0 6px 20px rgba(0,0,0,.28);font-variant-numeric:tabular-nums}
3135
+ .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}
3094
3136
  .dq-tip--above{transform:translate(-50%,calc(-100% - 8px))}
3095
- .dq-tip-head{font-weight:650;margin-bottom:2px}
3137
+ .dq-tip-head{font-weight:600;margin-bottom:2px}
3096
3138
  .dq-tip-row{opacity:.85}
3097
3139
  .dq-bars{display:flex;align-items:flex-end;gap:2px;width:100%}
3098
3140
  .dq-bar-col{flex:1 1 0;min-width:0;display:flex;flex-direction:column;justify-content:flex-end;align-items:stretch}
@@ -3108,7 +3150,7 @@ p.dq-session-sub{margin:8px 0}
3108
3150
  .dq-heat-cell:not(.dq-heat-cell--pad):hover{outline:1.5px solid var(--dsw-alias-label-primary,#1f2328);outline-offset:1px}
3109
3151
  .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}
3110
3152
  .dq-heat-cell--pinned{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px;position:relative;z-index:2}
3111
- .dq-bar-label{font-size:9px;color:var(--dsw-alias-label-tertiary,#59636e);text-align:center;margin-top:3px;overflow:visible;white-space:nowrap}
3153
+ .dq-bar-label{font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);text-align:center;margin-top:4px;overflow:visible;white-space:nowrap}
3112
3154
  .dq-heat{display:flex;flex-direction:column;gap:8px;max-width:100%}
3113
3155
  .dq-heat-scroll{overflow-x:auto;padding-bottom:2px}
3114
3156
  .dq-heatmap{display:flex;gap:3px}
@@ -3116,16 +3158,16 @@ p.dq-session-sub{margin:8px 0}
3116
3158
  .dq-heat-cell{width:100%;aspect-ratio:1/1;border-radius:3px;flex:none}
3117
3159
  .dq-heat-cell--pad{background:transparent}
3118
3160
  .dq-heat-months{display:flex;gap:3px;margin-top:4px}
3119
- .dq-heat-month{flex:1 1 0;min-width:6px;font-size:10px;line-height:14px;color:var(--dsw-alias-label-tertiary,#59636e);white-space:nowrap;overflow:visible}
3161
+ .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}
3120
3162
  .dq-heat-key{width:12px;height:12px;border-radius:2px;flex:none}
3121
- .dq-heat-scale{display:flex;align-items:center;gap:3px;font-size:10px;color:var(--dsw-alias-label-tertiary,#59636e);align-self:flex-end}
3163
+ .dq-heat-scale{display:flex;align-items:center;gap:3px;font-size:12px;color:var(--dsw-alias-label-secondary,#59636e);align-self:flex-end}
3122
3164
  .dq-heat-scale>span:first-child{margin-right:2px}
3123
3165
  .dq-heat-scale>span:last-child{margin-left:2px}
3124
3166
  .dq-muted{color:var(--dsw-alias-label-secondary,#59636e)}
3125
3167
  .dq-error{color:var(--dsw-alias-state-error-primary,#cf222e)}
3126
- .dq-warn{color:var(--dsw-alias-state-warning-primary,#9a6700)}
3127
- .dq-crash{margin:10px 0 14px;padding:10px 12px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.10));border-radius:8px;font-size:12px;line-height:1.5;color:var(--dsw-alias-state-error-primary,#cf222e);white-space:pre-wrap;word-break:break-word;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
3128
- .dq-empty{color:var(--dsw-alias-label-secondary,#59636e);font-size:12px;line-height:1.6;padding:6px 0}
3168
+ .dq-warn{color:var(--dq-text-warn)}
3169
+ .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)}
3170
+ .dq-empty{color:var(--dsw-alias-label-secondary,#59636e);font-size:12px;line-height:1.6;padding:6px 0;text-wrap:pretty}
3129
3171
  /* Error-state modifier for a card body that has nothing else to show (mirrors the .dq-stat-value--ok/
3130
3172
  --bad/--warn pattern: same layout as .dq-empty, declared after it so this color wins at equal
3131
3173
  specificity). Used by the current-session card when its own fetch failed and there is no prior
@@ -3134,17 +3176,17 @@ p.dq-session-sub{margin:8px 0}
3134
3176
  .dq-empty--error{color:var(--dsw-alias-state-error-primary,#cf222e)}
3135
3177
  .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}
3136
3178
  .dq-stat .dq-skel+.dq-skel{margin-top:6px}
3137
- .dq-skel-bars{display:flex;align-items:flex-end;gap:2px;width:100%;height:120px;margin-top:10px}
3179
+ .dq-skel-bars{display:flex;align-items:flex-end;gap:2px;width:100%;height:160px;margin-top:12px}
3138
3180
  .dq-skel-bar{flex:1 1 0;min-width:0;border-radius:2px 2px 0 0}
3139
3181
  @keyframes dq-shimmer{0%{background-position:100% 50%}100%{background-position:0 50%}}
3140
- .dq-status-row{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:20px}
3182
+ .dq-status-row{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:20px;padding:0 20px;margin-bottom:-12px}
3141
3183
  .dq-status-messages{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-width:0}
3142
- .dq-status-row .dq-warn,.dq-status-row .dq-error{font-size:12px;line-height:1.45}
3184
+ .dq-status-row .dq-warn,.dq-status-row .dq-error{font-size:12px;line-height:1.5}
3143
3185
  .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}
3144
3186
  .dq-sync-dot{width:7px;height:7px;border-radius:50%;flex:none;background:var(--dsw-alias-label-tertiary,#8c959f)}
3145
3187
  .dq-sync--fresh .dq-sync-dot{background:var(--dsw-alias-state-success-primary,#2da44e)}
3146
3188
  .dq-sync--syncing .dq-sync-dot{background:var(--dsw-alias-state-business-primary,#4176e6);animation:dq-sync-pulse 1.2s ease-in-out infinite}
3147
- .dq-sync--fallback{color:var(--dsw-alias-state-warning-primary,#9a6700)}
3189
+ .dq-sync--fallback{color:var(--dq-text-warn)}
3148
3190
  .dq-sync--fallback .dq-sync-dot{background:var(--dsw-alias-state-warning-primary,#bf8700)}
3149
3191
  .dq-sync--error{color:var(--dsw-alias-state-error-primary,#cf222e)}
3150
3192
  .dq-sync--error .dq-sync-dot{background:var(--dsw-alias-state-error-primary,#cf222e)}
@@ -3167,6 +3209,14 @@ p.dq-session-sub{margin:8px 0}
3167
3209
 
3168
3210
  // src/client/widget.tsx
3169
3211
  var import_react6 = require("react");
3212
+
3213
+ // src/client/sessions.ts
3214
+ function currentSessionIdOf(state) {
3215
+ const retained = Object.values(state.byId ?? {}).find((row) => (row?.retainedBy?.mainView ?? 0) > 0);
3216
+ return retained?.id ?? state.current;
3217
+ }
3218
+
3219
+ // src/client/widget.tsx
3170
3220
  var import_jsx_runtime6 = require("react/jsx-runtime");
3171
3221
  var MARGIN = 16;
3172
3222
  var CORNER_KEY = "widget.corner";
@@ -3217,7 +3267,7 @@ function cornerPos(corner, node, bounds) {
3217
3267
  }
3218
3268
  function QuotaWidget(props) {
3219
3269
  const { t } = useI18n();
3220
- const sessionId = props.useSessions((state) => state.current);
3270
+ const sessionId = props.useSessions(currentSessionIdOf);
3221
3271
  const [visible, setVisible] = (0, import_react6.useState)(widgetVisibleStore.get());
3222
3272
  (0, import_react6.useEffect)(() => widgetVisibleStore.subscribe(() => setVisible(widgetVisibleStore.get())), []);
3223
3273
  const [quotaViewActive2, setQuotaViewActive] = (0, import_react6.useState)(quotaViewActiveStore.get());
@@ -3433,7 +3483,7 @@ function QuotaWidget(props) {
3433
3483
  const sessionCostRow = sessionUsage === null ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-quota-row", title: t("widget.sessionCostTitle"), children: [
3434
3484
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-quota-label", children: t("widget.sessionCost") }),
3435
3485
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dsh-quota-value", children: [
3436
- "\xA5 ",
3486
+ "\xA5",
3437
3487
  fmtTurnCost(sessionUsage.cost)
3438
3488
  ] })
3439
3489
  ] });
@@ -3459,7 +3509,7 @@ function QuotaWidget(props) {
3459
3509
  usage.data !== null && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-quota-row", title: t("widget.todayCostTitle", { age: usageAgeText }), children: [
3460
3510
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-quota-label", children: t("widget.todayCost") }),
3461
3511
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dsh-quota-value", children: [
3462
- "\xA5 ",
3512
+ "\xA5",
3463
3513
  fmt(usage.data.summary.today.cost)
3464
3514
  ] })
3465
3515
  ] }),
@@ -3575,6 +3625,7 @@ function apply(ctx) {
3575
3625
  const t = ctx.locale.bind(NS);
3576
3626
  const views = conversationViewsSource(ctx.slots);
3577
3627
  if (typeof document !== "undefined") {
3628
+ document.querySelectorAll('style[data-plugin="dsh-usage-dashboard"]').forEach((node) => node.remove());
3578
3629
  const tag = document.createElement("style");
3579
3630
  tag.dataset.plugin = "dsh-usage-dashboard";
3580
3631
  tag.textContent = css;