Record project continuation changes
This commit is contained in:
+478
-11
@@ -149,7 +149,14 @@ button.danger {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.sideRail {
|
||||
.portalShell {
|
||||
display: grid;
|
||||
grid-template-columns: 280px minmax(0, 1fr);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.sideRail,
|
||||
.portalRail {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
@@ -160,6 +167,11 @@ button.danger {
|
||||
radial-gradient(circle at 20% 20%, rgba(184, 111, 35, 0.36), transparent 16rem);
|
||||
}
|
||||
|
||||
.portalRail button {
|
||||
width: 100%;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.brandMark {
|
||||
display: inline-grid;
|
||||
width: 58px;
|
||||
@@ -183,7 +195,8 @@ button.danger {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.sideRail h1 {
|
||||
.sideRail h1,
|
||||
.portalRail h1 {
|
||||
margin: 0 0 12px;
|
||||
font-size: clamp(2.3rem, 4vw, 4.2rem);
|
||||
line-height: 0.9;
|
||||
@@ -218,9 +231,15 @@ button.danger {
|
||||
padding: 28px 28px 54px;
|
||||
}
|
||||
|
||||
.topBar {
|
||||
.portalWorkspace {
|
||||
width: min(1280px, calc(100vw - 310px));
|
||||
padding: 28px 28px 54px;
|
||||
}
|
||||
|
||||
.topBar,
|
||||
.portalTop {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(260px, 360px) auto minmax(220px, auto);
|
||||
grid-template-columns: minmax(0, 1fr) minmax(260px, 360px) auto minmax(150px, auto) minmax(220px, auto);
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
padding: 28px;
|
||||
@@ -231,6 +250,10 @@ button.danger {
|
||||
backdrop-filter: blur(16px);
|
||||
}
|
||||
|
||||
.portalTop {
|
||||
grid-template-columns: minmax(0, 1fr) minmax(240px, 340px) auto;
|
||||
}
|
||||
|
||||
.clusterPicker {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
@@ -248,6 +271,25 @@ button.danger {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.refreshStatus {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
min-width: 150px;
|
||||
color: var(--muted);
|
||||
font-size: 0.78rem;
|
||||
font-weight: 800;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.refreshStatus strong {
|
||||
color: var(--text);
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
.refreshStatus span {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.profilePanel {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
@@ -441,6 +483,69 @@ summary {
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.cardHead.compact {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.subPanel {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
padding: 16px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
|
||||
.portalInstallList {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.installTile {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
padding: 16px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 18px;
|
||||
color: var(--ink);
|
||||
background: rgba(255, 255, 255, 0.52);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.installTile:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.installTile strong {
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
.installTile span,
|
||||
.installTile small {
|
||||
color: var(--muted);
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.primaryInstall {
|
||||
border-color: rgba(47, 111, 79, 0.35);
|
||||
background: rgba(47, 111, 79, 0.1);
|
||||
}
|
||||
|
||||
.portalRoadmap {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.portalRoadmap span {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 14px;
|
||||
background: rgba(255, 255, 255, 0.48);
|
||||
color: var(--muted);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.vpnCard {
|
||||
grid-template-columns: minmax(0, 1.2fr) minmax(220px, 0.8fr) auto;
|
||||
padding: 16px 0;
|
||||
@@ -476,7 +581,7 @@ summary {
|
||||
|
||||
.nodeListRow {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(240px, 1.2fr) auto minmax(110px, 0.55fr) minmax(130px, 0.7fr) auto auto;
|
||||
grid-template-columns: minmax(220px, 1.1fr) auto minmax(220px, 0.9fr) minmax(150px, 0.7fr) auto minmax(180px, 0.8fr) minmax(130px, 0.7fr) auto auto;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px;
|
||||
@@ -496,6 +601,43 @@ summary {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.runtimeBadges {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.runtimeBadges .pill {
|
||||
padding: 0.24rem 0.52rem;
|
||||
font-size: 0.68rem;
|
||||
}
|
||||
|
||||
.nodeEndpointCell {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.nodeEndpointCell .pill {
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
padding: 0.28rem 0.58rem;
|
||||
font-size: 0.72rem;
|
||||
}
|
||||
|
||||
.nodeEndpointCell strong,
|
||||
.nodeEndpointCell small {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.nodeEndpointCell small {
|
||||
color: var(--muted);
|
||||
font-size: 0.74rem;
|
||||
}
|
||||
|
||||
.functionList {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
@@ -513,6 +655,41 @@ summary {
|
||||
background: rgba(255, 255, 255, 0.42);
|
||||
}
|
||||
|
||||
.functionState {
|
||||
min-width: 96px;
|
||||
display: grid;
|
||||
gap: 2px;
|
||||
padding: 8px 10px;
|
||||
border-radius: 14px;
|
||||
background: rgba(16, 43, 35, 0.06);
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.functionState small {
|
||||
color: var(--muted);
|
||||
font-size: 0.68rem;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.functionState strong {
|
||||
font-size: 0.76rem;
|
||||
}
|
||||
|
||||
.functionState.good {
|
||||
background: rgba(36, 118, 84, 0.14);
|
||||
color: var(--green);
|
||||
}
|
||||
|
||||
.functionState.info {
|
||||
background: rgba(41, 80, 111, 0.12);
|
||||
color: var(--blue);
|
||||
}
|
||||
|
||||
.functionState.warn {
|
||||
background: rgba(175, 110, 46, 0.15);
|
||||
color: #8a4f19;
|
||||
}
|
||||
|
||||
.nodePanel {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
@@ -522,6 +699,111 @@ summary {
|
||||
background: rgba(255, 255, 255, 0.42);
|
||||
}
|
||||
|
||||
.nodeDetails {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.nodeDetailGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.nodeMetricGrid {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.summaryChips {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.inlineActions {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.stackedText {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.nodeTabs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
padding: 8px 0;
|
||||
background: rgba(249, 247, 239, 0.94);
|
||||
}
|
||||
|
||||
.nodeTabs button {
|
||||
min-width: 92px;
|
||||
padding: 0.55rem 0.8rem;
|
||||
}
|
||||
|
||||
.nodeTabs button.active {
|
||||
color: #fffaf0;
|
||||
border-color: transparent;
|
||||
background: #36556c;
|
||||
}
|
||||
|
||||
.rawDetailsGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.rawBlock {
|
||||
min-width: 0;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 12px;
|
||||
background: rgba(255, 255, 255, 0.42);
|
||||
}
|
||||
|
||||
.rawBlock summary {
|
||||
cursor: pointer;
|
||||
padding: 10px 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.rawBlock pre {
|
||||
max-height: 320px;
|
||||
margin: 0;
|
||||
overflow: auto;
|
||||
padding: 0 12px 12px;
|
||||
font-size: 0.78rem;
|
||||
line-height: 1.45;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.segmented {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.segmented button {
|
||||
min-width: 84px;
|
||||
padding: 0.52rem 0.85rem;
|
||||
}
|
||||
|
||||
.segmented button.active {
|
||||
color: #fffaf0;
|
||||
border-color: transparent;
|
||||
background: #36556c;
|
||||
}
|
||||
|
||||
.stateList {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
@@ -621,11 +903,21 @@ summary {
|
||||
background: rgba(47, 111, 79, 0.12);
|
||||
}
|
||||
|
||||
.pill.info {
|
||||
color: var(--steel);
|
||||
background: rgba(54, 85, 108, 0.1);
|
||||
}
|
||||
|
||||
.pill.bad {
|
||||
color: var(--red);
|
||||
background: rgba(177, 68, 52, 0.12);
|
||||
}
|
||||
|
||||
.pill.warn {
|
||||
color: var(--amber);
|
||||
background: rgba(184, 111, 35, 0.14);
|
||||
}
|
||||
|
||||
.membershipList {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -691,7 +983,8 @@ summary {
|
||||
|
||||
.topologySvg {
|
||||
width: 100%;
|
||||
min-height: 440px;
|
||||
min-height: 520px;
|
||||
max-height: 78vh;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 22px;
|
||||
color: rgba(24, 32, 24, 0.42);
|
||||
@@ -750,12 +1043,25 @@ summary {
|
||||
stroke: var(--amber);
|
||||
}
|
||||
|
||||
.topologyLink.oneWay {
|
||||
color: var(--amber);
|
||||
stroke: var(--amber);
|
||||
stroke-dasharray: 4 7;
|
||||
}
|
||||
|
||||
.topologyLink.bad {
|
||||
color: var(--red);
|
||||
stroke: var(--red);
|
||||
stroke-dasharray: 10 8;
|
||||
}
|
||||
|
||||
.topologyLink.stale {
|
||||
color: var(--red);
|
||||
stroke: var(--red);
|
||||
stroke-dasharray: 2 8;
|
||||
opacity: 0.42;
|
||||
}
|
||||
|
||||
.topologyPlacementLink {
|
||||
stroke: var(--steel);
|
||||
stroke-width: 3;
|
||||
@@ -774,6 +1080,15 @@ summary {
|
||||
stroke: var(--amber);
|
||||
}
|
||||
|
||||
.topologyConfiguredLink {
|
||||
color: var(--steel);
|
||||
stroke: var(--steel);
|
||||
stroke-width: 2.5;
|
||||
stroke-linecap: round;
|
||||
stroke-dasharray: 4 7;
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
.topologyLinkLabel,
|
||||
.topologyNodeName,
|
||||
.topologyNodeMeta,
|
||||
@@ -834,6 +1149,7 @@ summary {
|
||||
}
|
||||
|
||||
.topologyNodeCircle.critical,
|
||||
.topologyNodeCircle.offline,
|
||||
.topologyNodeCircle.failed {
|
||||
stroke: var(--red);
|
||||
}
|
||||
@@ -884,6 +1200,22 @@ summary {
|
||||
border-color: var(--amber);
|
||||
}
|
||||
|
||||
.legendLine.oneWay {
|
||||
border-top-style: dashed;
|
||||
border-color: var(--amber);
|
||||
}
|
||||
|
||||
.legendLine.stale,
|
||||
.legendLine.problem {
|
||||
border-top-style: dashed;
|
||||
border-color: var(--red);
|
||||
}
|
||||
|
||||
.legendLine.configured {
|
||||
border-top-style: dashed;
|
||||
border-color: var(--steel);
|
||||
}
|
||||
|
||||
.serviceTags {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
@@ -944,13 +1276,25 @@ summary {
|
||||
.status.active,
|
||||
.status.approved,
|
||||
.status.healthy,
|
||||
.status.connected,
|
||||
.status.current,
|
||||
.status.running,
|
||||
.status.authoritative {
|
||||
background: var(--green);
|
||||
}
|
||||
|
||||
.status.outdated,
|
||||
.status.no_policy {
|
||||
background: var(--amber);
|
||||
}
|
||||
|
||||
.status.rejected,
|
||||
.status.failed,
|
||||
.status.critical,
|
||||
.status.missing,
|
||||
.status.offline,
|
||||
.status.stale,
|
||||
.status.unreachable,
|
||||
.status.disabled,
|
||||
.status.revoked {
|
||||
background: var(--red);
|
||||
@@ -996,6 +1340,23 @@ th {
|
||||
background: var(--green);
|
||||
}
|
||||
|
||||
.noticePanel.goodPanel {
|
||||
background: var(--green);
|
||||
}
|
||||
|
||||
.noticePanel.warnPanel {
|
||||
background: var(--amber);
|
||||
}
|
||||
|
||||
.noticePanel.badPanel {
|
||||
background: var(--red);
|
||||
}
|
||||
|
||||
.noticePanel .muted,
|
||||
.noticePanel .stateLine span {
|
||||
color: rgba(255, 255, 255, 0.78);
|
||||
}
|
||||
|
||||
.formGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(180px, 1fr));
|
||||
@@ -1060,10 +1421,30 @@ th {
|
||||
margin: 18px 0;
|
||||
}
|
||||
|
||||
.inlineForm input {
|
||||
.inlineForm input,
|
||||
.inlineForm select {
|
||||
flex: 1 1 320px;
|
||||
}
|
||||
|
||||
.diagnosticCommandPanel {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
margin: 12px 0 18px;
|
||||
padding: 14px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 18px;
|
||||
background: rgba(255, 255, 255, 0.42);
|
||||
}
|
||||
|
||||
.diagnosticCommandPanel label {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.diagnosticCommandPanel input {
|
||||
min-width: min(520px, 100%);
|
||||
}
|
||||
|
||||
.secretOnce {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
@@ -1087,16 +1468,19 @@ code {
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.consoleShell {
|
||||
.consoleShell,
|
||||
.portalShell {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.sideRail {
|
||||
.sideRail,
|
||||
.portalRail {
|
||||
position: relative;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.workspace {
|
||||
.workspace,
|
||||
.portalWorkspace {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -1105,7 +1489,10 @@ code {
|
||||
.grid.two,
|
||||
.controlBar,
|
||||
.topBar,
|
||||
.portalTop,
|
||||
.loginShell,
|
||||
.nodeDetailGrid,
|
||||
.rawDetailsGrid,
|
||||
.vpnCard {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
@@ -1121,11 +1508,91 @@ code {
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
body {
|
||||
background: #f4f1e7;
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
button {
|
||||
min-height: 46px;
|
||||
}
|
||||
|
||||
.workspace,
|
||||
.sideRail {
|
||||
.portalWorkspace,
|
||||
.sideRail,
|
||||
.portalRail {
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
.loginShell {
|
||||
align-items: start;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.loginCard {
|
||||
padding: 18px;
|
||||
border-radius: 18px;
|
||||
}
|
||||
|
||||
.portalRail {
|
||||
height: auto;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.portalRail .brandMark,
|
||||
.portalRail .sideKicker,
|
||||
.portalRail .sideText {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.portalRail h1 {
|
||||
margin: 0;
|
||||
font-size: 2rem;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.portalTop,
|
||||
.card,
|
||||
.metric,
|
||||
.empty,
|
||||
.errorPanel,
|
||||
.noticePanel {
|
||||
border-radius: 18px;
|
||||
}
|
||||
|
||||
.portalTop {
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
.portalTop h2 {
|
||||
font-size: 2rem;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.portalInstallList,
|
||||
.stack,
|
||||
.grid {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.installTile {
|
||||
border-radius: 14px;
|
||||
}
|
||||
|
||||
.metric {
|
||||
min-height: 96px;
|
||||
}
|
||||
|
||||
.metric strong {
|
||||
font-size: 2.2rem;
|
||||
}
|
||||
|
||||
.formGrid,
|
||||
.signalStrip,
|
||||
.clusterCardMain,
|
||||
|
||||
Reference in New Issue
Block a user