march-cli 0.1.35 → 0.1.37

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.
Files changed (63) hide show
  1. package/package.json +1 -1
  2. package/src/agent/code-search/cache.mjs +133 -0
  3. package/src/agent/code-search/chunk-rules.mjs +107 -0
  4. package/src/agent/code-search/chunker.mjs +125 -0
  5. package/src/agent/code-search/engine.mjs +109 -0
  6. package/src/agent/code-search/languages.mjs +25 -0
  7. package/src/agent/code-search/parser-pool.mjs +29 -0
  8. package/src/agent/code-search/rerank.mjs +43 -0
  9. package/src/agent/code-search/retrieval/bm25.mjs +47 -0
  10. package/src/agent/code-search/retrieval/fusion.mjs +18 -0
  11. package/src/agent/code-search/retrieval/model2vec.mjs +96 -0
  12. package/src/agent/code-search/retrieval/safetensors.mjs +49 -0
  13. package/src/agent/code-search/retrieval/vector.mjs +107 -0
  14. package/src/agent/code-search/retrieval/wordpiece.mjs +82 -0
  15. package/src/agent/code-search/scanner.mjs +84 -0
  16. package/src/agent/code-search/tokenize.mjs +16 -0
  17. package/src/agent/code-search/tool.mjs +75 -0
  18. package/src/agent/runner/provider-quota-runtime.mjs +38 -0
  19. package/src/agent/runner.mjs +14 -10
  20. package/src/agent/runtime/remote-runner-client.mjs +2 -0
  21. package/src/agent/runtime/runner-ipc-target.mjs +7 -0
  22. package/src/agent/runtime/runner-process-client.mjs +5 -0
  23. package/src/agent/runtime/runner-process-factory.mjs +5 -0
  24. package/src/agent/runtime/runner-runtime-host.mjs +2 -0
  25. package/src/agent/runtime/state/runner-state.mjs +1 -0
  26. package/src/agent/runtime/ui-event-bridge.mjs +2 -0
  27. package/src/agent/session/session-options.mjs +2 -1
  28. package/src/agent/tools.mjs +7 -1
  29. package/src/agent/turn/turn-events.mjs +41 -0
  30. package/src/agent/turn/turn-runner.mjs +5 -2
  31. package/src/cli/commands/registry/slash-command-registry.mjs +10 -7
  32. package/src/cli/commands/status-command.mjs +61 -35
  33. package/src/cli/input/history-store.mjs +65 -3
  34. package/src/cli/repl-loop.mjs +8 -6
  35. package/src/cli/startup/app-runtime.mjs +5 -29
  36. package/src/cli/startup/create-runtime-runner.mjs +4 -46
  37. package/src/cli/tui/input/history-navigation-controller.mjs +56 -0
  38. package/src/cli/turn/turn-input-preparer.mjs +0 -1
  39. package/src/cli/ui.mjs +9 -0
  40. package/src/context/engine.mjs +4 -2
  41. package/src/context/system-core/base.md +9 -1
  42. package/src/history/runner.mjs +11 -0
  43. package/src/history/store.mjs +129 -0
  44. package/src/history/tool.mjs +39 -0
  45. package/src/lsp/client.mjs +12 -5
  46. package/src/lsp/service.mjs +15 -3
  47. package/src/main.mjs +1 -2
  48. package/src/provider/quota/codex.mjs +278 -0
  49. package/src/provider/quota/index.mjs +46 -0
  50. package/src/provider/quota/transport-observer.mjs +99 -0
  51. package/src/web-ui/command.mjs +2 -2
  52. package/src/web-ui/runtime-host.mjs +7 -23
  53. package/src/web-ui/server.mjs +1 -0
  54. package/src/web-ui/session-manager.mjs +4 -2
  55. package/src/web-ui/src/components/AppShell.tsx +1 -0
  56. package/src/web-ui/src/components/RightSidebar.tsx +47 -2
  57. package/src/web-ui/src/model.ts +20 -0
  58. package/src/web-ui/src/runtime/client.ts +8 -1
  59. package/src/web-ui/src/runtime/useWebRuntime.ts +13 -1
  60. package/src/web-ui/src/styles/shell.css +10 -0
  61. package/src/web-ui/dist/assets/index-BUmhnID4.css +0 -1
  62. package/src/web-ui/dist/assets/index-CtuqTjcB.js +0 -1845
  63. package/src/web-ui/dist/index.html +0 -13
