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.
- package/package.json +1 -1
- package/src/agent/code-search/cache.mjs +133 -0
- package/src/agent/code-search/chunk-rules.mjs +107 -0
- package/src/agent/code-search/chunker.mjs +125 -0
- package/src/agent/code-search/engine.mjs +109 -0
- package/src/agent/code-search/languages.mjs +25 -0
- package/src/agent/code-search/parser-pool.mjs +29 -0
- package/src/agent/code-search/rerank.mjs +43 -0
- package/src/agent/code-search/retrieval/bm25.mjs +47 -0
- package/src/agent/code-search/retrieval/fusion.mjs +18 -0
- package/src/agent/code-search/retrieval/model2vec.mjs +96 -0
- package/src/agent/code-search/retrieval/safetensors.mjs +49 -0
- package/src/agent/code-search/retrieval/vector.mjs +107 -0
- package/src/agent/code-search/retrieval/wordpiece.mjs +82 -0
- package/src/agent/code-search/scanner.mjs +84 -0
- package/src/agent/code-search/tokenize.mjs +16 -0
- package/src/agent/code-search/tool.mjs +75 -0
- package/src/agent/runner/provider-quota-runtime.mjs +38 -0
- package/src/agent/runner.mjs +14 -10
- package/src/agent/runtime/remote-runner-client.mjs +2 -0
- package/src/agent/runtime/runner-ipc-target.mjs +7 -0
- package/src/agent/runtime/runner-process-client.mjs +5 -0
- package/src/agent/runtime/runner-process-factory.mjs +5 -0
- package/src/agent/runtime/runner-runtime-host.mjs +2 -0
- package/src/agent/runtime/state/runner-state.mjs +1 -0
- package/src/agent/runtime/ui-event-bridge.mjs +2 -0
- package/src/agent/session/session-options.mjs +2 -1
- package/src/agent/tools.mjs +7 -1
- package/src/agent/turn/turn-events.mjs +41 -0
- package/src/agent/turn/turn-runner.mjs +5 -2
- package/src/cli/commands/registry/slash-command-registry.mjs +10 -7
- package/src/cli/commands/status-command.mjs +61 -35
- package/src/cli/input/history-store.mjs +65 -3
- package/src/cli/repl-loop.mjs +8 -6
- package/src/cli/startup/app-runtime.mjs +5 -29
- package/src/cli/startup/create-runtime-runner.mjs +4 -46
- package/src/cli/tui/input/history-navigation-controller.mjs +56 -0
- package/src/cli/turn/turn-input-preparer.mjs +0 -1
- package/src/cli/ui.mjs +9 -0
- package/src/context/engine.mjs +4 -2
- package/src/context/system-core/base.md +9 -1
- package/src/history/runner.mjs +11 -0
- package/src/history/store.mjs +129 -0
- package/src/history/tool.mjs +39 -0
- package/src/lsp/client.mjs +12 -5
- package/src/lsp/service.mjs +15 -3
- package/src/main.mjs +1 -2
- package/src/provider/quota/codex.mjs +278 -0
- package/src/provider/quota/index.mjs +46 -0
- package/src/provider/quota/transport-observer.mjs +99 -0
- package/src/web-ui/command.mjs +2 -2
- package/src/web-ui/runtime-host.mjs +7 -23
- package/src/web-ui/server.mjs +1 -0
- package/src/web-ui/session-manager.mjs +4 -2
- package/src/web-ui/src/components/AppShell.tsx +1 -0
- package/src/web-ui/src/components/RightSidebar.tsx +47 -2
- package/src/web-ui/src/model.ts +20 -0
- package/src/web-ui/src/runtime/client.ts +8 -1
- package/src/web-ui/src/runtime/useWebRuntime.ts +13 -1
- package/src/web-ui/src/styles/shell.css +10 -0
- package/src/web-ui/dist/assets/index-BUmhnID4.css +0 -1
- package/src/web-ui/dist/assets/index-CtuqTjcB.js +0 -1845
- package/src/web-ui/dist/index.html +0 -13
package/src/web-ui/src/model.ts
CHANGED
|
@@ -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}}}
|