diff --git a/internal/cloudcp/portal/dist/build_manifest.json b/internal/cloudcp/portal/dist/build_manifest.json
index aab2dc64f..2fa9f4fd3 100644
--- a/internal/cloudcp/portal/dist/build_manifest.json
+++ b/internal/cloudcp/portal/dist/build_manifest.json
@@ -1,5 +1,5 @@
{
- "source_hash": "85ccadc015ace1a5ed37c100689292817f7c41de9b0d8547a6d26ca908c4d19f",
+ "source_hash": "b4d41db9eab964bde794244e2c7d9d7e0aa77de1523520c2c448d1f08cfe969f",
"build_inputs": [
"package.json",
"tsconfig.json",
diff --git a/internal/cloudcp/portal/dist/portal_app.css b/internal/cloudcp/portal/dist/portal_app.css
index a196e9fce..b99d432e4 100644
--- a/internal/cloudcp/portal/dist/portal_app.css
+++ b/internal/cloudcp/portal/dist/portal_app.css
@@ -399,6 +399,46 @@ header .logout-btn:hover,
.portal-shell-main > .portal-content-panel {
display: none !important;
}
+.portal-account-bar {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) auto;
+ gap: 18px;
+ align-items: end;
+ padding: 16px 22px 18px;
+ border-bottom: 1px solid var(--line);
+ background: rgba(244, 247, 250, 0.92);
+}
+.portal-account-bar-copy {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+}
+.portal-account-bar-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 16px;
+ flex-wrap: wrap;
+}
+.portal-account-bar-row h2 {
+ margin: 0;
+ font-size: 28px;
+ line-height: 0.98;
+ letter-spacing: -0.05em;
+}
+.portal-account-bar-copy p {
+ margin: 0;
+ font-size: 13px;
+ line-height: 1.5;
+ color: var(--ink-soft);
+}
+.portal-account-bar-chips,
+.portal-account-bar-actions {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ flex-wrap: wrap;
+}
.portal-shell[data-shell-section=overview] .portal-content-panel-overview,
.portal-shell[data-shell-section=services] .portal-content-panel-services,
.portal-shell[data-shell-section=support] .portal-content-panel-support,
@@ -470,29 +510,6 @@ header .logout-btn:hover,
.account-surface + .account-surface {
margin-top: 22px;
}
-.account-surface-header {
- display: grid;
- grid-template-columns: minmax(0, 1fr) auto;
- align-items: end;
- gap: 16px;
- padding: 0 4px 12px;
- border: none;
- border-bottom: 1px solid var(--line);
- border-radius: var(--radius-md);
- background: transparent;
- box-shadow: none;
-}
-.account-heading h2 {
- margin: 2px 0 0;
- font-size: 24px;
- line-height: 1.02;
- letter-spacing: -0.05em;
-}
-.account-summary {
- margin-top: 5px;
- font-size: 12px;
- color: var(--ink-soft);
-}
.account-badges,
.account-context-strip,
.workspace-badges,
@@ -536,7 +553,6 @@ header .logout-btn:hover,
display: grid;
grid-template-columns: 1fr;
gap: 14px;
- margin-top: 10px;
}
.account-content-panel {
display: block;
@@ -704,36 +720,11 @@ header .logout-btn:hover,
.overview-side-card-primary {
background: var(--panel-strong);
}
-.overview-quick-actions {
- display: grid;
- grid-template-columns: repeat(3, minmax(0, 1fr));
- gap: 10px;
- margin-top: 16px;
-}
-.overview-quick-action {
+.overview-next-actions {
display: flex;
- flex-direction: column;
- gap: 6px;
- padding: 14px;
- border: 1px solid var(--line);
- border-radius: 10px;
- background: #fff;
- text-align: left;
- cursor: pointer;
-}
-.overview-quick-action:hover {
- border-color: var(--accent);
- box-shadow: var(--shadow-sm);
-}
-.overview-quick-action-title {
- font-size: 14px;
- font-weight: 700;
- color: var(--ink);
-}
-.overview-quick-action-copy {
- font-size: 12px;
- line-height: 1.5;
- color: var(--ink-soft);
+ gap: 10px;
+ flex-wrap: wrap;
+ margin-top: 16px;
}
.overview-alert-list {
display: flex;
@@ -1100,17 +1091,22 @@ header .logout-btn:hover,
display: grid;
grid-template-columns: minmax(0, 1.65fr) minmax(320px, 0.92fr);
gap: 14px;
+ align-items: start;
}
.team-side-column {
display: flex;
flex-direction: column;
gap: 14px;
+ align-self: start;
}
.team-roster,
.team-invite-panel {
background: #fff;
border-color: var(--line);
}
+.team-roster {
+ align-self: start;
+}
.team-policy-panel {
padding: 16px;
border: 1px solid var(--line);
@@ -1695,9 +1691,6 @@ header .logout-btn:hover,
.account-metric-strip {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
- .overview-quick-actions {
- grid-template-columns: 1fr;
- }
.portal-shell-nav {
position: static;
}
@@ -1712,6 +1705,13 @@ header .logout-btn:hover,
.portal-shell-head-row {
grid-template-columns: 1fr;
}
+ .portal-account-bar {
+ grid-template-columns: 1fr;
+ align-items: start;
+ }
+ .portal-account-bar-row {
+ align-items: start;
+ }
.portal-shell-head-stats {
flex-wrap: wrap;
}
@@ -1742,11 +1742,12 @@ header .logout-btn:hover,
padding: 18px;
}
.portal-shell-head,
+ .portal-account-bar,
.portal-content-panel {
padding-left: 16px;
padding-right: 16px;
}
- .account-surface-header,
+ .portal-account-bar-row,
.workspace-management-header,
.team-management-header,
.service-header,
diff --git a/internal/cloudcp/portal/dist/portal_app.js b/internal/cloudcp/portal/dist/portal_app.js
index f03cc3161..ceb8c1d25 100644
--- a/internal/cloudcp/portal/dist/portal_app.js
+++ b/internal/cloudcp/portal/dist/portal_app.js
@@ -1695,9 +1695,6 @@
}).join("");
return '' + kicker + ' Self-hosted
' + title + " " + description + '
' + highlightHTML + '
Open
';
}
- function renderOverviewQuickAction(section, title, copy) {
- return '' + title + ' ' + copy + " ";
- }
function workspaceStatusCopy(workspace) {
var status = workspaceHealthState(workspace);
if (status === "healthy") return "Live updates and health checks are currently good.";
@@ -1737,6 +1734,20 @@
var summary = hosted ? "Hosted operations, operator access, and commercial account services." : "Billing, license recovery, refunds, and privacy actions until hosted access is attached.";
return 'Pulse Account
' + (hosted ? "Operator console" : "Account console") + ' ' + (hosted ? "Operator ready" : "Self-hosted only") + " " + statusText + " " + summary + '
Hosted access ' + (hosted ? "Active" : "Not attached") + '
Accounts ' + (accounts.length === 1 ? "1 account" : String(accounts.length) + " accounts") + '
Workspace fleet ' + (workspaceTotal ? workspaceCountLabel(workspaceTotal) : "0 workspaces") + "
";
}
+ function renderPrimaryAccountBar(account) {
+ var workspaceLabel = workspaceCountLabel((account.workspaces || []).length);
+ var actionHTML = "";
+ if (account.kind === "msp" && account.can_manage) {
+ actionHTML += 'Add workspace ';
+ }
+ if (account.has_billing && account.can_manage) {
+ actionHTML += 'Manage billing ';
+ }
+ if (account.can_manage) {
+ actionHTML += 'Manage team ';
+ }
+ return '' + escapeHTML(accountKindLabel(account)) + '
' + escapeHTML(account.name) + ' ' + escapeHTML(account.kind_label) + ' ' + escapeHTML(titleCase(account.role)) + ' ' + escapeHTML(workspaceLabel) + "
" + escapeHTML(account.kind === "msp" ? "Operator workspace account" : "Hosted account operations") + '
' + actionHTML + "
";
+ }
function shellSectionButton(section, activeSection, title, copy) {
return '' + title + ' ' + copy + " ";
}
@@ -1777,18 +1788,18 @@
var activeCount = countWorkspacesByState(workspaces, "active");
var postureTitle = unhealthyCount > 0 ? "Hosted posture needs review" : checkingCount > 0 ? "Hosted posture is still settling" : "Hosted posture is stable";
var postureCopy = unhealthyCount > 0 ? "One or more workspaces still need attention before the hosted fleet is trustworthy." : checkingCount > 0 ? "The hosted fleet is mostly healthy, but some workspaces are still waiting on a completed health check." : "The hosted fleet is healthy and ready for routine operator work.";
- var operationsCopy = account.kind === "msp" ? "Manage the client fleet from this account surface. Workspace creation, billing, and team actions belong here." : "Use this account surface to open hosted workspaces, manage billing, and control access for this hosted account.";
- var actions = "";
var addWorkspaceForm = "";
+ var nextStepTitle = unhealthyCount > 0 ? "Start in Workspaces" : checkingCount > 0 ? "Review pending checks" : "Fleet is clear";
+ var nextStepCopy = unhealthyCount > 0 ? "One or more workspaces need review before you treat the hosted fleet as trustworthy." : checkingCount > 0 ? "The fleet is mostly healthy, but there are still workspaces waiting on a completed health check." : "Hosted posture looks stable. Move into team or account services only if you need to change access or billing.";
+ var nextStepActions = '
Open workspaces ' + (account.can_manage ? "Review team access" : "Open account services") + "
";
if (account.can_manage) {
- actions = 'Account operations
' + escapeHTML(operationsCopy) + '
' + (account.kind === "msp" ? 'Add workspace ' : "") + (account.has_billing ? 'Manage billing ' : "") + 'Manage team
';
if (account.kind === "msp") {
addWorkspaceForm = '';
}
}
return 'Hosted posture
' + escapeHTML(postureTitle) + " " + escapeHTML(postureCopy) + '
' + escapeHTML(
account.kind === "msp" ? "Use this console to run client workspaces, account billing, and operator access from one place." : "Use this console to run hosted workspaces, account billing, and operator access from one place."
- ) + '
Active workspaces ' + String(activeCount) + '
Healthy ' + String(healthyCount) + '
Checking ' + String(checkingCount) + '
Needs attention ' + String(unhealthyCount) + "
" + actions + addWorkspaceForm + '
Operator overview
Start from the next action, not the whole account Use the overview for posture, then move into workspaces, team, or account services depending on what needs attention.
' + renderOverviewQuickAction("workspaces", "Open workspaces", "Review the hosted fleet and move into a workspace") + renderOverviewQuickAction("team", "Review team access", "Check who can operate billing and hosted workspaces") + renderOverviewQuickAction("services", "Open account services", "Handle billing, licenses, refunds, and privacy actions") + "
" + renderAttentionPanel(workspaces) + "
";
+ ) + 'Active workspaces ' + String(activeCount) + '
Healthy ' + String(healthyCount) + '
Checking ' + String(checkingCount) + '
Needs attention ' + String(unhealthyCount) + "
" + addWorkspaceForm + 'Next move
' + escapeHTML(nextStepTitle) + " " + escapeHTML(nextStepCopy) + "
" + nextStepActions + "
" + renderAttentionPanel(workspaces) + "
";
}
function renderAccountWorkspaceSection(account, accountAPIBasePath) {
var workspaces = Array.isArray(account.workspaces) ? account.workspaces : [];
@@ -1832,10 +1843,9 @@
var serviceHeading = hosted ? "Self-hosted licenses and billing" : "Account services";
var serviceNote = hosted ? "Hosted operations live above. Use these commercial tools for self-hosted licenses, billing, refunds, and privacy actions." : "Use these account tools for self-hosted licenses, billing, refunds, and privacy actions.";
var hostedContent = accounts.map(function(account) {
- var workspaceLabel = workspaceCountLabel((account.workspaces || []).length);
- return '' + renderAccountOverviewSection(account) + renderAccountWorkspaceSection(account, context.accountAPIBasePath) + renderAccountTeamSection(account) + "
";
+ return '' + renderAccountOverviewSection(account) + renderAccountWorkspaceSection(account, context.accountAPIBasePath) + renderAccountTeamSection(account) + "
";
}).join("");
- return '' + renderShellNavigation(accounts, context.bootstrap.support_email || "", activeSection) + '
' + renderOverviewBand(accounts) + '
Select a service
Choose the next commercial action Open a billing, license, refund, or privacy flow from the service navigator. The active request stays here so the account-services area behaves like one operating desk instead of a list of disconnected tools.
Start here
Billing Open Stripe customer portal access after verification.
Licenses Recover the latest active self-hosted license and invoice link.
Refunds Confirm eligibility before revoking active commercial access.
Privacy Request export or deletion without leaving Pulse Account.
What to expect
Verification first Each flow confirms the commercial email before opening sensitive account actions.
One task at a time The active commercial request stays in this panel until you finish or switch tools.
Support stays close If billing, licenses, refunds, or privacy behave unexpectedly, escalate from this surface.
Data and privacy Request export or deletion of the commercial data tied to an email address. Payment data held directly by Stripe still requires support handling.
Payment-card data stays with Stripe. For Stripe deletion support, contact
' + escapeHTML(context.bootstrap.support_email || "") + ' .
' + renderSupportSection(context) + " ";
+ return '' + renderShellNavigation(accounts, context.bootstrap.support_email || "", activeSection) + '
' + renderOverviewBand(accounts) + (accounts.length === 1 ? renderPrimaryAccountBar(accounts[0]) : "") + '
Select a service
Choose the next commercial action Open a billing, license, refund, or privacy flow from the service navigator. The active request stays here so the account-services area behaves like one operating desk instead of a list of disconnected tools.
Start here
Billing Open Stripe customer portal access after verification.
Licenses Recover the latest active self-hosted license and invoice link.
Refunds Confirm eligibility before revoking active commercial access.
Privacy Request export or deletion without leaving Pulse Account.
What to expect
Verification first Each flow confirms the commercial email before opening sensitive account actions.
One task at a time The active commercial request stays in this panel until you finish or switch tools.
Support stays close If billing, licenses, refunds, or privacy behave unexpectedly, escalate from this surface.
Data and privacy Request export or deletion of the commercial data tied to an email address. Payment data held directly by Stripe still requires support handling.
Payment-card data stays with Stripe. For Stripe deletion support, contact
' + escapeHTML(context.bootstrap.support_email || "") + ' .
' + renderSupportSection(context) + " ";
}
function renderSignedOutPortalHTML(context) {
var statusHTML = "";
diff --git a/internal/cloudcp/portal/frontend/src/shell_view.test.ts b/internal/cloudcp/portal/frontend/src/shell_view.test.ts
index 2ffa30d7c..68e68fe40 100644
--- a/internal/cloudcp/portal/frontend/src/shell_view.test.ts
+++ b/internal/cloudcp/portal/frontend/src/shell_view.test.ts
@@ -135,15 +135,17 @@ describe('shell view', function() {
expect(html).toContain('Support');
expect(html).toContain('id="account-services-section"');
expect(html).toContain('Self-hosted licenses and billing');
+ expect(html).toContain('portal-account-bar');
expect(html).toContain('id="accounts-root"');
expect(html).toContain('MSP account');
expect(html).toContain('Acme MSP');
expect(html).toContain('Operator workspace account');
expect(html).toContain('3 workspaces');
- expect(html).toContain('Account operations');
- expect(html).toContain('Manage the client fleet from this account surface.');
- expect(html).toContain('Operator overview');
- expect(html).toContain('Start from the next action, not the whole account');
+ expect(html).toContain('Add workspace');
+ expect(html).toContain('Manage billing');
+ expect(html).toContain('Manage team');
+ expect(html).toContain('Next move');
+ expect(html).toContain('Start in Workspaces');
expect(html).toContain('Hosted posture needs review');
expect(html).toContain('Use this console to run client workspaces, account billing, and operator access from one place.');
expect(html).toContain('Open workspaces');
diff --git a/internal/cloudcp/portal/frontend/src/shell_view.ts b/internal/cloudcp/portal/frontend/src/shell_view.ts
index 81836a878..c1234441f 100644
--- a/internal/cloudcp/portal/frontend/src/shell_view.ts
+++ b/internal/cloudcp/portal/frontend/src/shell_view.ts
@@ -134,15 +134,6 @@ function renderServiceActionRow(
);
}
-function renderOverviewQuickAction(section: PortalShellSection, title: string, copy: string): string {
- return (
- '' +
- '' + title + ' ' +
- '' + copy + ' ' +
- ' '
- );
-}
-
function workspaceStatusCopy(workspace: PortalWorkspaceSummary): string {
var status = workspaceHealthState(workspace);
if (status === 'healthy') return 'Live updates and health checks are currently good.';
@@ -242,6 +233,48 @@ function renderOverviewBand(accounts: PortalAccountSummary[]): string {
);
}
+function renderPrimaryAccountBar(account: PortalAccountSummary): string {
+ var workspaceLabel = workspaceCountLabel((account.workspaces || []).length);
+ var actionHTML = '';
+
+ if (account.kind === 'msp' && account.can_manage) {
+ actionHTML +=
+ 'Add workspace ';
+ }
+ if (account.has_billing && account.can_manage) {
+ actionHTML +=
+ 'Manage billing ';
+ }
+ if (account.can_manage) {
+ actionHTML +=
+ 'Manage team ';
+ }
+
+ return (
+ '' +
+ '' +
+ '
' + escapeHTML(accountKindLabel(account)) + '
' +
+ '
' +
+ '
' + escapeHTML(account.name) + ' ' +
+ '
' +
+ '' + escapeHTML(account.kind_label) + ' ' +
+ '' + escapeHTML(titleCase(account.role)) + ' ' +
+ '' + escapeHTML(workspaceLabel) + ' ' +
+ '
' +
+ '
' +
+ '
' + escapeHTML(account.kind === 'msp' ? 'Operator workspace account' : 'Hosted account operations') + '
' +
+ '
' +
+ '' + actionHTML + '
' +
+ ' '
+ );
+}
+
function shellSectionButton(section: PortalShellSection, activeSection: PortalShellSection, title: string, copy: string): string {
return (
'' +
@@ -350,40 +383,24 @@ function renderAccountOverviewSection(account: PortalAccountSummary): string {
: checkingCount > 0
? 'The hosted fleet is mostly healthy, but some workspaces are still waiting on a completed health check.'
: 'The hosted fleet is healthy and ready for routine operator work.';
- var operationsCopy = account.kind === 'msp'
- ? 'Manage the client fleet from this account surface. Workspace creation, billing, and team actions belong here.'
- : 'Use this account surface to open hosted workspaces, manage billing, and control access for this hosted account.';
-
- var actions = '';
var addWorkspaceForm = '';
- if (account.can_manage) {
- actions =
- '' +
- '
' +
- '
Account operations
' +
- '
' + escapeHTML(operationsCopy) + '
' +
- '
' +
- '
' +
- (account.kind === 'msp'
- ? 'Add workspace '
- : '') +
- (account.has_billing
- ? 'Manage billing '
- : '') +
- 'Manage team ' +
- '
' +
- '
';
+ var nextStepTitle = unhealthyCount > 0
+ ? 'Start in Workspaces'
+ : checkingCount > 0
+ ? 'Review pending checks'
+ : 'Fleet is clear';
+ var nextStepCopy = unhealthyCount > 0
+ ? 'One or more workspaces need review before you treat the hosted fleet as trustworthy.'
+ : checkingCount > 0
+ ? 'The fleet is mostly healthy, but there are still workspaces waiting on a completed health check.'
+ : 'Hosted posture looks stable. Move into team or account services only if you need to change access or billing.';
+ var nextStepActions =
+ '' +
+ 'Open workspaces ' +
+ '' + (account.can_manage ? 'Review team access' : 'Open account services') + ' ' +
+ '
';
+ if (account.can_manage) {
if (account.kind === 'msp') {
addWorkspaceForm =
'' +
@@ -716,21 +728,8 @@ export function renderAuthenticatedPortalHTML(context: ShellViewContext): string
? 'Hosted operations live above. Use these commercial tools for self-hosted licenses, billing, refunds, and privacy actions.'
: 'Use these account tools for self-hosted licenses, billing, refunds, and privacy actions.';
var hostedContent = accounts.map(function(account) {
- var workspaceLabel = workspaceCountLabel((account.workspaces || []).length);
return (
'' +
- '' +
'' +
renderAccountOverviewSection(account) +
renderAccountWorkspaceSection(account, context.accountAPIBasePath) +
@@ -746,6 +745,7 @@ export function renderAuthenticatedPortalHTML(context: ShellViewContext): string
renderShellNavigation(accounts, context.bootstrap.support_email || '', activeSection) +
'
' +
renderOverviewBand(accounts) +
+ (accounts.length === 1 ? renderPrimaryAccountBar(accounts[0]) : '') +
'
' +
'' + hostedContent + '
' +
' ' +
diff --git a/internal/cloudcp/portal/frontend/src/styles.css b/internal/cloudcp/portal/frontend/src/styles.css
index a94cbf65b..d550a39d0 100644
--- a/internal/cloudcp/portal/frontend/src/styles.css
+++ b/internal/cloudcp/portal/frontend/src/styles.css
@@ -430,6 +430,52 @@ header .logout-btn:hover,
display: none !important;
}
+.portal-account-bar {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) auto;
+ gap: 18px;
+ align-items: end;
+ padding: 16px 22px 18px;
+ border-bottom: 1px solid var(--line);
+ background: rgba(244, 247, 250, 0.92);
+}
+
+.portal-account-bar-copy {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+}
+
+.portal-account-bar-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 16px;
+ flex-wrap: wrap;
+}
+
+.portal-account-bar-row h2 {
+ margin: 0;
+ font-size: 28px;
+ line-height: 0.98;
+ letter-spacing: -0.05em;
+}
+
+.portal-account-bar-copy p {
+ margin: 0;
+ font-size: 13px;
+ line-height: 1.5;
+ color: var(--ink-soft);
+}
+
+.portal-account-bar-chips,
+.portal-account-bar-actions {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ flex-wrap: wrap;
+}
+
.portal-shell[data-shell-section="overview"] .portal-content-panel-overview,
.portal-shell[data-shell-section="services"] .portal-content-panel-services,
.portal-shell[data-shell-section="support"] .portal-content-panel-support,
@@ -513,32 +559,6 @@ header .logout-btn:hover,
margin-top: 22px;
}
-.account-surface-header {
- display: grid;
- grid-template-columns: minmax(0, 1fr) auto;
- align-items: end;
- gap: 16px;
- padding: 0 4px 12px;
- border: none;
- border-bottom: 1px solid var(--line);
- border-radius: var(--radius-md);
- background: transparent;
- box-shadow: none;
-}
-
-.account-heading h2 {
- margin: 2px 0 0;
- font-size: 24px;
- line-height: 1.02;
- letter-spacing: -0.05em;
-}
-
-.account-summary {
- margin-top: 5px;
- font-size: 12px;
- color: var(--ink-soft);
-}
-
.account-badges,
.account-context-strip,
.workspace-badges,
@@ -588,7 +608,6 @@ header .logout-btn:hover,
display: grid;
grid-template-columns: 1fr;
gap: 14px;
- margin-top: 10px;
}
.account-content-panel {
@@ -773,40 +792,11 @@ header .logout-btn:hover,
background: var(--panel-strong);
}
-.overview-quick-actions {
- display: grid;
- grid-template-columns: repeat(3, minmax(0, 1fr));
- gap: 10px;
- margin-top: 16px;
-}
-
-.overview-quick-action {
+.overview-next-actions {
display: flex;
- flex-direction: column;
- gap: 6px;
- padding: 14px;
- border: 1px solid var(--line);
- border-radius: 10px;
- background: #fff;
- text-align: left;
- cursor: pointer;
-}
-
-.overview-quick-action:hover {
- border-color: var(--accent);
- box-shadow: var(--shadow-sm);
-}
-
-.overview-quick-action-title {
- font-size: 14px;
- font-weight: 700;
- color: var(--ink);
-}
-
-.overview-quick-action-copy {
- font-size: 12px;
- line-height: 1.5;
- color: var(--ink-soft);
+ gap: 10px;
+ flex-wrap: wrap;
+ margin-top: 16px;
}
.overview-alert-list {
@@ -1233,12 +1223,14 @@ header .logout-btn:hover,
display: grid;
grid-template-columns: minmax(0, 1.65fr) minmax(320px, 0.92fr);
gap: 14px;
+ align-items: start;
}
.team-side-column {
display: flex;
flex-direction: column;
gap: 14px;
+ align-self: start;
}
.team-roster,
@@ -1247,6 +1239,10 @@ header .logout-btn:hover,
border-color: var(--line);
}
+.team-roster {
+ align-self: start;
+}
+
.team-policy-panel {
padding: 16px;
border: 1px solid var(--line);
@@ -1917,10 +1913,6 @@ header .logout-btn:hover,
grid-template-columns: repeat(2, minmax(0, 1fr));
}
- .overview-quick-actions {
- grid-template-columns: 1fr;
- }
-
.portal-shell-nav {
position: static;
}
@@ -1939,6 +1931,15 @@ header .logout-btn:hover,
grid-template-columns: 1fr;
}
+ .portal-account-bar {
+ grid-template-columns: 1fr;
+ align-items: start;
+ }
+
+ .portal-account-bar-row {
+ align-items: start;
+ }
+
.portal-shell-head-stats {
flex-wrap: wrap;
}
@@ -1976,12 +1977,13 @@ header .logout-btn:hover,
}
.portal-shell-head,
+ .portal-account-bar,
.portal-content-panel {
padding-left: 16px;
padding-right: 16px;
}
- .account-surface-header,
+ .portal-account-bar-row,
.workspace-management-header,
.team-management-header,
.service-header,