@@ -43,6 +43,25 @@ export type ActivityEvent = {
43
43
  time: string;
44
44
  };
45
45
 
46
+ export type ProviderQuotaSnapshot = {
47
+ providerId: string;
48
+ modelId?: string | null;
49
+ label: string;
50
+ planType?: string | null;
51
+ capturedAt: string;
52
+ limits: Array<{
53
+ id: string;
54
+ name: string;
55
+ windows: Array<{
56
+ id: string;
57
+ label: string;
58
+ usedPercent: number;
59
+ remainingPercent: number;
60
+ resetsAt?: string | null;
61
+ }>;
62
+ }>;
63
+ };
64
+
46
65
  export type ComposerState = {
47
66
  mode: string;
48
67
  placeholder: string;
@@ -57,6 +76,7 @@ export type WebUiModel = {
57
76
  events: MarchTimelineEvent[];
58
77
  };
59
78
  sessions: SessionSummary[];
79
+ providerQuota?: ProviderQuotaSnapshot | null;
60
80
  activity: ActivityEvent[];
61
81
  composer: ComposerState;
62
82
  };
@@ -1,4 +1,4 @@
1
- import type { SessionSummary, WebUiModel } from "../model";
1
+ import type { ProviderQuotaSnapshot, SessionSummary, WebUiModel } from "../model";
2
2
 
3
3
  export type RuntimeUiEvent =
4
4
  | { type: "web_user_message"; text: string }
@@ -13,6 +13,7 @@ export type RuntimeUiEvent =
13
13
  | { type: "tool_end"; name: string; isError?: boolean; result?: unknown }
14
14
  | { type: "edit_diff"; path: string; diffLines?: Array<{ type?: string; text?: string }> }
15
15
  | { type: "permission_request"; toolName: string; category?: string; params?: unknown }
16
+ | { type: "provider_quota_snapshot"; snapshot: ProviderQuotaSnapshot | null }
16
17
  | { type: "status"; text: string }
17
18
  | { type: "retry_start"; errorMessage?: string }
18
19
  | { type: "retry_end"; success?: boolean; finalError?: string };
@@ -47,6 +48,12 @@ export async function fetchFsList(path: string): Promise<FsEntry[]> {
47
48
  return (await response.json()).entries;
48
49
  }
49
50
 
