mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-23 20:25:56 +00:00
feat(portal): replace sidebar shell with top command bar
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"source_hash": "f7b726f8e8d6c01630420d83fad1e59f7947f386a570d1715f0165f958c39410",
|
||||
"source_hash": "3ee5dcea0783b4085b4a7feb3fd0dcee628b4280042752af29256a685db8a466",
|
||||
"build_inputs": [
|
||||
"package.json",
|
||||
"tsconfig.json",
|
||||
|
||||
+38
-37
@@ -232,26 +232,18 @@ header .logout-btn:hover,
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.04em;
|
||||
}
|
||||
.portal-frame {
|
||||
.portal-shell-bar {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(220px, 250px) minmax(0, 1fr);
|
||||
gap: 22px;
|
||||
align-items: start;
|
||||
}
|
||||
.portal-rail {
|
||||
position: sticky;
|
||||
top: 88px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 16px;
|
||||
align-items: stretch;
|
||||
}
|
||||
.portal-section-nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
.portal-section-link,
|
||||
.portal-rail-panel,
|
||||
.intro-card,
|
||||
.service-panel,
|
||||
.account-surface,
|
||||
@@ -287,30 +279,41 @@ header .logout-btn:hover,
|
||||
line-height: 1.5;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
.portal-rail-panel {
|
||||
border-radius: var(--radius-md);
|
||||
padding: 20px;
|
||||
}
|
||||
.portal-rail-panel h3 {
|
||||
margin: 8px 0 10px;
|
||||
font-size: 23px;
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.04em;
|
||||
}
|
||||
.portal-rail-panel p {
|
||||
margin: 0;
|
||||
color: var(--ink-soft);
|
||||
line-height: 1.6;
|
||||
}
|
||||
.portal-support-link,
|
||||
.support-link,
|
||||
.service-panel .helper-text a {
|
||||
color: var(--accent-strong);
|
||||
font-weight: 600;
|
||||
}
|
||||
.portal-support-link {
|
||||
display: inline-block;
|
||||
margin-top: 14px;
|
||||
.portal-support-strip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
min-width: 340px;
|
||||
padding: 16px 18px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-md);
|
||||
background: rgba(255, 255, 255, 0.98);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
.portal-support-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
.portal-support-label {
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--ink-muted);
|
||||
}
|
||||
.portal-support-text {
|
||||
max-width: 280px;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
.portal-stage {
|
||||
display: flex;
|
||||
@@ -896,17 +899,15 @@ header .logout-btn:hover,
|
||||
background: #6e1414;
|
||||
}
|
||||
@media (max-width: 1180px) {
|
||||
.portal-frame,
|
||||
.account-management-grid,
|
||||
.team-management-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.portal-rail {
|
||||
position: static;
|
||||
.portal-shell-bar {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.portal-section-nav {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
.portal-support-strip {
|
||||
min-width: 0;
|
||||
}
|
||||
.account-overview-rail {
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
+1
-1
@@ -1672,7 +1672,7 @@
|
||||
var hosted = hasHostedAccounts(accounts);
|
||||
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.";
|
||||
return '<div class="portal-shell">' + renderOverviewBand(accounts) + '<div class="portal-frame"><aside class="portal-rail">' + renderShellNavigation(accounts, context.bootstrap.support_email || "") + '<div class="portal-rail-panel"><div class="account-panel-kicker">Support</div><h3>One account surface</h3><p>This portal should be the place where hosted access and commercial account actions meet. Hosted workspaces sit above. Self-hosted services remain available below.</p><a class="portal-support-link" href="mailto:' + escapeAttr(context.bootstrap.support_email || "") + '">' + escapeHTML(context.bootstrap.support_email || "") + '</a></div></aside><div class="portal-stage"><section class="portal-top-section" id="hosted-operations-section"><div class="portal-top-section-header"><div class="account-panel-kicker">' + (hosted ? "Hosted operations" : "Hosted access") + "</div><h2>" + (hosted ? "Run hosted accounts from one place" : "No hosted workspaces are attached yet") + "</h2><p>" + (hosted ? "Use this area for workspace access, fleet operations, hosted billing, and team management." : "This account does not currently have hosted workspace access. If that is unexpected, contact support while using the commercial tools below.") + '</p></div><div id="accounts-root">' + renderAccountsHTML(context) + '</div></section><section class="service-section" id="account-services-section"><div class="service-header"><div><div class="account-panel-kicker">Account services</div><h2>' + serviceHeading + '</h2></div><div class="service-note">' + serviceNote + '</div></div><div class="service-grid"><button class="service-card service-card-button" type="button" id="open-manage-service" data-account-service-action="open-service-panel" data-account-service-panel="manage-service-panel" data-account-service-focus="manage-inline-email"><span class="service-card-kicker">Billing</span><h3>Manage subscriptions</h3><p>Open Stripe billing access for existing self-hosted subscriptions without leaving the Pulse Account shell.</p></button><button class="service-card service-card-button" type="button" id="open-retrieve-service" data-account-service-action="open-service-panel" data-account-service-panel="retrieve-service-panel" data-account-service-focus="retrieve-inline-email"><span class="service-card-kicker">Licenses</span><h3>Retrieve licenses</h3><p>Recover the latest active self-hosted license and invoice link for a commercial email address.</p></button><button class="service-card service-card-button" type="button" id="open-refund-service" data-account-service-action="open-service-panel" data-account-service-panel="refund-service-panel" data-account-service-focus="refund-inline-email"><span class="service-card-kicker">Refunds</span><h3>Refund requests</h3><p>Request an immediate self-serve refund for eligible self-hosted purchases with explicit revocation confirmation.</p></button><button class="service-card service-card-button" type="button" id="open-data-service" data-account-service-action="open-service-panel" data-account-service-panel="data-service-panel" data-account-service-focus="data-export-email"><span class="service-card-kicker">Privacy</span><h3>Data and privacy</h3><p>Request commercial data export or deletion without leaving the account shell.</p></button></div><div class="service-panel" id="manage-service-panel"><div id="manage-service-root"></div></div><div class="service-panel" id="retrieve-service-panel"><div id="retrieve-service-root"></div></div><div class="service-panel" id="refund-service-panel"><div id="refund-service-root"></div></div><div class="service-panel" id="data-service-panel"><h3>Data and privacy</h3><p>Request export or deletion of the commercial data tied to an email address. Payment data held directly by Stripe still requires support handling.</p><div class="subsection"><div id="data-export-root"></div></div><div class="subsection"><div id="data-delete-root"></div></div><div class="helper-text">Payment-card data stays with Stripe. For Stripe deletion support, contact <a href="mailto:' + escapeAttr(context.bootstrap.support_email || "") + '">' + escapeHTML(context.bootstrap.support_email || "") + "</a>.</div></div></section></div></div></div>";
|
||||
return '<div class="portal-shell">' + renderOverviewBand(accounts) + '<div class="portal-shell-bar">' + renderShellNavigation(accounts, context.bootstrap.support_email || "") + '<div class="portal-support-strip"><div class="portal-support-copy"><span class="portal-support-label">Support</span><span class="portal-support-text">Hosted operations and commercial account tools now share one account surface.</span></div><a class="portal-support-link" href="mailto:' + escapeAttr(context.bootstrap.support_email || "") + '">' + escapeHTML(context.bootstrap.support_email || "") + '</a></div></div><section class="portal-top-section" id="hosted-operations-section"><div class="portal-top-section-header"><div class="account-panel-kicker">' + (hosted ? "Hosted operations" : "Hosted access") + "</div><h2>" + (hosted ? "Run hosted accounts from one place" : "No hosted workspaces are attached yet") + "</h2><p>" + (hosted ? "Use this area for workspace access, fleet operations, hosted billing, and team management." : "This account does not currently have hosted workspace access. If that is unexpected, contact support while using the commercial tools below.") + '</p></div><div id="accounts-root">' + renderAccountsHTML(context) + '</div></section><section class="service-section" id="account-services-section"><div class="service-header"><div><div class="account-panel-kicker">Account services</div><h2>' + serviceHeading + '</h2></div><div class="service-note">' + serviceNote + '</div></div><div class="service-grid"><button class="service-card service-card-button" type="button" id="open-manage-service" data-account-service-action="open-service-panel" data-account-service-panel="manage-service-panel" data-account-service-focus="manage-inline-email"><span class="service-card-kicker">Billing</span><h3>Manage subscriptions</h3><p>Open Stripe billing access for existing self-hosted subscriptions without leaving the Pulse Account shell.</p></button><button class="service-card service-card-button" type="button" id="open-retrieve-service" data-account-service-action="open-service-panel" data-account-service-panel="retrieve-service-panel" data-account-service-focus="retrieve-inline-email"><span class="service-card-kicker">Licenses</span><h3>Retrieve licenses</h3><p>Recover the latest active self-hosted license and invoice link for a commercial email address.</p></button><button class="service-card service-card-button" type="button" id="open-refund-service" data-account-service-action="open-service-panel" data-account-service-panel="refund-service-panel" data-account-service-focus="refund-inline-email"><span class="service-card-kicker">Refunds</span><h3>Refund requests</h3><p>Request an immediate self-serve refund for eligible self-hosted purchases with explicit revocation confirmation.</p></button><button class="service-card service-card-button" type="button" id="open-data-service" data-account-service-action="open-service-panel" data-account-service-panel="data-service-panel" data-account-service-focus="data-export-email"><span class="service-card-kicker">Privacy</span><h3>Data and privacy</h3><p>Request commercial data export or deletion without leaving the account shell.</p></button></div><div class="service-panel" id="manage-service-panel"><div id="manage-service-root"></div></div><div class="service-panel" id="retrieve-service-panel"><div id="retrieve-service-root"></div></div><div class="service-panel" id="refund-service-panel"><div id="refund-service-root"></div></div><div class="service-panel" id="data-service-panel"><h3>Data and privacy</h3><p>Request export or deletion of the commercial data tied to an email address. Payment data held directly by Stripe still requires support handling.</p><div class="subsection"><div id="data-export-root"></div></div><div class="subsection"><div id="data-delete-root"></div></div><div class="helper-text">Payment-card data stays with Stripe. For Stripe deletion support, contact <a href="mailto:' + escapeAttr(context.bootstrap.support_email || "") + '">' + escapeHTML(context.bootstrap.support_email || "") + "</a>.</div></div></section></div>";
|
||||
}
|
||||
function renderSignedOutPortalHTML(context) {
|
||||
var statusHTML = "";
|
||||
|
||||
@@ -497,74 +497,71 @@ export function renderAuthenticatedPortalHTML(context: ShellViewContext): string
|
||||
return (
|
||||
'<div class="portal-shell">' +
|
||||
renderOverviewBand(accounts) +
|
||||
'<div class="portal-frame">' +
|
||||
'<aside class="portal-rail">' +
|
||||
renderShellNavigation(accounts, context.bootstrap.support_email || '') +
|
||||
'<div class="portal-rail-panel">' +
|
||||
'<div class="account-panel-kicker">Support</div>' +
|
||||
'<h3>One account surface</h3>' +
|
||||
'<p>This portal should be the place where hosted access and commercial account actions meet. Hosted workspaces sit above. Self-hosted services remain available below.</p>' +
|
||||
'<a class="portal-support-link" href="mailto:' + escapeAttr(context.bootstrap.support_email || '') + '">' + escapeHTML(context.bootstrap.support_email || '') + '</a>' +
|
||||
'<div class="portal-shell-bar">' +
|
||||
renderShellNavigation(accounts, context.bootstrap.support_email || '') +
|
||||
'<div class="portal-support-strip">' +
|
||||
'<div class="portal-support-copy">' +
|
||||
'<span class="portal-support-label">Support</span>' +
|
||||
'<span class="portal-support-text">Hosted operations and commercial account tools now share one account surface.</span>' +
|
||||
'</div>' +
|
||||
'</aside>' +
|
||||
'<div class="portal-stage">' +
|
||||
'<section class="portal-top-section" id="hosted-operations-section">' +
|
||||
'<div class="portal-top-section-header">' +
|
||||
'<div class="account-panel-kicker">' + (hosted ? 'Hosted operations' : 'Hosted access') + '</div>' +
|
||||
'<h2>' + (hosted ? 'Run hosted accounts from one place' : 'No hosted workspaces are attached yet') + '</h2>' +
|
||||
'<p>' + (hosted
|
||||
? 'Use this area for workspace access, fleet operations, hosted billing, and team management.'
|
||||
: 'This account does not currently have hosted workspace access. If that is unexpected, contact support while using the commercial tools below.') + '</p>' +
|
||||
'</div>' +
|
||||
'<div id="accounts-root">' + renderAccountsHTML(context) + '</div>' +
|
||||
'</section>' +
|
||||
'<section class="service-section" id="account-services-section">' +
|
||||
'<div class="service-header">' +
|
||||
'<div>' +
|
||||
'<div class="account-panel-kicker">Account services</div>' +
|
||||
'<h2>' + serviceHeading + '</h2>' +
|
||||
'</div>' +
|
||||
'<div class="service-note">' + serviceNote + '</div>' +
|
||||
'</div>' +
|
||||
'<div class="service-grid">' +
|
||||
'<button class="service-card service-card-button" type="button" id="open-manage-service" data-account-service-action="open-service-panel" data-account-service-panel="manage-service-panel" data-account-service-focus="manage-inline-email">' +
|
||||
'<span class="service-card-kicker">Billing</span>' +
|
||||
'<h3>Manage subscriptions</h3>' +
|
||||
'<p>Open Stripe billing access for existing self-hosted subscriptions without leaving the Pulse Account shell.</p>' +
|
||||
'</button>' +
|
||||
'<button class="service-card service-card-button" type="button" id="open-retrieve-service" data-account-service-action="open-service-panel" data-account-service-panel="retrieve-service-panel" data-account-service-focus="retrieve-inline-email">' +
|
||||
'<span class="service-card-kicker">Licenses</span>' +
|
||||
'<h3>Retrieve licenses</h3>' +
|
||||
'<p>Recover the latest active self-hosted license and invoice link for a commercial email address.</p>' +
|
||||
'</button>' +
|
||||
'<button class="service-card service-card-button" type="button" id="open-refund-service" data-account-service-action="open-service-panel" data-account-service-panel="refund-service-panel" data-account-service-focus="refund-inline-email">' +
|
||||
'<span class="service-card-kicker">Refunds</span>' +
|
||||
'<h3>Refund requests</h3>' +
|
||||
'<p>Request an immediate self-serve refund for eligible self-hosted purchases with explicit revocation confirmation.</p>' +
|
||||
'</button>' +
|
||||
'<button class="service-card service-card-button" type="button" id="open-data-service" data-account-service-action="open-service-panel" data-account-service-panel="data-service-panel" data-account-service-focus="data-export-email">' +
|
||||
'<span class="service-card-kicker">Privacy</span>' +
|
||||
'<h3>Data and privacy</h3>' +
|
||||
'<p>Request commercial data export or deletion without leaving the account shell.</p>' +
|
||||
'</button>' +
|
||||
'</div>' +
|
||||
'<div class="service-panel" id="manage-service-panel"><div id="manage-service-root"></div></div>' +
|
||||
'<div class="service-panel" id="retrieve-service-panel"><div id="retrieve-service-root"></div></div>' +
|
||||
'<div class="service-panel" id="refund-service-panel"><div id="refund-service-root"></div></div>' +
|
||||
'<div class="service-panel" id="data-service-panel">' +
|
||||
'<h3>Data and privacy</h3>' +
|
||||
'<p>Request export or deletion of the commercial data tied to an email address. Payment data held directly by Stripe still requires support handling.</p>' +
|
||||
'<div class="subsection"><div id="data-export-root"></div></div>' +
|
||||
'<div class="subsection"><div id="data-delete-root"></div></div>' +
|
||||
'<div class="helper-text">Payment-card data stays with Stripe. For Stripe deletion support, contact <a href="mailto:' +
|
||||
escapeAttr(context.bootstrap.support_email || '') +
|
||||
'">' +
|
||||
escapeHTML(context.bootstrap.support_email || '') +
|
||||
'</a>.</div>' +
|
||||
'</div>' +
|
||||
'</section>' +
|
||||
'<a class="portal-support-link" href="mailto:' + escapeAttr(context.bootstrap.support_email || '') + '">' + escapeHTML(context.bootstrap.support_email || '') + '</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<section class="portal-top-section" id="hosted-operations-section">' +
|
||||
'<div class="portal-top-section-header">' +
|
||||
'<div class="account-panel-kicker">' + (hosted ? 'Hosted operations' : 'Hosted access') + '</div>' +
|
||||
'<h2>' + (hosted ? 'Run hosted accounts from one place' : 'No hosted workspaces are attached yet') + '</h2>' +
|
||||
'<p>' + (hosted
|
||||
? 'Use this area for workspace access, fleet operations, hosted billing, and team management.'
|
||||
: 'This account does not currently have hosted workspace access. If that is unexpected, contact support while using the commercial tools below.') + '</p>' +
|
||||
'</div>' +
|
||||
'<div id="accounts-root">' + renderAccountsHTML(context) + '</div>' +
|
||||
'</section>' +
|
||||
'<section class="service-section" id="account-services-section">' +
|
||||
'<div class="service-header">' +
|
||||
'<div>' +
|
||||
'<div class="account-panel-kicker">Account services</div>' +
|
||||
'<h2>' + serviceHeading + '</h2>' +
|
||||
'</div>' +
|
||||
'<div class="service-note">' + serviceNote + '</div>' +
|
||||
'</div>' +
|
||||
'<div class="service-grid">' +
|
||||
'<button class="service-card service-card-button" type="button" id="open-manage-service" data-account-service-action="open-service-panel" data-account-service-panel="manage-service-panel" data-account-service-focus="manage-inline-email">' +
|
||||
'<span class="service-card-kicker">Billing</span>' +
|
||||
'<h3>Manage subscriptions</h3>' +
|
||||
'<p>Open Stripe billing access for existing self-hosted subscriptions without leaving the Pulse Account shell.</p>' +
|
||||
'</button>' +
|
||||
'<button class="service-card service-card-button" type="button" id="open-retrieve-service" data-account-service-action="open-service-panel" data-account-service-panel="retrieve-service-panel" data-account-service-focus="retrieve-inline-email">' +
|
||||
'<span class="service-card-kicker">Licenses</span>' +
|
||||
'<h3>Retrieve licenses</h3>' +
|
||||
'<p>Recover the latest active self-hosted license and invoice link for a commercial email address.</p>' +
|
||||
'</button>' +
|
||||
'<button class="service-card service-card-button" type="button" id="open-refund-service" data-account-service-action="open-service-panel" data-account-service-panel="refund-service-panel" data-account-service-focus="refund-inline-email">' +
|
||||
'<span class="service-card-kicker">Refunds</span>' +
|
||||
'<h3>Refund requests</h3>' +
|
||||
'<p>Request an immediate self-serve refund for eligible self-hosted purchases with explicit revocation confirmation.</p>' +
|
||||
'</button>' +
|
||||
'<button class="service-card service-card-button" type="button" id="open-data-service" data-account-service-action="open-service-panel" data-account-service-panel="data-service-panel" data-account-service-focus="data-export-email">' +
|
||||
'<span class="service-card-kicker">Privacy</span>' +
|
||||
'<h3>Data and privacy</h3>' +
|
||||
'<p>Request commercial data export or deletion without leaving the account shell.</p>' +
|
||||
'</button>' +
|
||||
'</div>' +
|
||||
'<div class="service-panel" id="manage-service-panel"><div id="manage-service-root"></div></div>' +
|
||||
'<div class="service-panel" id="retrieve-service-panel"><div id="retrieve-service-root"></div></div>' +
|
||||
'<div class="service-panel" id="refund-service-panel"><div id="refund-service-root"></div></div>' +
|
||||
'<div class="service-panel" id="data-service-panel">' +
|
||||
'<h3>Data and privacy</h3>' +
|
||||
'<p>Request export or deletion of the commercial data tied to an email address. Payment data held directly by Stripe still requires support handling.</p>' +
|
||||
'<div class="subsection"><div id="data-export-root"></div></div>' +
|
||||
'<div class="subsection"><div id="data-delete-root"></div></div>' +
|
||||
'<div class="helper-text">Payment-card data stays with Stripe. For Stripe deletion support, contact <a href="mailto:' +
|
||||
escapeAttr(context.bootstrap.support_email || '') +
|
||||
'">' +
|
||||
escapeHTML(context.bootstrap.support_email || '') +
|
||||
'</a>.</div>' +
|
||||
'</div>' +
|
||||
'</section>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -243,29 +243,20 @@ header .logout-btn:hover,
|
||||
letter-spacing: -0.04em;
|
||||
}
|
||||
|
||||
.portal-frame {
|
||||
.portal-shell-bar {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(220px, 250px) minmax(0, 1fr);
|
||||
gap: 22px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.portal-rail {
|
||||
position: sticky;
|
||||
top: 88px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 16px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.portal-section-nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.portal-section-link,
|
||||
.portal-rail-panel,
|
||||
.intro-card,
|
||||
.service-panel,
|
||||
.account-surface,
|
||||
@@ -303,24 +294,6 @@ header .logout-btn:hover,
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
|
||||
.portal-rail-panel {
|
||||
border-radius: var(--radius-md);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.portal-rail-panel h3 {
|
||||
margin: 8px 0 10px;
|
||||
font-size: 23px;
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.04em;
|
||||
}
|
||||
|
||||
.portal-rail-panel p {
|
||||
margin: 0;
|
||||
color: var(--ink-soft);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.portal-support-link,
|
||||
.support-link,
|
||||
.service-panel .helper-text a {
|
||||
@@ -328,9 +301,38 @@ header .logout-btn:hover,
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.portal-support-link {
|
||||
display: inline-block;
|
||||
margin-top: 14px;
|
||||
.portal-support-strip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
min-width: 340px;
|
||||
padding: 16px 18px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-md);
|
||||
background: rgba(255, 255, 255, 0.98);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.portal-support-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.portal-support-label {
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--ink-muted);
|
||||
}
|
||||
|
||||
.portal-support-text {
|
||||
max-width: 280px;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
|
||||
.portal-stage {
|
||||
@@ -1002,19 +1004,17 @@ header .logout-btn:hover,
|
||||
.toast.error { background: #6e1414; }
|
||||
|
||||
@media (max-width: 1180px) {
|
||||
.portal-frame,
|
||||
.account-management-grid,
|
||||
.team-management-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.portal-rail {
|
||||
position: static;
|
||||
.portal-shell-bar {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.portal-section-nav {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
.portal-support-strip {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.account-overview-rail {
|
||||
|
||||
Reference in New Issue
Block a user