-
- {features.map((feature) => (
-
-
-
-
{feature.title}
-
{feature.description}
+
+
{t("welcome.support_title")}
+
+ {features.map((feature) => (
+
+
+
+
{feature.title}
+
{feature.description}
+
-
- ))}
+ ))}
+
diff --git a/packages/web/src/locales/en.json b/packages/web/src/locales/en.json
index 98565247..247e1749 100644
--- a/packages/web/src/locales/en.json
+++ b/packages/web/src/locales/en.json
@@ -343,6 +343,9 @@
"loading_body": "This terminal is unavailable while history is being restored. Please wait until recovery finishes before continuing. Larger histories may take longer to restore.",
"failed_title": "Terminal history was not restored yet",
"failed_body": "The terminal is still usable, but older output still could not be filled back in. Try again later or after a refresh; if the server still retains the history, it may still come back.",
+ "reconcile_failed_title": "Terminal recovery check did not complete",
+ "reconcile_failed_body": "Recovery inspection did not finish this time. The terminal is still usable, but it is temporarily unclear whether older history was filled back in. Try checking again shortly.",
+ "recheck_action": "Check again",
"retryable_title": "Terminal history was not restored yet",
"retryable_body": "The terminal is still usable, but older output was not filled back in this time. You can retry recovery; if the server still retains the history, it may still come back later or after a refresh.",
"retry_action": "Retry recovery",
@@ -353,9 +356,7 @@
"unknown_body_with_provider": "This terminal session is no longer present on the server. Reopen a {provider} session to continue?",
"closed_title": "This session has ended",
"closed_body": "Reopen a new session to continue?",
- "closed_body_with_provider": "Reopen a {provider} session to continue?",
- "truncated_title": "Terminal history is partial",
- "truncated_body": "Older output has already fallen out of the replay buffer, but new output will continue to stream."
+ "closed_body_with_provider": "Reopen a {provider} session to continue?"
}
},
"file": {
@@ -987,21 +988,26 @@
"conflict": "Resource conflict"
},
"welcome": {
- "kicker": "DEPLOY ONCE, CODE EVERYWHERE",
- "title": "Welcome to Coder Studio",
- "description": "Deploy your coding workspace once, then keep working from wherever you are. Same workspace, same context, across all your devices.",
+ "kicker": "LOCAL AI CODING WORKSPACE",
+ "title": "Open a workspace. Start an AI coding session.",
+ "description": "Choose a local project folder to get started. Once the workspace is open, you can launch Claude Code or Codex right where you review files, Git changes, and terminal output.",
+ "workflow_title": "How it works",
+ "step_1_label": "Step 1",
+ "step_1_title": "Open your project folder",
+ "step_1_detail": "Choose a local directory to become your active workspace.",
+ "step_2_label": "Step 2",
+ "step_2_title": "Start Claude or Codex",
+ "step_2_detail": "Inside the workspace, launch an AI session for that project.",
+ "settings_hint": "Need provider setup first?",
+ "support_title": "Why use it here",
"features": {
- "agent_first": {
- "title": "Agent-first AI coding",
- "description": "Launch AI sessions that write, test, and deploy code."
- },
"git_tools": {
- "title": "Built-in Git tools",
- "description": "Stage, commit, and manage branches without leaving the IDE."
+ "title": "Review code and Git side by side",
+ "description": "Inspect files and changes next to the agent instead of switching between tools."
},
"terminals": {
- "title": "Integrated terminals",
- "description": "Run commands and scripts alongside your AI sessions."
+ "title": "Run commands in the same workspace",
+ "description": "Use integrated terminals alongside your AI session when you need manual control."
}
}
},
diff --git a/packages/web/src/locales/zh.json b/packages/web/src/locales/zh.json
index ba830611..5788e700 100644
--- a/packages/web/src/locales/zh.json
+++ b/packages/web/src/locales/zh.json
@@ -343,6 +343,9 @@
"loading_body": "恢复期间暂时无法使用当前终端;请耐心等待,历史内容恢复完成后再继续。内容较多时可能需要更久。",
"failed_title": "终端历史暂未恢复",
"failed_body": "当前终端可以继续使用,但较早输出这次仍未补齐。请稍后或刷新页面后再看;如果服务端仍保留历史,后续仍可能找回。",
+ "reconcile_failed_title": "终端恢复检查未完成",
+ "reconcile_failed_body": "这次没有完成恢复决策,当前终端仍可继续使用,但较早历史是否补齐暂时无法确认。请稍后重新检查。",
+ "recheck_action": "重新检查",
"retryable_title": "终端历史暂未恢复",
"retryable_body": "当前终端可以继续使用,但较早输出这次没有补齐。你可以重试恢复;如果服务端仍保留历史,稍后或刷新页面后仍可能找回。",
"retry_action": "重试恢复",
@@ -353,9 +356,7 @@
"unknown_body_with_provider": "这个终端会话已经不在服务端。是否重新打开一个 {provider} 会话继续?",
"closed_title": "当前会话已结束",
"closed_body": "是否重新打开一个新会话继续。",
- "closed_body_with_provider": "是否重新打开一个 {provider} 会话继续。",
- "truncated_title": "历史内容不完整",
- "truncated_body": "较早的终端输出已被回放缓冲区淘汰,后续输出仍会继续显示。"
+ "closed_body_with_provider": "是否重新打开一个 {provider} 会话继续。"
}
},
"file": {
@@ -987,21 +988,26 @@
"conflict": "资源冲突"
},
"welcome": {
- "kicker": "一次部署,随处编码",
- "title": "欢迎使用 Coder Studio",
- "description": "只需部署一次编码工作区,即可在任何地方继续工作。同一个工作区,同一个上下文,跨所有设备。",
+ "kicker": "本地 AI 编码工作台",
+ "title": "先打开工作区,再启动 AI 编码会话",
+ "description": "先选择一个本地项目目录。打开工作区后,你就可以在同一个界面里启动 Claude Code 或 Codex,同时查看文件、Git 变更和终端输出。",
+ "workflow_title": "使用步骤",
+ "step_1_label": "第 1 步",
+ "step_1_title": "打开你的项目目录",
+ "step_1_detail": "先选择一个本地目录,作为当前工作区。",
+ "step_2_label": "第 2 步",
+ "step_2_title": "启动 Claude 或 Codex",
+ "step_2_detail": "进入工作区后,再为当前项目启动一个 AI 会话。",
+ "settings_hint": "如果要先配置 Provider,可以先去设置。",
+ "support_title": "为什么在这里使用",
"features": {
- "agent_first": {
- "title": "以 Agent 为核心的 AI 编码",
- "description": "启动能够编写、测试和部署代码的 AI 会话。"
- },
"git_tools": {
- "title": "内置 Git 工具",
- "description": "无需离开 IDE,就能暂存、提交并管理分支。"
+ "title": "并排查看代码和 Git 变更",
+ "description": "在 Agent 旁边直接查看文件和改动,不用在多个工具之间来回切换。"
},
"terminals": {
- "title": "集成终端",
- "description": "在 AI 会话旁边直接运行命令和脚本。"
+ "title": "在同一工作区运行命令",
+ "description": "需要手动操作时,可以直接在集成终端里配合 AI 会话执行命令。"
}
}
},
diff --git a/packages/web/src/styles/components.css b/packages/web/src/styles/components.css
index 409b1ef9..b1172ea7 100644
--- a/packages/web/src/styles/components.css
+++ b/packages/web/src/styles/components.css
@@ -2629,9 +2629,15 @@ body.is-dragging-pane {
padding: var(--sp-10);
}
+.welcome-container--landing {
+ height: 100%;
+ min-height: 0;
+ overflow-y: auto;
+}
+
.welcome-card {
- width: min(100%, 920px);
- max-width: 920px;
+ width: min(100%, 1040px);
+ max-width: 1040px;
display: flex;
flex-direction: column;
align-items: stretch;
@@ -2644,6 +2650,17 @@ body.is-dragging-pane {
text-align: left;
}
+.welcome-card--landing {
+ gap: var(--sp-5);
+}
+
+.welcome-layout {
+ display: grid;
+ grid-template-columns: minmax(280px, 0.9fr) minmax(0, 1.1fr);
+ gap: var(--sp-7);
+ align-items: start;
+}
+
.welcome-card__hero,
.welcome-card__actions,
.welcome-card__panel,
@@ -2657,6 +2674,11 @@ body.is-dragging-pane {
gap: var(--sp-3);
}
+.welcome-card--landing .welcome-card__hero {
+ gap: var(--sp-4);
+ padding-right: 0;
+}
+
.welcome-card__actions,
.welcome-card__panel,
.welcome-card__features {
@@ -2666,11 +2688,119 @@ body.is-dragging-pane {
.welcome-actions-group {
display: flex;
- align-items: center;
+ align-items: flex-start;
gap: var(--sp-3);
flex-wrap: wrap;
}
+.welcome-step-hint,
+.welcome-step-detail,
+.welcome-settings-hint {
+ width: 100%;
+ margin: 0;
+}
+
+.welcome-step-hint {
+ font-size: var(--type-body-6-size);
+ line-height: var(--type-body-6-line-height);
+ font-weight: var(--type-body-6-weight);
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ color: var(--text-ter);
+}
+
+.welcome-flow {
+ display: flex;
+ flex-direction: column;
+ gap: var(--sp-4);
+ min-width: 0;
+}
+
+.welcome-flow__header {
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+}
+
+.welcome-flow__steps {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: var(--sp-3);
+}
+
+.welcome-flow__support {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--sp-3);
+ padding: var(--sp-3) var(--sp-4);
+ border: 1px solid var(--component-mix-border-default-84pct-transparent);
+ border-radius: var(--radius-lg);
+ background: var(--component-mix-surface-page-96pct-surface-panel-4pct);
+}
+
+.welcome-step-card {
+ display: flex;
+ flex-direction: column;
+ gap: var(--sp-3);
+ padding: var(--sp-4);
+ border: 1px solid var(--component-mix-border-default-84pct-transparent);
+ border-radius: var(--radius-lg);
+ background: var(--component-mix-surface-panel-92pct-surface-page);
+}
+
+.welcome-step-card__header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--sp-3);
+}
+
+.welcome-step-card__label {
+ font-size: var(--type-body-6-size);
+ line-height: var(--type-body-6-line-height);
+ font-weight: var(--type-body-6-weight);
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ color: var(--text-tertiary);
+}
+
+.welcome-step-card__icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ border-radius: var(--radius-md);
+ color: var(--text-secondary);
+ background: var(--component-mix-surface-page-94pct-surface-panel-6pct);
+}
+
+.welcome-step-card__title {
+ font-size: var(--type-heading-5-size);
+ line-height: var(--type-heading-5-line-height);
+ font-weight: var(--type-heading-5-weight);
+ color: var(--text-primary);
+ min-height: calc(var(--type-heading-5-line-height) * 2);
+}
+
+.welcome-step-detail {
+ max-width: 34ch;
+ font-size: var(--type-body-5-size);
+ line-height: var(--type-body-5-line-height);
+ font-weight: var(--type-body-5-weight);
+ color: var(--text-secondary);
+ flex: 1;
+}
+
+.welcome-settings-hint {
+ max-width: 32ch;
+ font-size: var(--type-body-6-size);
+ line-height: var(--type-body-6-line-height);
+ font-weight: var(--type-body-6-weight);
+ color: var(--text-tertiary);
+}
+
.welcome-kicker {
font-size: var(--type-body-6-size);
line-height: var(--type-body-6-line-height);
@@ -2681,19 +2811,20 @@ body.is-dragging-pane {
}
.welcome-title {
- font-size: var(--type-heading-1-size);
- line-height: var(--type-heading-1-line-height);
- font-weight: var(--type-heading-1-weight);
+ font-size: var(--type-heading-3-size);
+ line-height: var(--type-heading-3-line-height);
+ font-weight: var(--type-heading-3-weight);
margin: 0;
color: var(--text);
+ max-width: 12ch;
}
.welcome-body {
- font-size: var(--type-body-3-size);
- line-height: var(--type-body-3-line-height);
- font-weight: var(--type-body-3-weight);
+ font-size: var(--type-body-4-size);
+ line-height: var(--type-body-4-line-height);
+ font-weight: var(--type-body-4-weight);
color: var(--text-secondary);
- max-width: 440px;
+ max-width: 38ch;
margin: 0;
}
@@ -2967,16 +3098,37 @@ body.is-dragging-pane {
width: 100%;
}
+.welcome-support {
+ display: flex;
+ flex-direction: column;
+ gap: var(--sp-2);
+}
+
+.welcome-support__title {
+ font-size: var(--type-body-6-size);
+ line-height: var(--type-body-6-line-height);
+ font-weight: var(--type-body-6-weight);
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ color: var(--text-tertiary);
+}
+
+.welcome-support-list {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: var(--sp-2);
+}
+
.welcome-feature {
display: flex;
align-items: flex-start;
gap: var(--sp-3);
- padding: var(--sp-4);
+ padding: var(--sp-3);
border-radius: var(--radius-lg);
background: transparent;
min-height: 0;
justify-content: flex-start;
- flex-direction: column;
+ flex-direction: row;
border: 1px solid var(--component-mix-border-default-84pct-transparent);
box-shadow: none;
text-align: left;
@@ -2995,9 +3147,9 @@ body.is-dragging-pane {
}
.welcome-feature-title {
- font-size: var(--type-body-3-size);
- line-height: var(--type-body-3-line-height);
- font-weight: var(--type-body-3-weight);
+ font-size: var(--type-body-4-size);
+ line-height: var(--type-body-4-line-height);
+ font-weight: var(--type-body-4-weight);
color: var(--text-primary);
}
@@ -11877,6 +12029,7 @@ body.is-dragging-pane .session-action-btn-drag {
align-items: stretch;
justify-content: flex-start;
min-height: 100dvh;
+ overflow-y: auto;
padding: calc(env(safe-area-inset-top, 0px) + var(--sp-4))
calc(env(safe-area-inset-right, 0px) + var(--sp-4))
calc(env(safe-area-inset-bottom, 0px) + var(--sp-5))
@@ -11886,12 +12039,22 @@ body.is-dragging-pane .session-action-btn-drag {
.welcome-card--mobile {
width: 100%;
max-width: none;
- padding: var(--sp-6) var(--sp-4);
- gap: var(--sp-5);
+ padding: var(--sp-4);
+ gap: var(--sp-3);
border-radius: var(--radius-lg);
box-shadow: none;
}
+ .welcome-card--mobile.welcome-card--landing {
+ min-height: auto;
+ }
+
+ .welcome-card--mobile .welcome-layout {
+ display: flex;
+ flex-direction: column;
+ gap: var(--sp-3);
+ }
+
.welcome-card--mobile .welcome-card__actions {
align-items: stretch;
}
@@ -11902,31 +12065,58 @@ body.is-dragging-pane .session-action-btn-drag {
}
.welcome-card--mobile .welcome-title {
- font-size: var(--type-heading-1-size);
- line-height: var(--type-heading-1-line-height);
- font-weight: var(--type-heading-1-weight);
+ font-size: var(--type-heading-3-size);
+ line-height: var(--type-heading-3-line-height);
+ font-weight: var(--type-heading-3-weight);
letter-spacing: 0;
+ max-width: 10ch;
}
.welcome-card--mobile .welcome-body {
max-width: none;
- font-size: var(--type-body-3-size);
- line-height: var(--type-body-3-line-height);
- font-weight: var(--type-body-3-weight);
+ font-size: var(--type-body-5-size);
+ line-height: var(--type-body-5-line-height);
+ font-weight: var(--type-body-5-weight);
+ }
+
+ .welcome-card--mobile .welcome-step-detail,
+ .welcome-card--mobile .welcome-settings-hint {
+ max-width: none;
+ }
+
+ .welcome-card--mobile .welcome-flow {
+ gap: var(--sp-3);
+ }
+
+ .welcome-card--mobile .welcome-flow__steps {
+ grid-template-columns: 1fr;
+ gap: var(--sp-2);
+ }
+
+ .welcome-card--mobile .welcome-flow__support {
+ flex-direction: column;
+ align-items: stretch;
+ padding: var(--sp-3);
+ }
+
+ .welcome-card--mobile .welcome-step-card {
+ padding: var(--sp-3);
+ gap: var(--sp-2);
}
.welcome-card--mobile.diagnostics-card {
width: 100%;
}
- .welcome-card--mobile .welcome-features {
+ .welcome-card--mobile .welcome-support-list {
grid-template-columns: 1fr;
+ gap: var(--sp-2);
}
.welcome-card--mobile .welcome-feature {
align-items: flex-start;
min-height: 0;
- padding: var(--sp-4);
+ padding: var(--sp-3);
border-radius: var(--radius-lg);
text-align: left;
}
@@ -11938,12 +12128,14 @@ body.is-dragging-pane .session-action-btn-drag {
.welcome-card--mobile .welcome-btn {
width: 100%;
justify-content: center;
- padding-inline: var(--sp-5);
+ min-width: 0;
+ padding-inline: var(--sp-4);
border-radius: var(--radius-md);
}
.welcome-card--mobile .welcome-link {
width: 100%;
+ justify-content: center;
}
.auth-screen--mobile {
@@ -14420,7 +14612,18 @@ body.is-dragging-pane .session-action-btn-drag {
.session-card.session-card--active {
background: var(--workspace-session-active-surface);
- box-shadow: inset 0 0 0 1px var(--component-mix-border-focus-84pct-transparent);
+ box-shadow: none;
+ position: relative;
+ isolation: isolate;
+}
+
+.workspace-main-stage .session-card.session-card--active::after {
+ content: "";
+ position: absolute;
+ inset: 0;
+ z-index: var(--z-inline);
+ border: 1px solid var(--component-mix-border-focus-84pct-transparent);
+ pointer-events: none;
}
.session-header,
@@ -14597,9 +14800,14 @@ body.is-dragging-pane .session-action-btn-drag {
.mobile-shell__agent-stage .session-card.session-card--active {
background: var(--workspace-session-mobile-active-surface);
+ box-shadow: none;
backdrop-filter: var(--material-backdrop-filter);
}
+.mobile-shell__agent-stage > .session-card.session-card--active > .panel-header {
+ border-top: 1px solid var(--component-mix-border-focus-76pct-transparent);
+}
+
@media (max-width: 899px), (pointer: coarse) {
.mobile-shell {
--mobile-safe-top: env(safe-area-inset-top, 0px);
diff --git a/packages/web/src/styles/components.theme.test.ts b/packages/web/src/styles/components.theme.test.ts
index 44bf9bcb..efbbb1d0 100644
--- a/packages/web/src/styles/components.theme.test.ts
+++ b/packages/web/src/styles/components.theme.test.ts
@@ -1028,6 +1028,9 @@ describe("components.css theme-sensitive surfaces", () => {
const sessionTerminal = getLastRuleBlock(".session-terminal");
const sessionCard = getLastRuleBlock(".session-card");
const activeSessionCard = getLastRuleBlock(".session-card.session-card--active");
+ const activeSessionCardOverlay = getLastRuleBlock(
+ ".workspace-main-stage .session-card.session-card--active::after"
+ );
const activeSessionHeader = getRuleBlocksFrom(
stylesheet,
".session-card.session-card--active > .panel-header"
@@ -1147,9 +1150,16 @@ describe("components.css theme-sensitive surfaces", () => {
expect(sessionCard).toContain("backdrop-filter: var(--material-backdrop-filter)");
expect(activeSessionCard).toContain("background: var(--workspace-session-active-surface)");
expect(activeSessionCard).not.toContain("background: var(--bg-active)");
- expect(activeSessionCard).toContain("box-shadow: inset 0 0 0 1px");
- expect(activeSessionCard).toContain("var(--component-mix-border-focus-84pct-transparent)");
+ expect(activeSessionCard).toContain("box-shadow: none");
+ expect(activeSessionCardOverlay).toContain('content: ""');
+ expect(activeSessionCardOverlay).toContain("position: absolute");
+ expect(activeSessionCardOverlay).toContain("inset: 0");
+ expect(activeSessionCardOverlay).toContain(
+ "border: 1px solid var(--component-mix-border-focus-84pct-transparent)"
+ );
+ expect(activeSessionCardOverlay).toContain("pointer-events: none");
expect(activeSessionHeader).toContain("background: var(--workspace-session-header-surface)");
+ expect(activeSessionHeader).not.toContain("border-top:");
expect(activeSessionHeader).toContain("backdrop-filter: var(--material-backdrop-filter)");
expect(activeSessionHeader).not.toContain("var(--bg-active) 88%");
expect(activeSessionTitle).toContain("color: var(--text-primary)");
@@ -1264,6 +1274,33 @@ describe("components.css theme-sensitive surfaces", () => {
expect(authCard).not.toContain("rgba(13, 20, 26, 0.94)");
});
+ it("styles the welcome page as a step-first workflow with compact support content", () => {
+ const welcomeLayout = getLastRuleBlock(".welcome-layout");
+ const welcomeFlow = getLastRuleBlock(".welcome-flow");
+ const welcomeSteps = getLastRuleBlock(".welcome-flow__steps");
+ const welcomeFlowSupport = getLastRuleBlock(".welcome-flow__support");
+ const stepCard = getLastRuleBlock(".welcome-step-card");
+ const supportList = getLastRuleBlock(".welcome-support-list");
+ const stepHint = getLastRuleBlock(".welcome-step-hint");
+ const stepDetail = getLastRuleBlock(".welcome-step-detail");
+ const settingsHint = getLastRuleBlock(".welcome-settings-hint");
+
+ expect(welcomeLayout).toContain("display: grid");
+ expect(welcomeLayout).toContain("grid-template-columns: minmax(280px, 0.9fr) minmax(0, 1.1fr)");
+ expect(welcomeFlow).toContain("flex-direction: column");
+ expect(welcomeSteps).toContain("display: grid");
+ expect(welcomeSteps).toContain("grid-template-columns: repeat(2, minmax(0, 1fr))");
+ expect(welcomeFlowSupport).toContain("display: flex");
+ expect(stepCard).toContain("border-radius: var(--radius-lg)");
+ expect(stepCard).toContain("background: var(--component-mix-surface-panel-92pct-surface-page)");
+ expect(supportList).toContain("grid-template-columns: repeat(2, minmax(0, 1fr))");
+ expect(stepHint).toContain("text-transform: uppercase");
+ expect(stepHint).toContain("color: var(--text-ter)");
+ expect(stepDetail).toContain("max-width: 34ch");
+ expect(stepDetail).toContain("color: var(--text-secondary)");
+ expect(settingsHint).toContain("color: var(--text-tertiary)");
+ });
+
it("keeps quick actions sized to its label instead of icon-button width", () => {
const quickActions = getLastRuleBlock(".topbar-quick-actions");
@@ -1511,6 +1548,13 @@ describe("components.css theme-sensitive surfaces", () => {
const xtermReplayCard = getLastRuleBlock(".xterm-replay-overlay__card");
const sessionProgress = getLastRuleBlock(".session-progress");
const sessionHeader = getLastRuleBlock(".session-header");
+ const activeSessionCard = getLastRuleBlock(".session-card.session-card--active");
+ const activeSessionCardOverlay = getLastRuleBlock(
+ ".workspace-main-stage .session-card.session-card--active::after"
+ );
+ const activeSessionHeader = getLastRuleBlock(
+ ".session-card.session-card--active > .panel-header"
+ );
const supervisorCard = getLastRuleBlock(".supervisor-card");
const sessionHeaderLeft = getLastRuleBlock(".session-header-left");
const sessionHeaderCopyBlocks = getRuleBlocksFrom(stylesheet, ".session-header-copy");
@@ -1536,6 +1580,11 @@ describe("components.css theme-sensitive surfaces", () => {
expect(xtermReplayCard).toContain("border-radius: var(--terminal-local-overlay-radius)");
expect(sessionProgress).toContain("background: var(--state-info-bg)");
expect(sessionHeader).toContain("padding: var(--gap-tight) var(--inset-control-inline)");
+ expect(activeSessionCard).toContain("box-shadow: none");
+ expect(activeSessionCardOverlay).toContain(
+ "border: 1px solid var(--component-mix-border-focus-84pct-transparent)"
+ );
+ expect(activeSessionHeader).not.toContain("border-top:");
expect(supervisorCard).toContain("background: var(--workspace-session-header-surface)");
expect(supervisorCard).toContain("backdrop-filter: var(--material-backdrop-filter)");
expect(sessionHeaderLeft).toContain("gap: var(--gap-default)");
@@ -2613,11 +2662,21 @@ describe("components.css theme-sensitive surfaces", () => {
it("stacks mobile welcome and auth shells vertically so cards size to content", () => {
const welcomeContainer = getLastRuleBlock(".welcome-container--mobile");
+ const mobileWelcomeLayout = getLastRuleBlock(".welcome-card--mobile .welcome-layout");
+ const mobileWelcomeSteps = getLastRuleBlock(".welcome-card--mobile .welcome-flow__steps");
+ const mobileWelcomeSupport = getLastRuleBlock(".welcome-card--mobile .welcome-flow__support");
+ const mobileSupportList = getLastRuleBlock(".welcome-card--mobile .welcome-support-list");
const authScreen = getLastRuleBlock(".auth-screen--mobile");
expect(welcomeContainer).toContain("flex-direction: column");
expect(welcomeContainer).toContain("align-items: stretch");
expect(welcomeContainer).toContain("justify-content: flex-start");
+ expect(welcomeContainer).toContain("overflow-y: auto");
+ expect(mobileWelcomeLayout).toContain("flex-direction: column");
+ expect(mobileWelcomeSteps).toContain("grid-template-columns: 1fr");
+ expect(mobileWelcomeSupport).toContain("flex-direction: column");
+ expect(mobileWelcomeSupport).toContain("align-items: stretch");
+ expect(mobileSupportList).toContain("grid-template-columns: 1fr");
expect(authScreen).toContain("padding:");
});
@@ -3196,8 +3255,14 @@ describe("components.css theme-sensitive surfaces", () => {
".mobile-shell--landscape-compact .mobile-shell__viewport"
);
const sessionCard = getLastRuleBlock(".mobile-shell__agent-stage > .session-card");
+ const activeSessionCard = getLastRuleBlock(
+ ".mobile-shell__agent-stage .session-card.session-card--active"
+ );
const progress = getLastRuleBlock(".mobile-shell__agent-stage .session-progress");
const header = getLastRuleBlock(".mobile-shell__agent-stage > .session-card > .panel-header");
+ const activeHeader = getLastRuleBlock(
+ ".mobile-shell__agent-stage > .session-card.session-card--active > .panel-header"
+ );
const titleRow = getLastRuleBlock(".mobile-shell__agent-stage .session-title-row");
const headerRight = getLastRuleBlock(".mobile-shell__agent-stage .session-header-right");
const badges = getLastGroupedRuleBlock(
@@ -3215,9 +3280,11 @@ describe("components.css theme-sensitive surfaces", () => {
expect(content).toContain("gap: 4px");
expect(sessionCard).toContain("border-radius: 0");
expect(sessionCard).toContain("box-shadow: none");
+ expect(activeSessionCard).toContain("box-shadow: none");
expect(progress).toContain("display: none");
expect(header).toContain("padding: 4px");
expect(header).toContain("border-bottom:");
+ expect(activeHeader).toContain("border-top:");
expect(header).not.toContain("linear-gradient(");
expect(titleRow).toContain("gap: 6px");
expect(headerRight).toContain("max-width: 100%");