51
+ export async function fetchProviderQuota(sessionId: string): Promise<ProviderQuotaSnapshot | null> {
52
+ const response = await fetch(apiPath("/api/provider-quota", { sessionId }));
53
+ if (!response.ok) throw new Error(await response.text());
54
+ return (await response.json()).snapshot ?? null;
55
+ }
56
+
50
57
  export async function submitRuntimeTurn(sessionId: string, prompt: string) {
51
58
  const response = await fetch("/api/turn", {
52
59
  method: "POST",
@@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from "react";
2
2
  import { mockWebUiModel } from "../mockData";
3
3
  import type { MarchTimelineEvent, WebUiModel } from "../model";
4
4
  import { applyRuntimeEvent } from "./runtimeTimeline";
5
- import { connectRuntimeEvents, createRuntimeSession, fetchFsList, fetchFsRoots, fetchRuntimeSnapshot, submitRuntimeTurn } from "./client";
5
+ import { connectRuntimeEvents, createRuntimeSession, fetchFsList, fetchFsRoots, fetchProviderQuota, fetchRuntimeSnapshot, submitRuntimeTurn } from "./client";
6
6
  import type { FsEntry } from "./client";
7
7
 
8
8
  export type WebRuntimeState = {
@@ -48,6 +48,12 @@ export function useWebRuntime(): WebRuntimeState {
48
48
  activeSessionId,
49
49
  (event) => {
50
50
  setConnected(true);
51
+ if (event.type === "provider_quota_snapshot") {
52
+ setModel((current) => current.activeSessionId === activeSessionId
53
+ ? { ...current, providerQuota: event.snapshot }
54
+ : current);
55
+ return;
56
+ }
51
57
  setModel((current) => {
52
58
  const next = updateTimelineEvents(current, (events) => applyRuntimeEvent(events, event));
53
59
  rememberTimeline(next, timelineCache.current);
@@ -56,6 +62,7 @@ export function useWebRuntime(): WebRuntimeState {
56
62
  },
57
63
  () => setConnected(false),
58
64
  );
65
+ refreshProviderQuota(activeSessionId).catch(() => undefined);
59
66
  return disconnect;
60
67
  }, [activeSessionId]);
61
68
 
@@ -79,6 +86,11 @@ export function useWebRuntime(): WebRuntimeState {
79
86
  }
80
87
  }
81
88
 
89
+ async function refreshProviderQuota(sessionId: string) {
90
+ const providerQuota = await fetchProviderQuota(sessionId);
91
+ setModel((current) => current.activeSessionId === sessionId ? { ...current, providerQuota } : current);
92
+ }
93
+
82
94
  async function browseRoots() {
83
95
  setFsPath(null);
84
96
  setFsEntries(await fetchFsRoots());
@@ -110,6 +110,16 @@
110
110
  .fs-entry-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px; }
111
111
  .fs-entry-row button, .fs-row { min-height: 28px; padding: 0 7px; text-align: left; }
112
112
  .fs-entry-row button:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--color-text-primary); }
113
+ .provider-quota { margin-top: 12px; border-top: 1px solid var(--color-border-subtle); padding-top: 12px; display: grid; gap: 9px; }
114
+ .provider-quota-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 12px; }
115
+ .provider-quota-header span { color: var(--color-text-primary); font-weight: var(--font-weight-ui-medium); }
116
+ .provider-quota-header time, .quota-row em { color: var(--color-text-muted); font-style: normal; }
117
+ .quota-row { display: grid; gap: 5px; font-size: 12px; }
118
+ .quota-row-main { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
119
+ .quota-row-main span { color: var(--color-text-primary); }
120
+ .quota-row-main strong { color: var(--color-accent); font-size: 12px; }
121
+ .quota-bar { height: 6px; overflow: hidden; border-radius: 999px; background: var(--color-bg-surface); box-shadow: inset 0 0 0 1px var(--color-border-subtle); }
122
+ .quota-bar span { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--color-accent), color-mix(in srgb, var(--color-accent) 72%, white)); }
113
123
  .session-row, .activity-row { width: 100%; min-height: 34px; border: 0; border-radius: var(--radius-control); padding: 7px 8px; background: transparent; color: var(--color-text-primary); display: flex; align-items: center; justify-content: space-between; gap: 8px; text-align: left; font-size: 13px; }
114
124
  .session-row.active { background: var(--color-accent-soft); color: var(--color-accent); font-weight: var(--font-weight-ui-medium); }
115
125
  .session-row time, .activity-row time { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--color-text-muted); font-size: 12px; }
@@ -1 +0,0 @@
1
- @layer theme.palette{:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;--font-sans:"Segoe UI Variable Text", "Segoe UI Variable", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, DengXian, "等线", "Microsoft YaHei UI", sans-serif;--font-mono:ui-monospace, "SFMono-Regular", "Cascadia Code", "JetBrains Mono", "Fira Code", Consolas, "Liberation Mono", Menlo, monospace;--font-weight-ui-normal:500;--font-weight-content-normal:600;--font-weight-ui-medium:600;--font-weight-ui-strong:700;--palette-white:#fff;--palette-slate-50:#f8fafc;--palette-slate-100:#f1f5f9;--palette-slate-200:#e2e8f0;--palette-slate-400:#94a3b8;--palette-slate-500:#64748b;--palette-slate-700:#334155;--palette-slate-900:#0f172a;--palette-slate-950:#020617;--palette-blue-400:#60a5fa;--palette-blue-600:#2563eb;--palette-green-700:#15803d;--palette-amber-600:#d97706;--palette-red-600:#dc2626}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}}}@layer theme.semantic{:root{--color-bg-page:#f3f4f6;--color-bg-surface:var(--palette-white);--color-bg-sidebar:#ffffffbd;--color-bg-subtle:var(--palette-slate-50);--color-text-primary:var(--palette-slate-900);--color-text-muted:var(--palette-slate-500);--color-text-inverse:var(--palette-white);--color-border-subtle:#0f172a14;--color-border-strong:#0f172a24;--color-accent:var(--palette-blue-600);--color-accent-soft:#2563eb14;--color-success:var(--palette-green-700);--color-warning:var(--palette-amber-600);--color-danger:var(--palette-red-600);--color-hover:#0000000d;--color-shadow-drawer:#00000026;--color-scrim:#0000004d}@media (prefers-color-scheme:dark){:root{--color-bg-page:var(--palette-slate-900);--color-bg-surface:var(--palette-slate-950);--color-bg-sidebar:var(--palette-slate-900);--color-bg-subtle:var(--palette-slate-900);--color-text-primary:var(--palette-slate-50);--color-text-muted:var(--palette-slate-400);--color-border-subtle:#94a3b81f;--color-border-strong:#94a3b833;--color-accent:var(--palette-blue-400);--color-accent-soft:#60a5fa24;--color-hover:#94a3b814}}}@layer theme.component{:root{--shell-left-width:260px;--shell-right-width:280px;--shell-mobile-panel-width:75vw;--header-height:36px;--composer-min-height:46px;--radius-row:6px;--radius-control:8px;--radius-composer:12px;--space-panel:8px;--tree-indent:16px}}@layer base{*{box-sizing:border-box}html,body,#root{height:100%;margin:0;overflow:hidden}body{background:var(--color-bg-page);color:var(--color-text-primary);font-family:var(--font-sans);font-weight:var(--font-weight-ui-normal);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility}button,textarea{font:inherit}button{cursor:pointer}}@layer components{.app-shell{grid-template-columns:var(--shell-left-width) minmax(0, 1fr) var(--shell-right-width);background:var(--color-bg-page);height:100dvh;color:var(--color-text-primary);isolation:isolate;grid-template-rows:minmax(0,1fr) auto;grid-template-areas:"sidebar main right""sidebar footer right";display:grid;overflow:hidden}.panel{background:var(--color-bg-sidebar);min-height:0;overflow:hidden}.left-panel{border-right:1px solid var(--color-border-subtle);grid-area:sidebar}.right-panel{border-left:1px solid var(--color-border-subtle);flex-direction:column;grid-area:right;display:flex}.projects-header,.right-header,.main-header{height:var(--header-height);border-bottom:1px solid var(--color-border-subtle);background:var(--color-bg-sidebar);color:var(--color-text-muted);font-size:11px;font-weight:var(--font-weight-ui-medium);text-transform:uppercase;justify-content:space-between;align-items:center;padding:0 16px;display:flex}.projects-header h3{font:inherit;letter-spacing:.5px;margin:0}.menu-button{border-radius:var(--radius-control);width:28px;height:28px;color:var(--color-text-muted);background:0 0;border:0;justify-content:center;align-items:center;gap:3px;display:inline-flex}.menu-button span{background:currentColor;border-radius:999px;width:3.6px;height:3.6px}.menu-button:hover,.header-button:hover,.session-row:hover,.activity-row:hover{background:var(--color-hover)}.projects-body{height:calc(100% - var(--header-height));padding:var(--space-panel) 0;overflow:hidden}.project-tree-host{--trees-accent-override:var(--color-accent);--trees-bg-override:var(--color-bg-sidebar);--trees-bg-muted-override:var(--color-hover);--trees-border-color-override:var(--color-border-subtle);--trees-fg-override:var(--color-text-primary);--trees-fg-muted-override:var(--color-text-muted);--trees-selected-bg-override:var(--color-accent-soft);--trees-selected-fg-override:var(--color-accent);--trees-font-family-override:var(--font-sans);--trees-font-size-override:13px;--trees-border-radius-override:var(--radius-row);--trees-item-height:30px;--trees-item-padding-x-override:8px;--trees-item-margin-x-override:8px;--trees-item-row-gap-override:4px;--trees-level-gap-override:var(--tree-indent);--trees-padding-inline-override:0px;--trees-scrollbar-gutter-override:6px;height:100%}.timeline{background:var(--color-bg-surface);flex-direction:column;grid-area:main;min-width:0;min-height:0;display:flex;overflow:hidden}.main-header{background:var(--color-bg-surface)}.runtime-pill{color:var(--color-text-muted);background:var(--color-bg-subtle);border-radius:999px;padding:2px 7px;font-size:12px}.runtime-pill.connected{color:var(--color-accent);background:var(--color-accent-soft)}.timeline-scroll{flex:1;min-height:0;padding:16px 18px 24px;overflow:auto}.session-title{align-items:baseline;gap:8px;margin:0 0 14px 40px;display:flex}.session-title h1{font-size:17px;font-weight:var(--font-weight-ui-strong);letter-spacing:-.01em;margin:0}.session-title span{color:var(--color-text-muted);font-size:12px}.timeline-list{max-width:920px;margin:0 auto}.message-row{grid-template-columns:30px minmax(0,1fr);gap:10px;padding:10px 0;display:grid}.message-row+.message-row{border-top:1px solid var(--color-border-subtle)}.agent-dot{border-radius:var(--radius-control);background:var(--palette-slate-700);width:28px;height:28px;color:var(--color-text-inverse);place-items:center;font-size:12px;font-weight:800;display:grid}.agent-dot.march{background:var(--color-accent)}.message-body{min-width:0;color:var(--color-text-primary);font-size:14px;font-weight:var(--font-weight-content-normal);padding-top:3px;line-height:1.55}.message-body p{margin:0}.message-body time{color:var(--color-text-muted);margin-top:4px;font-size:11px;display:block}.timeline-aux{border:1px solid var(--color-border-subtle);border-radius:var(--radius-control);background:var(--color-bg-subtle);padding:7px 9px}.timeline-aux summary,.aux-title{align-items:center;gap:8px;min-height:20px;display:flex}.timeline-aux summary{cursor:pointer}.timeline-aux span,.timeline-aux em{color:var(--color-text-muted);font-size:12px;font-style:normal}.timeline-aux strong{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:13px;font-weight:var(--font-weight-ui-medium);overflow:hidden}.timeline-aux p{color:var(--color-text-muted);margin:7px 0 0;font-size:13px}.tool-block span,.diff-inline,.terminal-block pre{font-family:var(--font-mono)}.diff-inline{border-left:2px solid var(--color-border-strong);margin-top:7px;padding-left:10px;font-size:13px}.diff-line{padding:2px 0}.diff-line.add{color:var(--color-success)}.diff-line.remove,.error-block strong{color:var(--color-danger)}.diff-line.keep{color:var(--color-text-muted)}.terminal-block pre{color:var(--color-text-muted);white-space:pre-wrap;margin:7px 0 0;font-size:12px}.permission-block.pending strong{color:var(--color-warning)}.permission-block.approved strong{color:var(--color-success)}.right-body{flex:1;min-height:0;padding:12px;overflow:auto}.workspace-picker{gap:7px;padding-bottom:10px;display:grid}.workspace-picker label{color:var(--color-text-muted);font-size:11px;font-weight:var(--font-weight-ui-medium);text-transform:uppercase}.workspace-input-row{grid-template-columns:minmax(0,1fr) auto;gap:4px;display:grid}.workspace-input-row input{border:1px solid var(--color-border-subtle);border-radius:var(--radius-control);background:var(--color-bg-surface);min-width:0;color:var(--color-text-primary);padding:7px 8px}.workspace-input-row button,.fs-entry-row button,.fs-row{border-radius:var(--radius-control);color:var(--color-text-muted);background:0 0;border:0}.workspace-input-row button{background:var(--color-accent-soft);color:var(--color-accent);padding:0 8px}.workspace-input-row button:disabled{opacity:.45}.workspace-path{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--color-text-muted);font-size:12px;overflow:hidden}.fs-entry-row{grid-template-columns:minmax(0,1fr) auto;gap:4px;display:grid}.fs-entry-row button,.fs-row{text-align:left;min-height:28px;padding:0 7px}.fs-entry-row button:first-child{text-overflow:ellipsis;white-space:nowrap;color:var(--color-text-primary);overflow:hidden}.session-row,.activity-row{border-radius:var(--radius-control);width:100%;min-height:34px;color:var(--color-text-primary);text-align:left;background:0 0;border:0;justify-content:space-between;align-items:center;gap:8px;padding:7px 8px;font-size:13px;display:flex}.session-row.active{background:var(--color-accent-soft);color:var(--color-accent);font-weight:var(--font-weight-ui-medium)}.session-row time,.activity-row time{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--color-text-muted);font-size:12px;overflow:hidden}.right-divider{border-top:1px solid var(--color-border-subtle);color:var(--color-text-muted);font-size:11px;font-weight:var(--font-weight-ui-medium);text-transform:uppercase;margin:12px 0 4px;padding-top:12px}.activity-row{color:var(--color-text-muted)}.composer{background:var(--color-bg-surface);grid-area:footer;grid-template-columns:1fr;align-items:end;min-width:0;padding:0 16px 12px;display:grid}.composer-box{width:100%;min-height:var(--composer-min-height);border:1px solid var(--color-border-strong);border-radius:var(--radius-composer);background:var(--color-bg-sidebar);align-items:center;display:flex;position:relative;overflow:visible}.composer-box:focus-within{border-color:var(--color-accent);box-shadow:0 0 0 1px var(--color-accent-soft)}.composer textarea{resize:none;width:100%;max-height:160px;color:var(--color-text-primary);font-weight:var(--font-weight-content-normal);background:0 0;border:0;outline:0;padding:12px 124px 12px 12px}.composer-actions{align-items:center;gap:2px;display:flex;position:absolute;bottom:8px;right:8px}.session-ring,.chip-button,.icon-action,.send-icon,.mobile-toggle{border-radius:var(--radius-control);width:28px;height:28px;color:var(--color-text-muted);background:0 0;border:0;justify-content:center;align-items:center;display:inline-flex}.session-ring:before{content:"";border:2px solid var(--color-accent);border-radius:999px;width:14px;height:14px}.chip-button{width:auto;padding:0 8px;font-size:12px}.icon-action:hover,.chip-button:hover,.mobile-toggle:hover{background:var(--color-hover)}.send-icon{background:var(--color-accent);color:var(--color-text-inverse);font-size:16px;font-weight:700}.send-icon:disabled{opacity:.45}.mobile-toggle,.overlay{display:none}@media (width<=920px){html,body{width:100%;min-height:0;position:fixed;inset:0}.app-shell{height:100dvh;padding-top:env(safe-area-inset-top,0);flex-direction:column;display:flex}.timeline{flex:1;min-height:0}.composer{padding:0 1px max(2px, env(safe-area-inset-bottom));flex:none;grid-template-columns:30px minmax(0,1fr) 30px;gap:1px}.mobile-toggle{align-self:center;height:44px;display:inline-flex}.composer-box{border-radius:10px;min-height:44px}.composer textarea{padding-right:114px}.left-panel,.right-panel{top:env(safe-area-inset-top,0);z-index:30;width:var(--shell-mobile-panel-width);background:var(--color-bg-sidebar);box-shadow:4px 0 24px var(--color-shadow-drawer);transition:transform .22s cubic-bezier(.2,.8,.2,1);position:fixed;bottom:0;transform:translate(-100%)}.left-panel{border-top-right-radius:14px;border-bottom-right-radius:14px;left:0}.right-panel{box-shadow:-4px 0 24px var(--color-shadow-drawer);border-top-left-radius:14px;border-bottom-left-radius:14px;right:0;transform:translate(100%)}.app-shell[data-left-open=true] .left-panel,.app-shell[data-right-open=true] .right-panel{transform:translate(0)}.app-shell[data-left-open=true] .overlay,.app-shell[data-right-open=true] .overlay{z-index:20;background:var(--color-scrim);display:block;position:fixed;inset:0}}}