Refactor web UI: feature-first structure, tokenized styles, modern blue theme.

Structure
- pages/ -> features/<domain>/{Page, components, hooks, lib}; 95 files moved,
  333 imports rewritten, verified with tsc.
- services/api.ts -> services/api/<domain>.ts (250 exports preserved),
  types.ts -> types/<domain>.ts, i18n zh/en -> locales/<lang>/<namespace>.ts
  (2696 messages deep-equal before/after).
- ESLint rule: shared layers must not import features/.

Styles
- index.css (16k lines) split losslessly into styles/{base,layout,components,
  pages,legacy,theme}; compiled CSS was byte-identical before tokenizing.
- ~930 hard-coded colors replaced by --nx-* tokens (theme/tokens.css); WebCRT
  off-palette colors unified; fixed dark-on-dark text introduced by mapping.
- theme/theme.css: modern blue design language (rounded shapes, gradients,
  unified buttons/fields/tables/modals), form-grid alignment fix, flat nav list
  without tree indent, soft selected state instead of left accent bar.

Docs: WEB.md documents code structure and style rules.
Not touched: the large Biz*/Webcrt/Topology page components (to be split later).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
oliver 2026-10-12 03:17:51 +08:00
parent 3b45d6abe3
commit 0d894efe5e
196 changed files with 26947 additions and 28091 deletions

View file

@ -0,0 +1,45 @@
/* Base: HeroUI token alignment, scrollbars, body */
* {
box-sizing: border-box;
}
html {
color-scheme: dark;
scrollbar-color: var(--nx-line-strong) var(--nx-surface-2);
scrollbar-width: thin;
}
*::-webkit-scrollbar {
width: 10px;
height: 10px;
}
*::-webkit-scrollbar-track {
background: var(--nx-surface-2);
}
*::-webkit-scrollbar-thumb {
background: var(--nx-line-strong);
border: 2px solid var(--nx-surface-2);
border-radius: 999px;
}
*::-webkit-scrollbar-thumb:hover {
background: var(--nx-text-faint);
}
*::-webkit-scrollbar-corner {
background: var(--nx-surface-2);
}
body {
margin: 0;
font-family: "Segoe UI", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
background: #070b14;
color: var(--nx-text);
}
#root {
min-height: 100vh;
}

View file

@ -0,0 +1,855 @@
/* Shared primitives: header menu, buttons, inputs, cards, tables, pills, toast, spinner, help-hint */
.header-menu__panel--light {
background: var(--nx-surface-2);
border-color: var(--nx-line);
box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
}
.header-menu__label--light {
color: var(--nx-text-muted);
}
.header-menu__item--light {
color: var(--nx-text);
}
.header-menu__item--light:hover {
background: var(--nx-text-strong);
color: var(--nx-surface-2);
}
.header-menu__item--active-light {
background: #e3f2fd;
color: var(--nm-accent, var(--nx-accent-strong));
}
.header-menu {
position: relative;
}
.header-menu__trigger {
min-width: 36px;
height: 36px;
padding: 0 10px;
font-size: 20px;
line-height: 1;
letter-spacing: 0.12em;
}
.header-menu__trigger:hover,
.header-menu__trigger:focus-visible {
border-color: #3d82f7;
outline: none;
}
.header-menu__panel {
position: absolute;
top: calc(100% + 6px);
right: 0;
z-index: 50;
min-width: 148px;
padding: 6px;
border: 1px solid #2c405f;
border-radius: 10px;
background: #0f1e34;
box-shadow: 0 10px 28px rgba(0, 0, 0, 0.35);
}
.header-menu__label {
padding: 6px 10px 4px;
font-size: 11px;
color: #6b7f9c;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.header-menu__item {
display: block;
width: 100%;
text-align: left;
padding: 8px 10px;
border: none;
border-radius: 6px;
background: transparent;
color: #c1cde0;
font-size: 13px;
cursor: pointer;
}
.header-menu__item:hover {
background: rgba(61, 130, 247, 0.14);
color: #dce8ff;
}
.header-menu__item--active {
background: rgba(61, 130, 247, 0.22);
color: #dce8ff;
}
.app-main button,
.app-main select,
.app-main input,
.app-main textarea {
border: 1px solid var(--nm-panel-border, var(--nx-line));
background: var(--nx-field);
color: var(--nm-text, var(--nx-text));
border-radius: 6px;
padding: 8px 10px;
}
button,
select,
input,
textarea {
border: 1px solid var(--nm-panel-border, var(--nx-line));
background: var(--nx-field);
color: var(--nm-text, var(--nx-text));
border-radius: 6px;
padding: 8px 10px;
}
textarea {
width: 100%;
resize: vertical;
}
button {
cursor: pointer;
}
.cards {
display: grid;
grid-template-columns: repeat(3, minmax(220px, 1fr));
gap: 12px;
margin-bottom: 12px;
}
.app-main .card,
.app-main .panel {
border: 1px solid var(--nm-ops-line, var(--nm-panel-border, var(--nx-line)));
background: var(--nm-panel-solid, var(--nx-surface-1));
border-radius: 6px;
padding: 14px;
box-shadow: none;
color: var(--nm-text, var(--nx-text));
}
.card,
.panel {
border: 1px solid var(--nm-ops-line, var(--nm-panel-border, var(--nx-line)));
background: var(--nm-panel-solid, var(--nx-surface-1));
border-radius: 6px;
padding: 14px;
box-shadow: none;
color: var(--nm-text, var(--nx-text));
}
.card h3,
.panel h2 {
margin: 0 0 10px;
font-size: 16px;
}
.card__section-title {
margin: 14px 0 8px;
font-size: 14px;
font-weight: 600;
}
.card input:not([type="checkbox"]):not([type="radio"]),
.card select,
.card textarea {
width: 100%;
margin-bottom: 8px;
}
.card input[type="checkbox"],
.card input[type="radio"] {
width: auto;
margin-bottom: 0;
flex: 0 0 auto;
}
.pager input,
.pager select {
width: auto;
margin-bottom: 0;
}
.actions-row {
margin-top: 8px;
}
.actions-row--inline {
display: flex;
gap: 8px;
flex-wrap: nowrap;
overflow-x: auto;
}
.card--full {
grid-column: 1 / -1;
}
.filter-inline {
display: grid;
grid-template-columns: minmax(280px, 2fr) minmax(180px, 1fr) minmax(180px, 1fr) 180px;
gap: 8px;
align-items: center;
}
.filter-inline input,
.filter-inline select {
width: 100%;
margin-bottom: 0;
}
a {
color: var(--nm-accent, var(--nx-accent-strong));
text-decoration: none;
}
.muted {
color: var(--nx-text-muted);
}
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
border-bottom: 1px solid var(--nm-panel-border, var(--nx-line));
padding: 8px;
text-align: left;
font-size: 13px;
vertical-align: top;
color: var(--nm-text, var(--nx-text));
}
th {
color: var(--nm-muted, var(--nx-text-muted));
font-weight: 600;
}
.split {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
}
pre {
white-space: pre-wrap;
margin: 0;
background: var(--nx-surface-2);
color: var(--nx-text);
border: 1px solid #223651;
border-radius: 8px;
padding: 10px;
}
.ws-log-panel {
margin-top: 12px;
max-height: 240px;
overflow-y: auto;
background: rgb(var(--nx-ink-deep-rgb) / 0.55);
border: 1px solid rgba(148, 163, 184, 0.2);
border-radius: 8px;
padding: 8px 10px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 12px;
line-height: 1.45;
color: var(--nx-text-soft);
}
.ws-log-line {
padding: 3px 0;
border-bottom: 1px solid rgba(148, 163, 184, 0.12);
word-break: break-word;
}
.ws-log-line:last-child {
border-bottom: none;
}
.ws-log-line--error {
color: #fca5a5;
}
.ws-log-line--warning {
color: #fdba74;
}
.ws-log-line--info {
color: var(--nx-text-muted);
}
.ws-log-ts {
color: var(--nx-text-muted);
margin-right: 8px;
}
.pill {
margin-top: 8px;
padding: 6px 10px;
border-radius: 6px;
width: fit-content;
font-size: 12px;
background: rgba(148, 163, 184, 0.12);
color: var(--nx-text-soft);
border: 1px solid rgba(148, 163, 184, 0.22);
}
.pill--high {
background: rgba(239, 68, 68, 0.16);
border-color: rgba(248, 113, 113, 0.35);
color: #fecaca;
}
.pill--medium {
background: rgba(245, 158, 11, 0.14);
border-color: rgba(251, 191, 36, 0.35);
color: #fde68a;
}
.pill--low {
background: rgba(34, 197, 94, 0.14);
border-color: rgba(74, 222, 128, 0.3);
color: #bbf7d0;
}
.link-btn {
border: none;
background: transparent;
color: var(--nm-accent, var(--nx-accent-strong));
padding: 0;
cursor: pointer;
}
.link-btn--danger {
color: #f87171;
}
.link-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.table-actions {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
.status {
margin-top: 12px;
color: #9db2cf;
font-size: 12px;
}
.app-main .conn-pill:not(.conn-pill--on-brand) {
font-size: 12px;
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 999px;
padding: 4px 10px;
background: rgb(var(--nx-ink-rgb) / 0.75);
color: var(--nx-text-soft);
}
.conn-pill {
font-size: 12px;
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 999px;
padding: 4px 10px;
background: rgb(var(--nx-ink-rgb) / 0.75);
color: var(--nx-text-soft);
}
.conn-pill--up {
border-color: rgba(74, 222, 128, 0.4);
color: #86efac;
background: rgba(34, 197, 94, 0.14);
}
.conn-pill--down {
border-color: rgba(248, 113, 113, 0.4);
color: #fca5a5;
background: rgba(239, 68, 68, 0.14);
}
.conn-pill--unknown {
border-color: rgba(148, 163, 184, 0.3);
color: var(--nx-text-muted);
background: rgba(148, 163, 184, 0.1);
}
/* Brand header chips/buttons — must follow global button/conn-pill rules. */
.app-brand .conn-pill.conn-pill--on-brand {
display: inline-flex;
align-items: center;
gap: 6px;
height: 24px;
padding: 0 10px;
border: 1px solid rgba(255, 255, 255, 0.16);
border-radius: 999px;
background: rgba(255, 255, 255, 0.08);
color: rgba(255, 255, 255, 0.82);
font-size: 11px;
font-weight: 400;
line-height: 1;
white-space: nowrap;
}
.app-brand .conn-pill.conn-pill--on-brand::before {
content: "";
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--nx-text-muted);
flex-shrink: 0;
}
.app-brand .conn-pill.conn-pill--on-brand.conn-pill--up {
border-color: rgba(255, 255, 255, 0.16);
background: rgba(255, 255, 255, 0.08);
color: rgba(255, 255, 255, 0.82);
}
.app-brand .conn-pill.conn-pill--on-brand.conn-pill--up::before {
background: #4ade80;
}
.app-brand .conn-pill.conn-pill--on-brand.conn-pill--down {
border-color: rgba(248, 113, 113, 0.35);
background: rgba(127, 29, 29, 0.35);
color: #fecaca;
}
.app-brand .conn-pill.conn-pill--on-brand.conn-pill--down::before {
background: #f87171;
}
.app-brand .conn-pill.conn-pill--on-brand.conn-pill--unknown {
border-color: rgba(255, 255, 255, 0.16);
background: rgba(255, 255, 255, 0.08);
color: rgba(255, 255, 255, 0.7);
}
.app-brand .conn-pill.conn-pill--on-brand.conn-pill--unknown::before {
background: var(--nx-text-muted);
}
.app-brand .conn-pill.conn-pill--on-brand.conn-pill--user {
background: rgba(255, 255, 255, 0.08);
border-color: rgba(255, 255, 255, 0.16);
color: rgba(255, 255, 255, 0.78);
font-size: 11px;
font-weight: 400;
}
.app-brand .conn-pill.conn-pill--on-brand.conn-pill--user::before {
display: none;
}
.app-brand button.conn-pill.conn-pill--on-brand.conn-pill--tasks {
cursor: pointer;
font: inherit;
font-size: 11px;
font-weight: 400;
}
.app-brand button.conn-pill.conn-pill--on-brand.conn-pill--tasks:hover,
.app-brand button.conn-pill.conn-pill--on-brand.conn-pill--tasks:focus-visible {
border-color: rgb(var(--nx-accent-rgb) / 0.55);
background: rgb(var(--nx-accent-rgb) / 0.22);
color: #fff;
outline: none;
}
.app-brand .header-menu__trigger.header-menu__trigger--on-brand {
display: inline-flex;
align-items: center;
justify-content: center;
height: 24px;
min-width: 24px;
padding: 0 10px;
border: 1px solid rgba(255, 255, 255, 0.16);
border-radius: 999px;
background: rgba(255, 255, 255, 0.08);
color: rgba(255, 255, 255, 0.78);
font-size: 11px;
font-weight: 400;
letter-spacing: normal;
line-height: 1;
box-shadow: none;
}
.app-brand .header-menu__trigger.header-menu__trigger--on-brand.header-menu__trigger--icon {
width: 24px;
padding: 0;
font-size: 14px;
letter-spacing: 0.06em;
}
.app-brand .header-menu__trigger.header-menu__trigger--on-brand.header-menu__trigger--locale {
min-width: 36px;
padding: 0 8px;
font-size: 11px;
font-weight: 650;
letter-spacing: 0.04em;
}
.app-brand .header-menu__trigger.header-menu__trigger--on-brand:hover,
.app-brand .header-menu__trigger.header-menu__trigger--on-brand:focus-visible {
background: rgb(var(--nx-accent-rgb) / 0.22);
border-color: rgb(var(--nx-accent-rgb) / 0.55);
color: #fff;
}
.app-brand .conn-pill.conn-pill--on-brand.conn-pill--up {
border-color: rgb(var(--nx-accent-rgb) / 0.35);
}
.app-brand button.conn-pill.conn-pill--on-brand.conn-pill--tasks:hover,
.app-brand button.conn-pill.conn-pill--on-brand.conn-pill--tasks:focus-visible {
border-color: rgb(var(--nx-accent-rgb) / 0.55);
background: rgb(var(--nx-accent-rgb) / 0.22);
color: #fff;
outline: none;
}
.toast,
.app-toast {
position: fixed;
right: max(12px, env(safe-area-inset-right, 0px));
bottom: max(12px, env(safe-area-inset-bottom, 0px));
left: auto;
top: auto;
margin: 0;
padding: 8px 12px;
border-radius: 8px;
border: 1px solid rgba(148, 163, 184, 0.28);
background: var(--nx-surface-2);
color: var(--nx-text);
font-size: 12.5px;
font-weight: 500;
line-height: 1.35;
z-index: 10050;
width: max-content;
max-width: min(280px, calc(100vw - 24px));
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.45);
pointer-events: none;
word-break: break-word;
}
.toast--ok,
.app-toast--ok {
border-color: rgba(74, 222, 128, 0.35);
background: rgba(20, 83, 45, 0.92);
color: #bbf7d0;
}
.toast--error,
.app-toast--error {
border-color: rgba(248, 113, 113, 0.4);
background: rgba(127, 29, 29, 0.92);
color: #fecaca;
}
.inline-spinner {
display: inline-block;
width: 14px;
height: 14px;
margin-right: 8px;
border: 2px solid rgba(255, 255, 255, 0.22);
border-top-color: rgba(255, 255, 255, 0.85);
border-radius: 50%;
vertical-align: -2px;
animation: inline-spin 0.65s linear infinite;
}
@keyframes inline-spin {
to {
transform: rotate(360deg);
}
}
.conn-pill--warn {
border-color: rgba(251, 191, 36, 0.4);
color: #fde68a;
background: rgba(245, 158, 11, 0.14);
}
.app-main .inline-spinner {
border-color: rgba(21, 101, 192, 0.2);
border-top-color: var(--nm-accent, var(--nx-accent-strong));
}
.skeleton-line {
height: 32px;
border-radius: 8px;
margin-bottom: 10px;
background: linear-gradient(90deg, #14253e 25%, #1d3558 50%, #14253e 75%);
background-size: 200% 100%;
animation: shimmer 1.4s infinite;
}
.mini-chart {
margin-top: 10px;
}
.mini-chart__row {
display: grid;
grid-template-columns: 70px 1fr 36px;
gap: 8px;
align-items: center;
margin-bottom: 8px;
}
.mini-chart__label,
.mini-chart__value {
font-size: 12px;
color: #a8bad5;
}
.card-title-with-hint {
display: flex;
align-items: center;
gap: 8px;
margin: 0;
}
.help-hint {
position: relative;
display: inline-flex;
vertical-align: middle;
}
.app-main .help-hint__trigger,
.help-hint__trigger {
width: auto;
height: auto;
min-width: 0;
padding: 0 2px;
border: none;
border-radius: 0;
background: transparent;
box-shadow: none;
color: var(--nx-text-faint);
font-size: 13px;
font-weight: 700;
line-height: 1;
cursor: pointer;
}
.app-main .help-hint__trigger:hover,
.app-main .help-hint__trigger:focus-visible,
.help-hint__trigger:hover,
.help-hint__trigger:focus-visible {
border: none;
background: transparent;
box-shadow: none;
color: var(--nm-accent, var(--nx-accent-strong));
outline: none;
}
.help-hint__popover {
position: absolute;
top: calc(100% + 6px);
left: 0;
z-index: 40;
width: min(360px, 80vw);
padding: 10px 12px;
border: 1px solid var(--nm-ops-line, var(--nx-line));
border-radius: 6px;
background: var(--nx-surface-1);
color: #d7e3f2;
font-size: 12px;
font-weight: 400;
line-height: 1.5;
white-space: pre-line;
box-shadow: none;
overflow: auto;
}
.help-hint--align-end .help-hint__popover {
left: auto;
right: 0;
}
.help-hint__popover--portal {
z-index: 2000;
width: auto;
}
.help-hint__popover--structured {
width: min(420px, 86vw);
white-space: normal;
padding: 12px 14px;
}
.help-hint__popover--nowrap {
width: max-content;
max-width: min(90vw, 720px);
white-space: nowrap;
}
.help-hint__body {
display: flex;
flex-direction: column;
gap: 10px;
min-width: 0;
}
.help-hint__plain {
white-space: pre-line;
}
.help-hint__section-title {
margin: 2px 0 0;
padding-bottom: 5px;
border-bottom: 1px solid var(--nm-ops-line, var(--nx-line));
color: var(--nm-ops-accent, var(--nx-accent));
font-size: 11px;
font-weight: 650;
letter-spacing: 0.06em;
text-transform: uppercase;
line-height: 1.35;
}
.help-hint__section-title:first-child {
margin-top: 0;
}
.help-hint__list {
margin: 0;
padding: 0 0 0 1.05rem;
display: flex;
flex-direction: column;
gap: 5px;
color: var(--nm-ops-muted, var(--nx-text-muted));
}
.help-hint__list > li {
padding-left: 2px;
line-height: 1.45;
}
.help-hint__list > li::marker {
color: #526f94;
}
.help-hint__para {
margin: 0;
color: var(--nm-ops-muted, var(--nx-text-muted));
line-height: 1.5;
}
.help-hint__code {
display: inline;
padding: 0 4px;
border: 1px solid rgba(43, 55, 72, 0.9);
border-radius: 3px;
background: var(--nx-surface-2);
color: #c4ddfa;
font: 11px/1.45 ui-monospace, SFMono-Regular, Consolas, monospace;
white-space: nowrap;
}
.panel__toolbar-end {
margin-left: auto;
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.stat-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 12px;
}
.stat-card {
border: 1px solid var(--border, rgba(148, 163, 184, 0.22));
border-radius: 8px;
padding: 12px 14px;
background: var(--panel-bg, rgb(var(--nx-ink-rgb) / 0.72));
color: var(--nm-text, var(--nx-text));
}
.stat-card strong {
display: block;
margin-top: 4px;
font-size: 1.05rem;
}
.btn-row {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
.btn-primary {
background: var(--nx-accent-strong);
color: #fff;
border-color: #1d4ed8;
}
.btn-primary:disabled {
opacity: 0.55;
}
.data-table {
width: 100%;
}
.config-sync-policy-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 10px 16px;
}
.config-sync-policy-check {
display: inline-flex;
align-items: center;
gap: 6px;
margin: 0;
font-size: 13px;
color: var(--nx-text-soft);
white-space: nowrap;
cursor: pointer;
}
.config-sync-policy-check input {
width: 14px;
height: 14px;
margin: 0;
flex-shrink: 0;
}
.config-sync-policy-field {
display: inline-flex;
align-items: center;
gap: 6px;
margin: 0;
font-size: 13px;
color: var(--nx-text-soft);
white-space: nowrap;
}
.config-sync-policy-field input[type="number"] {
width: 64px;
margin: 0;
}
.config-sync-policy-field select {
width: auto;
min-width: 110px;
margin: 0;
}

View file

@ -0,0 +1,105 @@
/* App shell + brand header (.app--shell, .app-brand, .app-main) */
.app--shell {
/* --nm-* chrome tokens: see styles/theme/tokens.css */
display: flex;
flex-direction: column;
min-height: 100vh;
color: var(--nm-text);
}
.app-brand {
display: flex;
align-items: center;
justify-content: space-between;
height: 48px;
padding: 0 20px;
background: var(--nm-header, #0f1b2d);
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
box-shadow: none;
}
.app-brand__logo {
font-size: 18px;
font-weight: 700;
letter-spacing: 0.12em;
color: #fff;
text-decoration: none;
flex-shrink: 0;
line-height: 1;
}
.app-brand__logo--static {
display: inline-block;
}
.app-brand__sep {
width: 1px;
height: 16px;
background: rgba(255, 255, 255, 0.22);
flex-shrink: 0;
}
.app-brand__start {
display: flex;
align-items: center;
gap: 12px;
min-width: 0;
}
.app-brand__apps {
display: inline-flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
padding: 0;
border: none;
border-radius: 4px;
background: transparent;
color: rgba(255, 255, 255, 0.88);
cursor: pointer;
}
.app-brand__apps:hover,
.app-brand__apps:focus-visible {
background: rgb(var(--nx-accent-rgb) / 0.22);
color: #fff;
outline: none;
}
.app-brand__module-title {
font-size: 14px;
font-weight: 500;
color: rgba(255, 255, 255, 0.92);
white-space: nowrap;
letter-spacing: 0.02em;
}
.app-brand__actions {
display: flex;
align-items: center;
gap: 8px;
flex-shrink: 0;
}
.app-brand__actions-group {
display: inline-flex;
align-items: center;
gap: 6px;
}
.app-brand__actions-sep {
width: 1px;
height: 14px;
margin: 0 4px;
background: rgba(255, 255, 255, 0.18);
flex-shrink: 0;
}
.app-main {
flex: 1;
padding: 20px 28px 32px;
background: var(--nm-chrome, #e8eef6);
color: var(--nm-text, var(--nx-line));
}

View file

@ -0,0 +1,691 @@
/* Network / audit shell (left nav + main), ops list chrome, shared dialogs */
/* —— Network Management shell (left nav + main) ——
Fill the app chrome without a second document scrollbar.
Negative margins + 100vh used to fight app-main padding and over-expand the page. */
.app--shell:has(.network-shell),
.app--shell:has(.audit-shell) {
height: 100vh;
max-height: 100vh;
overflow: hidden;
}
.app-main:has(> .network-shell),
.app-main:has(> .audit-shell) {
flex: 1 1 auto;
min-height: 0;
padding: 0;
overflow: hidden;
display: flex;
flex-direction: column;
}
.network-shell {
display: flex;
flex: 1 1 auto;
width: 100%;
min-height: 0;
height: auto;
margin: 0;
background: var(--nm-chrome);
overflow: hidden;
}
.network-nav {
width: 232px;
flex-shrink: 0;
display: flex;
flex-direction: column;
background: #0a121c;
border-right: 1px solid var(--nm-ops-line);
min-height: 0;
color: var(--nm-text);
box-shadow: none;
}
.network-nav__scroll {
flex: 1;
min-height: 0;
overflow: auto;
padding: 8px 8px 16px;
}
.network-nav__accordion.accordion {
width: 100%;
background: transparent;
border: 0;
border-radius: 0;
contain: none;
}
.network-nav__group {
margin: 0 0 2px;
border-radius: 0;
background: transparent;
}
.network-nav__group.is-active-group {
background: transparent;
}
.app-main .network-nav__group-toggle,
.network-nav__group-toggle,
.network-nav .accordion__trigger.network-nav__group-toggle {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
padding: 8px 10px;
border: 0;
border-radius: 4px;
background: transparent;
color: var(--nm-ops-muted);
font-size: 11px;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
text-align: left;
cursor: pointer;
}
.app-main .network-nav__group-toggle:hover,
.network-nav__group-toggle:hover,
.network-nav .accordion__trigger.network-nav__group-toggle:hover {
background: rgb(var(--nx-ink-rgb) / 0.8);
color: #d7e6f8;
}
.network-nav__group.is-active-group .network-nav__group-toggle,
.network-nav__group.is-active-group .accordion__trigger.network-nav__group-toggle {
color: var(--nm-ops-accent);
background: transparent;
}
.network-nav__chevron,
.network-nav .accordion__indicator.network-nav__chevron {
display: inline-flex;
width: 12px;
height: 12px;
color: var(--nx-text-faint);
flex-shrink: 0;
opacity: 0.85;
}
.network-nav__group.is-active-group .network-nav__chevron,
.network-nav__group.is-active-group .accordion__indicator.network-nav__chevron {
color: var(--nm-ops-accent);
}
.network-nav__group-label {
flex: 1;
min-width: 0;
}
.network-nav .accordion__body-inner.network-nav__panel-body,
.network-nav .network-nav__panel-body {
padding: 0 0 6px !important;
color: inherit !important;
}
.network-nav__list {
list-style: none;
margin: 0;
padding: 0 0 0 6px;
display: flex;
flex-direction: column;
gap: 1px;
border-left: 1px solid var(--nm-ops-line);
margin-left: 14px;
}
.network-nav__list > li {
width: 100%;
}
.network-nav__link {
display: block;
box-sizing: border-box;
width: 100%;
padding: 7px 10px;
border-radius: 4px;
color: var(--nm-ops-muted);
text-decoration: none;
font-size: 13px;
line-height: 1.35;
border: 0;
box-shadow: none;
transition:
background 120ms ease,
color 120ms ease;
}
.network-nav__link:hover {
background: var(--nm-ops-surface);
color: #e8f0fa;
}
.network-nav__link.is-active {
background: rgb(var(--nx-accent-rgb) / 0.1);
color: #edf5ff;
font-weight: 600;
box-shadow: inset 0 0 0 1px rgb(var(--nx-accent-rgb) / 0.3);
}
.network-nav__brand {
padding: 14px 14px 12px;
font-size: 12px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: #edf5ff;
border-bottom: 1px solid var(--nm-ops-line);
background: var(--nx-surface-1);
}
.network-nav__list--flat {
padding: 0;
margin-left: 0;
border-left: 0;
gap: 1px;
}
.audit-shell .network-main {
overflow: auto;
}
.network-main {
flex: 1;
min-width: 0;
min-height: 0;
overflow: auto;
padding: 20px 22px 28px;
background:
radial-gradient(1200px 480px at 0% 0%, rgb(var(--nx-accent-rgb) / 0.07), transparent 55%),
var(--nm-main, var(--nm-chrome));
}
/* Compact ops chrome (aligned with biz-monitor / biz-compare). */
.network-main > .panel,
.network-main .page-stack > .panel,
.network-main > .nm-page-panel {
padding: 18px 20px 20px;
border: 1px solid var(--nm-ops-line);
border-radius: 6px;
background: var(--nx-surface-1);
box-shadow: none;
}
.network-main .panel__toolbar {
margin-bottom: 16px;
padding-bottom: 14px;
border-bottom: 1px solid var(--nm-ops-line);
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.network-main .panel__toolbar h2 {
margin: 0;
font-size: 18px;
font-weight: 650;
color: var(--nm-brand);
letter-spacing: -0.02em;
}
.network-main .button,
.network-main .input,
.network-main .ui-field__select {
border-radius: 4px;
box-shadow: none;
}
.network-main .filter-inline {
display: flex;
flex-wrap: wrap;
gap: 10px;
align-items: center;
margin-bottom: 0;
padding: 12px 14px;
border: 1px solid var(--nm-ops-line);
border-radius: 4px;
background: rgb(var(--nx-ink-deep-rgb) / 0.45);
grid-template-columns: none;
}
.network-main .filter-inline input,
.network-main .filter-inline > select {
width: auto;
min-width: 140px;
flex: 1 1 160px;
max-width: 280px;
height: 34px;
margin: 0;
border: 1px solid var(--nm-ops-line);
border-radius: 4px;
background: var(--nx-field);
color: var(--nx-text);
padding: 0 12px;
font-size: 13px;
}
/* FieldSelect wrapper is the flex item; nested select must NOT inherit flex-basis as height */
.network-main .filter-inline > .ui-field {
flex: 1 1 160px;
max-width: 280px;
min-width: 140px;
align-self: center;
gap: 0;
}
.network-main .filter-inline > .ui-field > .ui-field__select {
width: 100%;
height: 34px;
min-height: 34px;
max-height: 34px;
flex: none;
margin: 0;
border: 1px solid var(--nm-ops-line);
border-radius: 4px;
background: var(--nx-field);
color: var(--nx-text);
padding: 0 12px;
font-size: 13px;
}
.network-main .filter-inline button {
height: 34px;
flex: 0 0 auto;
}
.network-main .pt-list {
gap: 14px;
}
.network-main .pt-list-kpis {
gap: 0;
border: 1px solid var(--nm-ops-line);
border-radius: 4px;
overflow: hidden;
background: var(--nm-ops-surface);
}
.network-main .pt-list-kpi {
border: 0;
border-right: 1px solid var(--nm-ops-line);
border-radius: 0;
background: transparent;
}
.network-main .pt-list-kpi:last-child {
border-right: 0;
}
.network-main .pt-list-kpi__value {
font-family: ui-monospace, Consolas, monospace;
}
.network-main .pt-list-kpi__label {
font-size: 11px;
color: var(--nm-ops-muted);
}
.network-main .pt-list-table-wrap {
border: 1px solid var(--nm-ops-line);
border-radius: 4px;
overflow: hidden;
background: rgb(var(--nx-ink-deep-rgb) / 0.28);
}
.network-main .pt-list-table {
margin: 0;
}
.network-main .pt-list-table thead th {
background: var(--nx-surface-3);
color: var(--nx-text-muted);
font-size: 11px;
font-weight: 600;
letter-spacing: 0.02em;
text-transform: uppercase;
padding-top: 12px;
padding-bottom: 12px;
}
.network-main .pt-list-table tbody td {
padding-top: 11px;
padding-bottom: 11px;
font-size: 12px;
border-bottom-color: var(--nm-ops-line);
}
.network-main .pt-list-table tbody tr:last-child td {
border-bottom: 0;
}
.network-main .pt-list-actions .button,
.network-main .table-actions .button {
min-height: 28px;
}
@media (max-width: 800px) {
.network-main .pt-list-kpis {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.network-main .pt-list-kpi:nth-child(2) {
border-right: 0;
}
.network-main .pt-list-kpi:nth-child(-n+2) {
border-bottom: 1px solid var(--nm-ops-line);
}
}
.network-main .pager.pt-list-pager,
.network-main .pt-list-pager {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 10px;
margin-top: 4px;
padding-top: 4px;
}
.pt-port-updown {
display: inline-flex;
flex-wrap: wrap;
align-items: center;
gap: 4px;
}
.pt-port-updown .conn-pill {
min-width: 2.4em;
justify-content: center;
text-transform: lowercase;
font-variant-numeric: tabular-nums;
}
.pt-wizard__confirm-port {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 12px;
}
.pt-list-status--ok,
.pt-list-status--up,
.pt-list-status--connected {
background: rgba(34, 197, 94, 0.16);
color: #86efac;
}
.pt-list-status--down,
.pt-list-status--failed,
.pt-list-status--critical {
background: rgba(239, 68, 68, 0.16);
color: #fca5a5;
}
.pt-list-status--major {
background: rgba(249, 115, 22, 0.16);
color: #fdba74;
}
.pt-list-status--minor,
.pt-list-status--warning {
background: rgba(245, 158, 11, 0.16);
color: #fde68a;
}
.pt-list-status--info {
background: rgba(56, 189, 248, 0.14);
color: #7dd3fc;
}
.pt-list-status--unknown {
background: rgba(148, 163, 184, 0.14);
color: var(--nx-text-muted);
}
/* Shared detail dialog for config view / LLDP jobs / config-sync cycles */
.ops-detail-modal,
.nm-config-modal {
display: flex;
flex-direction: column;
width: min(960px, 100%);
max-height: min(90vh, 840px);
overflow: hidden;
}
.ops-detail-modal__head,
.nm-config-modal__head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 12px;
flex: 0 0 auto;
}
.ops-detail-modal__title h3,
.nm-config-modal__title h3 {
margin: 0 0 4px;
}
.ops-detail-modal__title .muted,
.nm-config-modal__title .muted {
margin: 0;
font-size: 13px;
}
.ops-detail-modal__actions,
.nm-config-modal__actions {
flex: 0 0 auto;
}
.ops-detail-modal__toolbar {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
margin-bottom: 10px;
flex: 0 0 auto;
}
.ops-detail-modal__scroll {
flex: 1 1 auto;
min-height: 0;
overflow: auto;
border: 1px solid rgba(148, 163, 184, 0.22);
border-radius: 8px;
background: rgb(var(--nx-ink-deep-rgb) / 0.35);
}
.ops-detail-modal__scroll .pt-list-table-wrap,
.ops-detail-modal__scroll .data-table {
border: 0;
}
.ops-detail-modal__foot {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 10px;
margin-top: 12px;
flex: 0 0 auto;
}
.ops-detail-modal__error {
margin: 0 0 10px;
color: #fca5a5;
font-size: 13px;
}
.ops-detail-modal--xl {
width: min(1100px, 100%);
}
.ops-detail-modal__scroll--pad {
padding: 12px 14px;
}
/* Form + list share one scroll body (no cramped nested table viewport). */
.ops-detail-modal__scroll--flow {
border: 0;
background: transparent;
border-radius: 0;
}
.ops-detail-modal__scroll--flow .pt-list-table-wrap {
border: 1px solid rgba(148, 163, 184, 0.22);
border-radius: 8px;
overflow: visible;
}
.ume-entry-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 16px;
}
.ume-page > .ume-entry-grid > .panel {
padding: 16px 18px 18px;
border: 1px solid var(--nm-ops-line);
border-radius: 6px;
background: var(--nx-surface-1);
box-shadow: none;
margin: 0;
display: flex;
flex-direction: column;
gap: 10px;
min-height: 118px;
}
.ume-entry .panel__toolbar {
margin-bottom: 0;
padding-bottom: 10px;
}
.ume-entry__summary {
margin: 0;
font-size: 13px;
line-height: 1.45;
flex: 1 1 auto;
}
.ume-entry__pills {
margin: 0;
flex-wrap: wrap;
gap: 6px;
}
.ume-entry__link {
color: var(--nx-accent-text);
text-decoration: none;
font-weight: 600;
}
.ume-entry__link:hover {
color: #bfdbfe;
text-decoration: underline;
}
.ume-modal-form {
flex: 0 0 auto;
margin-bottom: 10px;
}
.ume-modal-form__grow {
flex: 1 1 160px;
min-width: 140px;
}
.ume-modal-form__label {
margin: 0 0 6px;
font-size: 13px;
}
.ume-modal-form__hint {
margin: 6px 0 0;
font-size: 12px;
}
.ume-modal-form__opts {
margin-top: 8px;
margin-bottom: 0;
}
.ume-ne-types {
display: flex;
flex-wrap: wrap;
gap: 8px 16px;
max-height: 120px;
overflow: auto;
padding: 8px 10px;
border: 1px solid rgba(148, 163, 184, 0.22);
border-radius: 8px;
background: rgb(var(--nx-ink-deep-rgb) / 0.35);
}
.ume-ne-types--tall {
max-height: 240px;
}
.ume-ne-types__item {
display: inline-flex;
align-items: center;
gap: 6px;
white-space: nowrap;
font-size: 13px;
}
.ume-ne-detail-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px 18px;
font-size: 13px;
}
.ume-ne-detail-grid > div > .muted {
display: block;
font-size: 11px;
margin-bottom: 2px;
}
.nowrap {
white-space: nowrap;
}
.nm-config-modal__tabs {
margin-bottom: 10px;
}
.nm-page-panel .nm-config-modal__tabs button.is-active,
.bs-cmp-job-body .nm-config-modal__tabs button.is-active,
.app-heroui-modal .nm-config-modal__tabs button.is-active,
.nm-config-modal__tabs button.is-active {
outline: 2px solid rgba(37, 99, 235, 0.55);
outline-offset: 1px;
box-shadow: 0 0 0 1px rgba(37, 99, 235, 0.25);
font-weight: 600;
}
.bs-cmp-metric-chips {
display: flex;
flex-wrap: wrap;
gap: 4px;
}
.bs-cmp-metric-chip {
display: inline-block;
padding: 2px 6px;
border-radius: 4px;
background: rgb(var(--nx-ink-rgb) / 0.72);
border: 1px solid rgba(148, 163, 184, 0.22);
font-size: 12px;
color: var(--nx-text-soft);
}

View file

@ -0,0 +1,268 @@
/* LEGACY: unified dark surfaces, dark modals, audit logs. Dissolve into components/ over time. */
/* ===== Unified dark content surfaces (forms / tables / status) ===== */
.page-loading {
display: flex;
align-items: center;
justify-content: center;
min-height: 240px;
color: var(--nx-text-muted);
font-size: 13px;
}
.page-loading--soft {
min-height: 120px;
opacity: 0;
animation: page-loading-soft-in 160ms ease 180ms forwards;
}
@keyframes page-loading-soft-in {
to {
opacity: 1;
}
}
.app-main option,
option {
background: var(--nx-surface-2);
color: var(--nx-text);
}
.app-main .filter-inline,
.ne-page .filter-inline,
.ume-page .filter-inline,
.system-page .filter-inline,
.network-main .filter-inline {
background: rgb(var(--nx-ink-deep-rgb) / 0.45) !important;
border-color: var(--nm-ops-line) !important;
}
.app-main .filter-inline input,
.app-main .filter-inline select,
.ne-page .filter-inline input,
.ne-page .filter-inline select,
.ume-page .filter-inline input,
.ume-page .filter-inline select,
.system-page .filter-inline input,
.system-page .filter-inline select,
.network-main .filter-inline input,
.network-main .filter-inline select {
background: var(--nx-field) !important;
border-color: var(--nm-ops-line) !important;
color: var(--nx-text) !important;
}
.app-main .pt-list-table-wrap,
.ne-page .pt-list-table-wrap,
.ume-page .pt-list-table-wrap,
.system-page .pt-list-table-wrap,
.network-main .pt-list-table-wrap,
.pt-list-table-wrap {
border-color: var(--nm-ops-line) !important;
background: rgb(var(--nx-ink-deep-rgb) / 0.28);
}
.app-main .pt-list-table thead th,
.ne-page .pt-list-table thead th,
.ume-page .pt-list-table thead th,
.system-page .pt-list-table thead th,
.network-main .pt-list-table thead th,
.pt-list-table thead th,
.app-main .data-table thead th,
.data-table thead th {
background: var(--nx-surface-3) !important;
color: var(--nx-text-muted) !important;
border-bottom-color: var(--nm-ops-line);
}
.app-main .pt-list-table tbody tr:hover td,
.pt-list-table tbody tr:hover td,
.app-main .data-table tbody tr:hover td,
.data-table tbody tr:hover td {
background: rgb(var(--nx-surface-3-rgb) / 0.55) !important;
}
.app-main .pt-list-status--unknown,
.pt-list-status--unknown,
.app-main .pt-list-status--other,
.pt-list-status--other,
.app-main .pt-list-status--stopped,
.pt-list-status--stopped {
background: rgba(148, 163, 184, 0.14) !important;
color: var(--nx-text-muted) !important;
}
.app-main .pt-list-status--ok,
.pt-list-status--ok,
.app-main .pt-list-status--pass,
.pt-list-status--pass,
.app-main .pt-list-status--up,
.pt-list-status--up {
background: rgba(34, 197, 94, 0.16) !important;
color: #86efac !important;
}
.app-main table,
.app-main .data-table {
color: var(--nx-text);
}
.app-main .muted,
.muted {
color: var(--nx-text-muted);
}
/* ===== Dark modals + topology non-canvas ===== */
.modal-backdrop,
.token-scopes-modal__backdrop,
.topo-modal__backdrop {
background: rgb(var(--nx-ink-deep-rgb) / 0.72) !important;
}
.modal,
.app-main .modal,
.token-scopes-modal__panel,
.topo-modal__panel,
.webcrt-auth-modal,
.webcrt-new-session-modal,
.webcrt-keyword-modal,
.webcrt-session-opts-modal {
background: var(--nx-surface-2) !important;
color: var(--nx-text) !important;
border: 1px solid rgba(148, 163, 184, 0.22) !important;
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.45) !important;
}
.modal h3,
.token-scopes-modal__head h3,
.topo-modal__head h3,
.pt-log-modal__head h3 {
color: var(--nx-text-strong) !important;
}
.modal .muted,
.modal .form-hint,
.modal label,
.modal .form-label,
.token-scopes-modal__row,
.topo-modal__hint,
.topo-modal__selectall {
color: var(--nx-text-soft) !important;
}
.modal input,
.modal select,
.modal textarea,
.topo-modal__panel input,
.topo-modal__panel select,
.token-scopes-modal__panel input,
.token-scopes-modal__panel select {
background: var(--nx-field) !important;
border-color: rgba(148, 163, 184, 0.28) !important;
color: var(--nx-text) !important;
}
.topo-browser,
.topo-main {
background: var(--nm-chrome, #070b14);
color: var(--nm-text, var(--nx-text));
border-color: rgba(148, 163, 184, 0.2);
}
.topo-browser__head,
.topo-toolbar {
background: rgb(var(--nx-ink-rgb) / 0.9);
border-color: rgba(148, 163, 184, 0.18);
}
.topo-browser__grid,
.topo-browser__grid--regions {
background: rgb(var(--nx-ink-deep-rgb) / 0.4);
}
.topo-map-list__row,
.topo-palette__row {
background: rgb(var(--nx-ink-rgb) / 0.75);
border-color: rgba(148, 163, 184, 0.22);
}
.app-main .topo-toolbar__select,
.topo-toolbar__select,
.app-main .topo-toolbar__display > summary,
.topo-toolbar__display > summary,
.app-main .topo-toolbar__actions > .btn:not([data-variant="primary"]):not([data-variant="secondary"]),
.topo-toolbar__actions > .btn:not([data-variant="primary"]):not([data-variant="secondary"]),
.app-main .topo-toolbar__group > .btn,
.topo-toolbar__group > .btn {
background: var(--nx-field) !important;
border-color: rgba(148, 163, 184, 0.28) !important;
color: var(--nx-text) !important;
}
.topo-nav-node {
background: linear-gradient(165deg, var(--nx-line) 0%, var(--nx-surface-2) 100%);
border-color: rgba(148, 163, 184, 0.28);
color: var(--nx-text);
}
.topo-nav-node__icon {
background: rgba(37, 99, 235, 0.18);
}
.webcrt-menubar__menu {
background: var(--nx-surface-2) !important;
border-color: rgba(148, 163, 184, 0.28) !important;
color: var(--nx-text) !important;
}
.webcrt-menubar__menu-item {
color: var(--nx-text) !important;
}
.webcrt-menubar__menu-item:hover {
background: rgba(37, 99, 235, 0.2) !important;
}
.pt-log-modal__list {
background: rgb(var(--nx-ink-deep-rgb) / 0.55) !important;
border-color: rgba(148, 163, 184, 0.2) !important;
color: var(--nx-text) !important;
}
/* Operation audit logs */
.system-page .audit-quick-filters button.is-active {
background: rgba(37, 99, 235, 0.18);
border-color: rgb(var(--nx-accent-rgb) / 0.55);
color: #1e3a8a;
font-weight: 600;
}
.system-page .audit-summary-cell {
max-width: 420px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.system-page button.linkish {
background: transparent;
border: none;
color: var(--nx-accent-strong);
cursor: pointer;
padding: 0;
height: auto;
font: inherit;
text-decoration: underline;
}
.system-page .audit-detail-row td {
background: rgb(var(--nx-ink-rgb) / 0.04);
padding: 10px 12px 14px;
}
.system-page .audit-detail-pre {
margin: 0;
max-height: 240px;
overflow: auto;
white-space: pre-wrap;
word-break: break-word;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 12px;
line-height: 1.45;
}
.system-page .audit-detail-meta {
margin: 8px 0 0;
}

View file

@ -0,0 +1,280 @@
/* LEGACY: HeroUI modal chrome, profiles table, ui-field, cutover wall. Dissolve into components/ over time. */
/* HeroUI Modal chrome used by NetX dialogs */
.app-heroui-modal-backdrop {
z-index: 1200;
}
.app-heroui-modal .modal__dialog,
.app-heroui-modal__dialog,
.topo-heroui-modal .modal__dialog,
.topo-heroui-modal__dialog {
background: var(--nx-surface-2);
color: var(--nx-text);
border: 1px solid rgba(148, 163, 184, 0.22);
max-height: min(90vh, 920px);
overflow: hidden;
}
/*
* HeroUI lg = max-w-lg (~32rem) — too narrow for NetX ops tables.
* Match legacy ops-detail-modal--xl (~1100px).
*/
.app-heroui-modal .modal__dialog--lg,
.topo-heroui-modal .modal__dialog--lg {
width: min(1100px, 96vw);
max-width: min(1100px, 96vw);
}
.app-heroui-modal--xl .modal__dialog,
.app-heroui-modal--xl .modal__dialog--lg,
.app-heroui-modal--xl .modal__dialog--md {
width: min(1280px, 98vw);
max-width: min(1280px, 98vw);
}
.app-heroui-modal__dialog [data-slot="modal-body"],
.app-heroui-modal__dialog .modal__body {
overflow: auto;
max-height: min(78vh, 780px);
}
/*
* Modal.Body often uses flex column; default flex-shrink:1 crushes the rules
* table to thead-only while the pager still shows total > 0.
*/
.app-heroui-modal__dialog [data-slot="modal-body"] > *,
.app-heroui-modal__dialog .modal__body > * {
flex-shrink: 0;
}
.app-heroui-modal--xl .app-heroui-modal__dialog [data-slot="modal-body"],
.app-heroui-modal--xl .app-heroui-modal__dialog .modal__body {
max-height: min(86vh, 900px);
}
.app-heroui-modal .pt-list-table-wrap {
overflow-x: auto;
max-width: 100%;
width: 100%;
min-height: 10rem;
}
.app-heroui-modal .pt-list-table {
width: 100%;
min-width: 100%;
table-layout: auto;
}
.app-heroui-modal .pt-list-table th,
.app-heroui-modal .pt-list-table td {
white-space: nowrap;
}
/* Biz-state profiles: keep wide table + H-scroll inside a fixed viewport. */
.app-heroui-modal__dialog [data-slot="modal-body"] > .bs-profiles-panel,
.app-heroui-modal__dialog .modal__body > .bs-profiles-panel {
flex-shrink: 1;
min-height: 0;
}
.app-heroui-modal .pt-list-table-wrap.bs-profiles-table-wrap {
overflow: auto !important;
max-width: 100%;
width: 100%;
max-height: none;
}
.app-heroui-modal .pt-list-table.bs-profiles-table {
width: max-content !important;
min-width: 100% !important;
table-layout: fixed !important;
}
.app-heroui-modal .pt-list-table.bs-profiles-table th,
.app-heroui-modal .pt-list-table.bs-profiles-table td {
white-space: normal;
}
.app-heroui-modal .pt-list-table.bs-profiles-table .bs-cmd-cell {
white-space: nowrap;
}
/* Last flexible column absorbs leftover width so the table fills the row */
.app-heroui-modal .pt-list-table td.ume-col-error,
.app-heroui-modal .pt-list-table th.ume-col-error {
white-space: normal;
min-width: 12rem;
width: 100%;
max-width: none;
word-break: break-word;
}
/* Keep dense filter bars compact when FieldSelect has no label */
.filter-inline > .ui-field {
gap: 0;
align-self: center;
}
.filter-inline > .ui-field > .ui-field__select {
height: 32px;
min-height: 32px;
max-height: 32px;
flex: none;
}
.login-card--heroui {
gap: 0;
}
.login-card__form {
display: flex;
flex-direction: column;
gap: 15px;
width: 100%;
}
.ui-field {
display: flex;
flex-direction: column;
gap: 6px;
min-width: 0;
}
.ui-field--full {
grid-column: 1 / -1;
}
.ui-field__label {
font-size: 12px;
color: var(--nm-muted, var(--nx-text-muted));
}
.ui-field__select {
width: 100%;
min-height: 36px;
padding: 0 10px;
border-radius: 10px;
border: 1px solid rgba(148, 163, 184, 0.28);
background: color-mix(in oklab, var(--field-background, var(--nx-surface-2)) 92%, #020617);
color: inherit;
font: inherit;
}
.ui-field__hint {
font-size: 11px;
color: var(--nm-muted, var(--nx-text-muted));
line-height: 1.35;
}
.pager__size-field {
min-width: 7.5rem;
}
.pager__jump .input,
.pager__jump-input {
width: 4.25rem;
}
/* Cutover wall: keep one board/poller alive in native or window fullscreen. */
.app-heroui-modal.bm-wall-modal {
width: 100vw !important;
max-width: 100vw !important;
height: 100dvh;
max-height: 100dvh;
padding: 0;
margin: 0;
transform: none;
box-sizing: border-box;
border: 0;
}
.app-heroui-modal.bm-wall-modal .app-heroui-modal__dialog {
width: 100% !important;
max-width: 100% !important;
height: 100%;
max-height: 100%;
margin: 0;
padding: 0;
border: 0;
border-radius: 0;
transform: none;
overflow: hidden;
box-sizing: border-box;
}
.bm-wall-modal .modal__header,
.bm-wall-modal .modal__footer,
.bm-wall-modal .bm-detail__chrome,
.bm-wall-modal .nm-config-modal__tabs { display: none; }
.app-heroui-modal.bm-wall-modal .bm-detail {
width: 100%;
min-width: 0;
height: 100%;
max-height: 100%;
margin: 0;
padding: 0;
gap: 0;
overflow: hidden;
}
.bm-board.is-wall,
.bm-board:fullscreen {
width: 100%;
min-width: 0;
height: 100dvh;
min-height: 0;
max-height: 100dvh;
margin: 0;
padding: clamp(12px, 1.25vw, 28px);
gap: 12px;
border-radius: 0;
background: var(--nx-field);
color: var(--nx-text);
box-sizing: border-box;
overflow: auto;
}
.bm-board.is-wall > * { flex-shrink: 0; }
.bm-wall-heading { display: flex; justify-content: space-between; align-items: center; gap: 20px; min-width: 0; }
.bm-wall-heading > div { min-width: 0; }
.bm-wall-heading__label { color: var(--nx-text-muted); font-size: 13px; letter-spacing: .08em; }
.bm-wall-heading h2 { margin: 4px 0 0; font-size: clamp(22px, 2vw, 36px); line-height: 1.2; overflow-wrap: anywhere; }
.bm-wall-heading__status { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.bm-wall-heading time { color: var(--nx-text-muted); font: 14px ui-monospace, monospace; white-space: nowrap; }
.bm-wall-state { padding: 6px 12px; font-size: 15px; border: 1px solid currentColor; border-radius: 3px; }
.bm-wall-state.is-normal { color: #34d399; }
.bm-wall-state.is-anomaly { color: #f87171; }
.bm-wall-state.is-waiting, .bm-wall-state.is-unknown { color: #fbbf24; }
.bm-board.is-wall .bm-live-header { position: sticky; top: 0; z-index: 5; background: var(--nx-field); padding: 8px 0; }
.bm-board.is-wall .bm-live-header strong { font-size: 17px; }
.bm-board.is-wall .bm-live-sources strong { font-size: 19px; }
.bm-board.is-wall .bm-live-kpis > div { padding: 16px 20px; }
.bm-board.is-wall .bm-live-kpis span { font-size: 16px; }
.bm-board.is-wall .bm-live-kpis strong { font-size: clamp(40px, 3.5vw, 68px); }
.bm-board.is-wall .bm-live-kpis strong small { font-size: 20px; }
.bm-board.is-wall .bm-live-warning { font-size: 14px; }
.bm-wall-progress { display: flex; align-items: center; gap: 20px; padding: 4px 0; color: #34d399; }
.bm-wall-progress > div:first-child { display: flex; align-items: baseline; gap: 16px; }
.bm-wall-progress span { font-size: 13px; }
.bm-wall-progress strong { font: 600 24px ui-monospace, monospace; }
.bm-wall-progress.is-unknown { color: #fbbf24; }
.bm-wall-progress__track { flex: 1; height: 8px; min-width: 60px; background: #243044; border-radius: 2px; overflow: hidden; }
.bm-wall-progress__track > span { display: block; height: 100%; background: currentColor; }
.bm-board.is-wall .bm-board-controls > summary { display: list-item; cursor: pointer; color: var(--nx-text-muted); font-size: 13px; padding: 6px 0; }
.bm-board.is-wall .bm-sampling { max-height: 240px; overflow: auto; }
.bm-board.is-wall .bm-sampling td, .bm-board.is-wall .bm-sampling th { font-size: 14px; }
.bm-board.is-wall .bs-cmp-board__body { flex: 1 0 260px; min-height: 260px; }
.bm-board.is-wall .bs-cmp-main { display: flex; min-height: 0; }
.bm-board.is-wall .bm-board__table { flex: 1; width: 100%; min-height: 0; max-height: none; }
.bm-board.is-wall .bm-board__table td { font-size: 15px; }
.bm-board.is-wall .bs-cmp-nav__list { max-height: none; }
@media (max-width: 720px) {
.bm-wall-heading { align-items: flex-start; gap: 12px; }
.bm-wall-heading__status { max-width: 48%; }
.bm-wall-heading time { font-size: 10px; white-space: normal; }
.bm-wall-state { font-size: 12px; padding: 4px 6px; }
.bm-board.is-wall .bm-live-kpis > div { padding: 12px; }
.bm-board.is-wall .bm-live-kpis strong { font-size: 36px; }
.bm-board.is-wall .bm-live-kpis span { font-size: 13px; }
.bm-wall-progress { flex-wrap: wrap; gap: 8px; }
.bm-wall-progress__track { flex-basis: 100%; }
.bm-board.is-wall .bs-cmp-board__body { flex-basis: auto; }
.bm-board.is-wall .bm-board__table { max-height: 50dvh; }
}

View file

@ -0,0 +1,183 @@
/* Compare template editor */
/* Compare template editor (aligned with monitor template editor) */
.ct-editor__basics {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
@media (max-width: 720px) {
.ct-editor__basics {
grid-template-columns: 1fr;
}
}
.ct-editor__pick {
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
padding: 8px 10px;
background: rgb(var(--nx-ink-rgb) / 0.28);
}
.ct-editor__pick-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.ct-editor__pick-title {
font-size: 13px;
font-weight: 650;
}
.ct-editor__pick-hint {
margin: 6px 0 8px;
font-size: 12px;
}
.ct-metric-chips {
display: flex;
flex-wrap: wrap;
gap: 6px;
max-height: 140px;
overflow: auto;
}
.ct-metric-chip__n {
margin-left: 6px;
opacity: 0.65;
font-size: 11px;
}
.ct-editor__main {
display: grid;
grid-template-columns: 200px 1fr;
gap: 12px;
min-height: 360px;
align-items: stretch;
}
@media (max-width: 900px) {
.ct-editor__main {
grid-template-columns: 1fr;
}
}
.ct-editor__nav {
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
padding: 8px;
background: rgb(var(--nx-ink-rgb) / 0.35);
display: flex;
flex-direction: column;
gap: 6px;
max-height: 70vh;
overflow: auto;
}
.ct-editor__nav-head {
font-size: 12px;
font-weight: 600;
padding: 2px 4px 6px;
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
}
.ct-editor__nav-list {
display: flex;
flex-direction: column;
gap: 4px;
}
.ct-editor__nav-item {
appearance: none;
text-align: left;
border: 1px solid transparent;
border-radius: 6px;
background: transparent;
color: inherit;
padding: 8px 10px;
cursor: pointer;
display: flex;
flex-direction: column;
gap: 2px;
}
.ct-editor__nav-item:hover {
background: rgb(var(--nx-surface-3-rgb) / 0.65);
}
.ct-editor__nav-item.is-active {
border-color: rgb(var(--nx-accent-rgb) / 0.55);
background: rgba(37, 99, 235, 0.18);
}
.ct-editor__nav-name {
font-size: 13px;
font-weight: 600;
}
.ct-editor__nav-tag {
font-size: 11px;
opacity: 0.7;
}
.ct-editor__pane {
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
padding: 12px 14px;
display: flex;
flex-direction: column;
gap: 12px;
min-width: 0;
}
.ct-editor__pane-head {
display: flex;
justify-content: space-between;
gap: 12px;
align-items: flex-start;
flex-wrap: wrap;
}
.ct-editor__metric {
font-size: 15px;
font-weight: 700;
}
.ct-editor__meta {
font-size: 12px;
margin-top: 4px;
}
.ct-filters__hint,
.ct-filters__empty,
.ct-field-hint {
margin: 0 0 8px;
font-size: 12px;
}
.ct-filters__actions {
display: flex;
gap: 12px;
margin-bottom: 8px;
}
.ct-filter-row {
display: grid;
grid-template-columns: minmax(90px, 1.1fr) minmax(72px, 0.8fr) minmax(80px, 1.2fr) auto;
gap: 6px;
align-items: center;
margin: 4px 0;
}
.ct-filter-row input {
min-width: 0;
width: 100%;
}
.ct-field-table-wrap {
max-height: min(55vh, 520px);
overflow: auto;
}
.ct-field-table {
border-collapse: separate;
border-spacing: 0;
}
.ct-field-table thead th {
position: sticky;
top: 0;
z-index: 2;
background: rgb(var(--nx-ink-rgb) / 0.98) !important;
box-shadow: 0 1px 0 rgba(148, 163, 184, 0.22);
}
.ct-field-table th,
.ct-field-table td {
vertical-align: middle;
}
.ct-field-table th:nth-child(n + 2),
.ct-field-table td:nth-child(n + 2) {
text-align: center;
white-space: nowrap;
}
.ct-field-table td:first-child {
text-align: left;
}
.ct-field-name {
font-size: 12px;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,711 @@
/* Cutover monitor / migration */
/* Cutover monitor (biz migration) */
.bm-hint {
margin: 0;
font-size: 12px;
}
.bm-pair-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
align-items: start;
}
@media (max-width: 720px) {
.bm-pair-grid {
grid-template-columns: 1fr;
}
}
.bm-pair-card {
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
padding: 10px 12px;
background: rgb(var(--nx-ink-rgb) / 0.28);
}
.bm-pair-card__label {
font-size: 11px;
opacity: 0.7;
margin-bottom: 4px;
}
.bm-mapping {
display: flex;
flex-direction: column;
gap: 8px;
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
padding: 10px 12px;
background: rgb(var(--nx-ink-rgb) / 0.22);
}
.bm-mapping__label {
font-size: 13px;
font-weight: 650;
}
.bm-mapping__row {
display: grid;
grid-template-columns: minmax(140px, 1.2fr) minmax(120px, 1fr) auto;
gap: 8px;
align-items: end;
}
@media (max-width: 720px) {
.bm-mapping__row {
grid-template-columns: 1fr;
}
}
.bm-mapping__text {
width: 100%;
min-height: 110px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 12px;
border: 1px solid rgba(148, 163, 184, 0.4);
border-radius: 6px;
background: rgb(var(--nx-ink-deep-rgb) / 0.35);
color: inherit;
padding: 8px 10px;
resize: vertical;
}
.bm-detail__chrome {
display: flex;
flex-wrap: wrap;
gap: 8px 16px;
align-items: center;
justify-content: space-between;
}
.bm-detail__meta {
display: flex;
flex-wrap: wrap;
gap: 6px 10px;
align-items: center;
font-size: 12px;
}
.bm-detail__arrow {
opacity: 0.55;
font-weight: 700;
}
.bm-detail__actions {
flex-wrap: wrap;
gap: 6px;
}
.bm-detail__link {
font-size: 12px;
align-self: center;
}
.bm-setup__meta {
display: flex;
flex-wrap: wrap;
gap: 4px 8px;
align-items: center;
font-size: 12px;
font-variant-numeric: tabular-nums;
padding: 6px 0 2px;
}
.bm-setup__sep {
opacity: 0.4;
}
.bm-setup__binds {
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 11px;
}
.bm-setup__cmp {
display: flex;
align-items: end;
font-size: 12px;
padding-bottom: 6px;
}
.bm-batches__toolbar {
display: flex;
flex-wrap: wrap;
gap: 8px 12px;
justify-content: space-between;
align-items: center;
}
.bm-batches__toolbar-main,
.bm-batches__toolbar-side {
flex-wrap: wrap;
gap: 6px;
align-items: center;
}
.bm-board__status {
display: flex;
flex-wrap: wrap;
gap: 10px 16px;
align-items: baseline;
padding: 8px 10px;
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 6px;
background: rgb(var(--nx-ink-rgb) / 0.35);
font-variant-numeric: tabular-nums;
font-size: 13px;
}
.bm-board__verdict {
font-weight: 700;
letter-spacing: 0.02em;
}
.bm-board__verdict.is-ok {
color: #34d399;
}
.bm-board__verdict.is-bad,
.bm-board__num.is-bad {
color: #f87171;
}
.bm-board__num {
opacity: 0.9;
}
.bm-batches {
display: flex;
flex-direction: column;
gap: 10px;
min-height: 0;
flex: 1;
}
.bm-batches__main {
min-height: 320px;
flex: 1;
}
.bm-expect-table {
max-height: min(48vh, 420px);
overflow: auto;
}
.bm-expect-desc {
max-width: 240px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.bm-board {
flex: 1;
min-height: 0;
}
.bm-board__accept {
display: flex;
flex-wrap: wrap;
gap: 10px 16px;
font-size: 12px;
font-variant-numeric: tabular-nums;
align-items: center;
}
.bm-board__table {
max-height: min(58vh, 560px);
overflow: auto;
}
/* Cutover operations console: readable device samples, continuity and scope. */
.bm-live-header, .bm-live-header > div, .bm-live-filters {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 10px;
}
.bm-live-header { justify-content: space-between; border-bottom: 1px solid rgba(148,163,184,.25); padding-bottom: 10px; }
.bm-live-state { font-size: 11px; padding: 3px 8px; border: 1px solid rgba(148,163,184,.35); border-radius: 3px; }
.bm-live-state.is-live { color: #34d399; border-color: rgba(52,211,153,.45); }
.bm-live-state.is-live::before { content: ""; display: inline-block; width: 6px; height: 6px; background: currentColor; margin-right: 6px; border-radius: 50%; }
.bm-live-sources { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 10px; }
.bm-live-sources > div { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px; padding: 10px 12px; border: 1px solid rgba(148,163,184,.24); border-left: 3px solid var(--nx-text-faint); border-radius: 4px; min-width: 0; }
.bm-live-sources > div:last-child { border-left-color: #38bdf8; }
.bm-live-sources small { flex-basis: 100%; font-variant-numeric: tabular-nums; }
.bm-live-sources strong { overflow-wrap: anywhere; }
.bm-live-kpis { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); gap: 10px; }
.bm-live-kpis > div { display: flex; flex-direction: column; gap: 5px; padding: 12px 14px; border: 1px solid rgba(148,163,184,.25); border-radius: 4px; }
.bm-live-kpis span { font-size: 12px; opacity: .8; }
.bm-live-kpis strong { font: 600 26px/1.2 ui-monospace,monospace; font-variant-numeric: tabular-nums; }
.bm-live-kpis strong small { font-size: 13px; opacity: .7; }
.bm-live-kpis .is-ok strong { color: #34d399; }
.bm-live-kpis .is-bad strong { color: #f87171; }
.bm-live-warning { display: flex; flex-wrap: wrap; gap: 6px 14px; padding: 10px 12px; border: 1px solid rgba(251,191,36,.3); border-left: 3px solid #fbbf24; border-radius: 3px; background: rgba(251,191,36,.06); font-size: 12px; overflow-wrap: anywhere; }
.bm-live-warning strong { flex-basis: 100%; }
.bm-live-filters > input { flex: 1 1 240px; min-width: 0; }
.bm-live-filters > .ui-field-select { max-width: 230px; }
.bm-diff-row.is-red > td:first-child { box-shadow: inset 3px 0 #f87171; }
.bm-diff-row.is-yellow > td:first-child { box-shadow: inset 3px 0 #fbbf24; }
.bm-scope-label { display: block; font-size: 10px; opacity: .65; padding-top: 3px; }
.bm-field-changes { font-size: 11px; margin-top: 5px; }
.bm-field-changes summary { cursor: pointer; color: #fbbf24; }
.bm-field-changes div { padding-top: 5px; overflow-wrap: anywhere; }
.bm-field-changes ins { color: #f87171; text-decoration: none; }
.bm-board .bs-cmp-main { min-width: 0; }
.bm-sampling { border: 1px solid rgba(148,163,184,.25); border-radius: 4px; min-width: 0; }
.bm-sampling > summary { padding: 8px 12px; cursor: pointer; font-size: 12px; }
.app-heroui-modal .bm-sampling .pt-list-table-wrap { max-width: 100%; min-height: 0; }
.bm-live-header__actions { display: flex; gap: 8px; align-items: center; }
.bm-board-controls > summary { display: none; }
.bm-board-controls > .bm-live-filters { margin-top: 8px; }
@media (max-width: 720px) {
.bm-live-sources { grid-template-columns: 1fr; }
.bm-live-kpis { grid-template-columns: repeat(2,minmax(0,1fr)); gap: 6px; }
.bm-live-header > .muted { flex: 1 1 100%; font-size: 11px; }
.bm-board .bs-cmp-board__toolbar { display: grid; grid-template-columns: minmax(0,1fr); }
.bm-board .bs-id-row { min-width: 0; }
.bm-board .bs-cmp-board__body { display: flex; flex-direction: column; min-width: 0; }
.bm-board .bs-cmp-nav { width: 100%; max-width: none; }
.bm-board .bs-cmp-nav__list { max-height: 180px; }
.bm-live-filters > .ui-field-select { max-width: none; width: 100%; }
.bm-board__table { max-width: 100%; }
}
/* Cutover create wizard */
.bm-create {
min-height: min(52vh, 520px);
}
.bm-create__pane {
display: flex;
flex-direction: column;
gap: 12px;
}
.bm-steps {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 6px;
margin-bottom: 4px;
}
.bm-steps__item {
display: flex;
align-items: center;
gap: 8px;
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
background: rgb(var(--nx-ink-rgb) / 0.22);
color: inherit;
padding: 8px 10px;
cursor: pointer;
text-align: left;
font: inherit;
opacity: 0.72;
transition: border-color 0.15s ease, opacity 0.15s ease, background 0.15s ease;
}
.bm-steps__item:hover {
opacity: 0.92;
}
.bm-steps__item.is-active {
opacity: 1;
border-color: rgba(148, 163, 184, 0.55);
background: rgba(51, 65, 85, 0.35);
}
.bm-steps__item.is-done {
opacity: 0.9;
}
.bm-steps__num {
flex: 0 0 auto;
width: 22px;
height: 22px;
border-radius: 999px;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 11px;
font-weight: 700;
background: rgba(148, 163, 184, 0.22);
}
.bm-steps__item.is-active .bm-steps__num,
.bm-steps__item.is-done .bm-steps__num {
background: rgba(148, 163, 184, 0.4);
}
.bm-steps__label {
font-size: 12px;
font-weight: 600;
line-height: 1.2;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
@media (max-width: 720px) {
.bm-steps {
grid-template-columns: 1fr 1fr;
}
}
.bm-ne-slot {
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
padding: 12px 14px;
background: rgb(var(--nx-ink-rgb) / 0.28);
color: inherit;
text-align: left;
cursor: pointer;
font: inherit;
transition: border-color 0.15s ease, box-shadow 0.15s ease;
min-height: 78px;
}
.bm-ne-slot:hover {
border-color: rgba(148, 163, 184, 0.5);
}
.bm-ne-slot.is-picking {
border-color: rgba(148, 163, 184, 0.65);
box-shadow: 0 0 0 1px rgba(148, 163, 184, 0.2);
}
.bm-ne-slot.is-filled {
background: rgb(var(--nx-ink-rgb) / 0.4);
}
.bm-ne-slot__name {
font-weight: 650;
font-size: 14px;
}
.bm-ne-slot__meta,
.bm-ne-slot__empty {
font-size: 12px;
margin-top: 4px;
}
.bm-ne-slot__empty {
opacity: 0.55;
}
.bm-ne-picker {
display: flex;
flex-direction: column;
gap: 8px;
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
padding: 10px 12px;
background: rgb(var(--nx-ink-deep-rgb) / 0.28);
}
.bm-ne-picker__head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.bm-ne-picker__table {
max-height: min(36vh, 320px);
overflow: auto;
}
.bm-ne-picker .pt-list-pager,
.bm-ne-picker .pager {
flex-shrink: 0;
margin-top: 4px;
}
.bm-ne-picker__table tr.is-selected td {
background: rgba(51, 65, 85, 0.45);
}
.bm-metric-chips {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.bm-metric-chip {
border: 1px solid rgba(148, 163, 184, 0.35);
border-radius: 6px;
background: rgb(var(--nx-ink-rgb) / 0.35);
color: inherit;
font: inherit;
font-size: 12px;
padding: 6px 10px;
cursor: pointer;
opacity: 0.7;
}
.bm-metric-chip.is-on {
opacity: 1;
border-color: rgba(148, 163, 184, 0.65);
background: rgba(51, 65, 85, 0.45);
font-weight: 600;
}
.bm-sched-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 10px;
}
@media (max-width: 720px) {
.bm-sched-grid {
grid-template-columns: 1fr;
}
}
.bm-sched-field {
display: flex;
flex-direction: column;
gap: 4px;
}
.bm-interval-table {
max-height: min(28vh, 240px);
overflow: auto;
}
.bm-hf-bindings {
margin: 6px 0 0;
padding-left: 1.1em;
list-style: disc;
}
.bm-create__summary {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px 14px;
padding: 10px 12px;
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
background: rgb(var(--nx-ink-rgb) / 0.28);
}
@media (max-width: 720px) {
.bm-create__summary {
grid-template-columns: 1fr;
}
}
.bm-create-modal .modal-footer,
.bm-create-modal [data-slot="footer"],
.bm-create-modal .app-heroui-modal__dialog [data-slot="footer"] {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.bm-create__footer-spacer {
flex: 1 1 auto;
min-width: 8px;
}
.bm-list-hf {
display: flex;
flex-direction: column;
gap: 2px;
align-items: flex-start;
}
.bm-list-hf__iv {
font-size: 11px;
font-variant-numeric: tabular-nums;
}
.bs-bind-panel {
padding: 10px 12px;
border: 1px solid rgba(148, 163, 184, 0.25);
border-radius: 8px;
}
.bs-bind-list {
max-height: 200px;
overflow: auto;
}
.bs-bind-list--modal {
max-height: min(48vh, 360px);
padding: 4px 2px;
border: 1px solid rgba(148, 163, 184, 0.18);
border-radius: 8px;
}
.bs-bind-item {
display: block;
margin-bottom: 4px;
}
.bs-profiles-panel {
display: flex;
flex-direction: column;
gap: 8px;
min-height: 0;
flex: 1 1 auto;
max-height: min(62vh, 620px);
}
.bs-profiles-toolbar {
flex: 0 0 auto;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.bs-profiles-stats {
font-size: 12px;
white-space: nowrap;
}
.bs-profiles-table-wrap {
flex: 1 1 auto;
min-height: 0;
overflow: auto !important;
max-height: none;
max-width: 100%;
/* Always reserve room for both scrollbars so H-bar stays in the visible viewport. */
scrollbar-gutter: stable both-edges;
scrollbar-width: thin;
scrollbar-color: rgba(148, 163, 184, 0.65) rgb(var(--nx-ink-rgb) / 0.9);
}
.bs-profiles-table-wrap::-webkit-scrollbar {
height: 12px;
width: 10px;
}
.bs-profiles-table-wrap::-webkit-scrollbar-track {
background: rgb(var(--nx-ink-rgb) / 0.9);
border-radius: 6px;
}
.bs-profiles-table-wrap::-webkit-scrollbar-thumb {
background: rgba(148, 163, 184, 0.55);
border-radius: 6px;
border: 2px solid rgb(var(--nx-ink-rgb) / 0.9);
}
.bs-profiles-table-wrap::-webkit-scrollbar-thumb:hover {
background: rgba(148, 163, 184, 0.75);
}
.bs-profiles-table {
width: max-content;
min-width: 100%;
table-layout: fixed;
border-collapse: separate;
border-spacing: 0;
}
.bs-profiles-table thead th {
position: sticky;
top: 0;
z-index: 3;
background: rgb(var(--nx-ink-rgb) / 0.97);
box-shadow: 0 1px 0 rgba(148, 163, 184, 0.25);
}
/* enable | title | lane | actions | params | command | aux */
.bs-profiles-table th:nth-child(1),
.bs-profiles-table td:nth-child(1) {
width: 52px;
}
.bs-profiles-table th:nth-child(2),
.bs-profiles-table td:nth-child(2) {
width: 200px;
}
.bs-profiles-table th:nth-child(3),
.bs-profiles-table td:nth-child(3) {
width: 88px;
}
.bs-profiles-table th:nth-child(4),
.bs-profiles-table td:nth-child(4) {
width: 120px;
}
.bs-profiles-table th:nth-child(5),
.bs-profiles-table td:nth-child(5) {
width: 200px;
}
.bs-profiles-table th:nth-child(6),
.bs-profiles-table td:nth-child(6) {
width: 360px;
}
.bs-profiles-table th:nth-child(7),
.bs-profiles-table td:nth-child(7) {
width: 280px;
}
.bs-profiles-sticky-col {
position: sticky;
z-index: 2;
background: rgb(var(--nx-ink-rgb) / 0.97);
}
.bs-profiles-table thead .bs-profiles-sticky-col,
.bs-profiles-table thead th:nth-child(1),
.bs-profiles-table thead th:nth-child(2) {
z-index: 4;
}
.bs-profiles-sticky-col--1,
.bs-profiles-table th:nth-child(1),
.bs-profiles-table td.bs-profiles-sticky-col--1 {
left: 0;
box-shadow: 1px 0 0 rgba(148, 163, 184, 0.2);
}
.bs-profiles-sticky-col--2,
.bs-profiles-table th:nth-child(2),
.bs-profiles-table td.bs-profiles-sticky-col--2 {
left: 52px;
box-shadow: 1px 0 0 rgba(148, 163, 184, 0.2);
}
.bs-profiles-table .bs-cmd-cell {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 12px;
max-width: 100%;
}
.bs-profiles-table .bs-aux-cell {
vertical-align: top;
font-size: 12px;
}
.bs-profiles-table .bs-aux-list {
margin: 0;
padding: 0;
list-style: none;
display: flex;
flex-direction: column;
gap: 6px;
}
.bs-profiles-table .bs-aux-list li {
min-width: 0;
}
.bs-profiles-table .bs-aux-key {
font-weight: 600;
color: var(--nx-text-soft);
}
.bs-profiles-table .bs-aux-cmd {
display: block;
margin-top: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 11px;
color: var(--nx-text-muted);
max-width: 100%;
}
.bs-profiles-table .bs-params-cell {
vertical-align: top;
}
.bs-profiles-table .bs-params-scroll {
max-width: 100%;
max-height: 3.2em;
overflow: hidden;
white-space: normal;
word-break: break-word;
line-height: 1.35;
font-size: 12px;
}
.bs-profiles-table .bs-params-scroll--clickable {
cursor: pointer;
user-select: none;
}
.bs-profiles-table .bs-params-scroll--clickable:hover {
text-decoration: underline;
text-underline-offset: 2px;
}
.bs-params-detail-list {
max-height: min(50vh, 420px);
}
.bs-params-detail-item {
padding: 4px 0;
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
font-size: 12px;
word-break: break-all;
}
.bs-params-detail-item:last-child {
border-bottom: none;
}
.bs-profiles-table .bs-actions-cell {
white-space: nowrap;
vertical-align: middle;
}
.bs-bind-hint {
margin-top: 4px;
font-size: 12px;
}
.bs-params-warn {
color: #fbbf24;
}
.bs-bind-modal.app-heroui-modal {
z-index: 80;
}

View file

@ -0,0 +1,487 @@
/* Monitor template editor */
/* Monitor template visual rule editor */
.mt-editor__basics {
display: grid;
grid-template-columns: 1.2fr 1.2fr 1fr;
gap: 12px;
align-items: start;
}
@media (max-width: 900px) {
.mt-editor__basics {
grid-template-columns: 1fr;
}
}
.mt-editor__main {
display: grid;
grid-template-columns: 200px 1fr;
gap: 12px;
min-height: 360px;
align-items: stretch;
}
@media (max-width: 900px) {
.mt-editor__main {
grid-template-columns: 1fr;
}
}
.mt-editor__nav {
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
padding: 8px;
background: rgb(var(--nx-ink-rgb) / 0.35);
display: flex;
flex-direction: column;
gap: 6px;
max-height: min(70vh, 720px);
overflow: auto;
min-height: 0;
align-self: stretch;
}
.mt-editor__nav-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 6px;
font-size: 12px;
font-weight: 600;
padding: 2px 4px 6px;
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
flex-shrink: 0;
}
.mt-editor__nav-list {
display: flex;
flex-direction: column;
gap: 4px;
flex: 1;
min-height: 0;
overflow: auto;
}
.mt-editor__nav-item {
appearance: none;
text-align: left;
border: 1px solid transparent;
border-radius: 6px;
background: transparent;
color: inherit;
padding: 8px 10px;
cursor: pointer;
display: flex;
flex-direction: column;
gap: 2px;
}
.mt-editor__nav-item:hover {
background: rgb(var(--nx-surface-3-rgb) / 0.65);
}
.mt-editor__nav-item.is-active {
border-color: rgb(var(--nx-accent-rgb) / 0.55);
background: rgba(37, 99, 235, 0.18);
}
.mt-editor__nav-name {
font-size: 13px;
font-weight: 600;
}
.mt-editor__nav-tag {
font-size: 11px;
opacity: 0.7;
}
.mt-editor__pane {
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
padding: 12px 14px;
display: flex;
flex-direction: column;
gap: 12px;
min-width: 0;
min-height: 0;
max-height: min(70vh, 720px);
overflow: auto;
align-self: stretch;
}
.mt-editor__pane-head {
display: flex;
justify-content: space-between;
gap: 12px;
align-items: flex-start;
flex-wrap: wrap;
}
.mt-editor__metric {
font-size: 15px;
font-weight: 700;
}
.mt-editor__meta {
display: flex;
flex-wrap: wrap;
gap: 6px 12px;
font-size: 12px;
margin-top: 4px;
}
.mt-editor__uv {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-top: 8px;
}
.mt-block__title {
font-size: 13px;
font-weight: 650;
margin-bottom: 6px;
}
.mt-block__hint {
margin: 0 0 10px;
font-size: 12px;
line-height: 1.4;
}
.mt-chip-row {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.mt-chip {
appearance: none;
border: 1px solid rgba(148, 163, 184, 0.4);
border-radius: 999px;
background: transparent;
color: inherit;
padding: 4px 10px;
font-size: 12px;
cursor: pointer;
line-height: 1.3;
}
.mt-chip:hover {
border-color: rgb(var(--nx-accent-rgb) / 0.55);
}
.mt-chip.is-on {
border-color: rgba(37, 99, 235, 0.75);
background: rgba(37, 99, 235, 0.22);
font-weight: 600;
}
.mt-skip-check {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 12px;
margin: 0;
cursor: pointer;
}
.mt-rule-tabs {
display: flex;
gap: 4px;
border-bottom: 1px solid rgba(148, 163, 184, 0.28);
padding-bottom: 0;
}
.mt-rule-tab {
appearance: none;
border: 1px solid transparent;
border-bottom: none;
border-radius: 6px 6px 0 0;
background: transparent;
color: inherit;
padding: 7px 12px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 6px;
opacity: 0.72;
}
.mt-rule-tab:hover {
opacity: 1;
background: rgb(var(--nx-surface-3-rgb) / 0.45);
}
.mt-rule-tab.is-active {
opacity: 1;
border-color: rgba(148, 163, 184, 0.35);
background: rgb(var(--nx-ink-rgb) / 0.55);
color: rgba(74, 222, 128, 0.95);
}
.mt-rule-tab--anomaly.is-active {
color: rgba(248, 113, 113, 0.95);
}
.mt-rule-tab__n {
font-size: 11px;
font-weight: 600;
opacity: 0.7;
min-width: 1.2em;
text-align: center;
padding: 0 5px;
border-radius: 999px;
background: rgba(148, 163, 184, 0.2);
}
.mt-rule-card {
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
padding: 10px 12px;
margin-bottom: 10px;
background: rgb(var(--nx-ink-rgb) / 0.28);
}
.mt-rule-card--anomaly {
border-color: rgba(239, 68, 68, 0.4);
background: rgba(239, 68, 68, 0.05);
}
.mt-rule-card__head {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
font-size: 12px;
font-weight: 650;
}
.mt-rule-card__grid {
display: grid;
grid-template-columns: 1fr auto 1fr;
gap: 10px;
align-items: stretch;
}
@media (max-width: 900px) {
.mt-rule-card__grid {
grid-template-columns: 1fr;
}
.mt-rule-arrow {
display: none;
}
}
.mt-rule-arrow {
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
font-weight: 700;
opacity: 0.55;
padding: 0 2px;
align-self: stretch;
}
.mt-side-col {
display: flex;
flex-direction: column;
min-width: 0;
min-height: 0;
}
.mt-side-col__label {
font-size: 12px;
font-weight: 650;
margin-bottom: 6px;
flex-shrink: 0;
}
.mt-side {
display: flex;
flex-direction: column;
gap: 6px;
min-width: 0;
flex: 1 1 auto;
min-height: 0;
}
.mt-side-empty-box {
flex: 1 1 auto;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
border: 1px dashed rgba(148, 163, 184, 0.35);
border-radius: 6px;
padding: 14px 12px;
min-height: 88px;
background: rgb(var(--nx-ink-deep-rgb) / 0.2);
}
.mt-side-empty {
margin: 0;
font-size: 12px;
line-height: 1.45;
}
.mt-or-wrap {
display: flex;
flex-direction: column;
gap: 4px;
}
.mt-and-box {
border: 1px solid rgba(148, 163, 184, 0.3);
border-radius: 6px;
padding: 8px;
background: rgb(var(--nx-ink-deep-rgb) / 0.25);
}
.mt-and-box__head {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 11px;
margin-bottom: 4px;
}
.mt-logic-badge {
align-self: center;
font-size: 10px;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
padding: 1px 8px;
border-radius: 999px;
opacity: 0.85;
}
.mt-logic-badge--or {
background: rgb(var(--nx-accent-rgb) / 0.2);
color: rgba(147, 197, 253, 0.95);
}
.mt-logic-badge--and {
background: rgba(148, 163, 184, 0.18);
color: rgba(203, 213, 225, 0.95);
margin: 2px auto;
width: fit-content;
}
.mt-select {
appearance: auto;
border: 1px solid rgba(148, 163, 184, 0.4);
border-radius: 6px;
background: rgb(var(--nx-ink-rgb) / 0.45);
color: inherit;
padding: 4px 8px;
font-size: 12px;
min-width: 0;
}
.mt-select--grow {
flex: 1 1 120px;
}
.mt-cond-row {
display: grid;
grid-template-columns: 88px minmax(0, 1fr) auto;
gap: 6px;
align-items: center;
margin: 4px 0;
}
.mt-cond-row.is-value {
grid-template-columns: 88px minmax(72px, 1fr) minmax(88px, 1.1fr) minmax(64px, 1fr) auto;
}
.mt-cond-row .mt-cond-value,
.mt-cond-row input {
min-width: 0;
width: 100%;
}
.mt-icon-btn {
appearance: none;
border: none;
background: transparent;
color: inherit;
opacity: 0.55;
cursor: pointer;
font-size: 16px;
line-height: 1;
padding: 2px 6px;
border-radius: 4px;
}
.mt-icon-btn:hover {
opacity: 1;
background: rgba(148, 163, 184, 0.15);
}
.mt-link-btn {
appearance: none;
border: none;
background: transparent;
color: rgba(147, 197, 253, 0.95);
font-size: 12px;
cursor: pointer;
padding: 4px 0 0;
text-align: left;
width: fit-content;
}
.mt-link-btn:hover {
text-decoration: underline;
}
.mt-dontcare {
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
margin: 0 0 4px;
cursor: pointer;
}
/* legacy aliases kept for safety */
.mt-success-card {
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
padding: 10px;
margin-bottom: 8px;
}
.mt-anomaly-card {
border-color: rgba(239, 68, 68, 0.45);
background: rgba(239, 68, 68, 0.06);
}
.mt-block--success .mt-block__title {
color: rgba(74, 222, 128, 0.95);
}
.mt-block--anomaly .mt-block__title {
color: rgba(248, 113, 113, 0.95);
}
.mt-rule-sections {
display: flex;
flex-direction: column;
gap: 16px;
}
.mt-success-card__head {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
font-size: 12px;
font-weight: 600;
}
.mt-success-card__grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
}
@media (max-width: 800px) {
.mt-success-card__grid {
grid-template-columns: 1fr;
}
}
.mt-success-side__label {
font-size: 12px;
font-weight: 600;
margin-bottom: 6px;
}
.mt-group {
border: 1px dashed rgba(148, 163, 184, 0.35);
border-radius: 8px;
padding: 8px;
margin-bottom: 6px;
}
.mt-group__head {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 11px;
opacity: 0.75;
}
.mt-group__or,
.mt-group__and {
font-size: 11px;
font-weight: 700;
letter-spacing: 0.04em;
opacity: 0.7;
margin: 2px 0;
}
.mt-side-hint {
margin: 0 0 6px;
font-size: 11px;
}
.mt-chip-group {
margin-bottom: 8px;
}
.mt-chip-group__label {
display: block;
font-size: 11px;
opacity: 0.65;
margin-bottom: 4px;
}
.mt-success-card__formula {
margin-top: 8px;
font-size: 12px;
padding-top: 8px;
border-top: 1px dashed rgba(148, 163, 184, 0.35);
}
.mt-arrow {
font-weight: 700;
opacity: 0.85;
}
.mt-editor__more {
border-top: 1px solid rgba(148, 163, 184, 0.22);
padding-top: 8px;
}

View file

@ -0,0 +1,377 @@
/* biz_state batch workbook */
/* biz_state batch workbook (Excel-like sheets) */
.bs-workbook-modal .bs-workbook-body {
min-height: min(62vh, 640px);
}
.bs-workbook-meta {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 12px;
}
.bs-alias-link {
appearance: none;
border: 0;
background: transparent;
padding: 0;
margin: 0;
color: var(--nx-accent-text);
cursor: pointer;
text-align: left;
max-width: 160px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.bs-alias-link:hover {
text-decoration: underline;
}
.bs-alias-link:disabled {
cursor: default;
opacity: 0.6;
text-decoration: none;
}
.bs-id-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
width: 100%;
min-width: 0;
padding: 6px 8px;
border-radius: 6px;
border: 1px solid rgba(148, 163, 184, 0.2);
background: rgb(var(--nx-ink-deep-rgb) / 0.45);
}
.bs-id-row--inline {
width: auto;
flex: 1 1 220px;
}
.bs-id-row__label {
flex: 0 0 auto;
font-size: 11px;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--nx-text-muted);
}
.bs-id-row__value {
flex: 1 1 auto;
min-width: 0;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 12px;
line-height: 1.4;
color: var(--nx-text);
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
word-break: normal;
}
.bs-sheet-cmd-bar {
display: flex;
flex-direction: column;
gap: 6px;
padding: 8px 10px;
border-radius: 8px;
border: 1px solid rgba(148, 163, 184, 0.22);
background: rgb(var(--nx-ink-rgb) / 0.45);
}
.bs-sheet-cmd-bar__label {
font-size: 11px;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--nx-text-muted);
}
.bs-sheet-cmd-list {
display: flex;
flex-direction: column;
gap: 6px;
}
.bs-sheet-cmd-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
justify-content: space-between;
}
.bs-sheet-cmd-code {
flex: 1 1 240px;
min-width: 0;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 12px;
line-height: 1.45;
color: var(--nx-text);
background: rgb(var(--nx-ink-deep-rgb) / 0.55);
border: 1px solid rgba(148, 163, 184, 0.18);
border-radius: 6px;
padding: 6px 8px;
overflow: auto;
white-space: nowrap;
}
.bs-sheet-cmd-code--block {
white-space: pre-wrap;
word-break: break-all;
}
.bs-sheet-cmd-actions {
display: flex;
align-items: center;
gap: 8px;
flex: 0 1 auto;
flex-wrap: wrap;
max-width: 100%;
}
.bs-commands-card-list {
display: flex;
flex-direction: column;
gap: 8px;
max-height: min(48vh, 520px);
overflow: auto;
padding: 2px;
}
.bs-commands-card {
padding: 8px 10px;
border-radius: 8px;
border: 1px solid rgba(148, 163, 184, 0.22);
background: rgb(var(--nx-ink-rgb) / 0.45);
}
.bs-commands-card__msg {
flex: 1 0 100%;
margin-top: 2px;
font-size: 12px;
color: var(--nx-text-muted);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.bs-cmd-metric {
font-size: 11px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.bs-inline-cmd {
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 12px;
color: var(--nx-text-soft);
}
.bs-rawlog-body {
min-height: min(50vh, 480px);
}
.bs-rawlog-stats {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 12px;
}
.bs-batch-message {
display: flex;
flex-direction: column;
gap: 4px;
width: 100%;
padding: 8px 10px;
border-radius: 8px;
border: 1px solid rgba(148, 163, 184, 0.28);
background: rgb(var(--nx-ink-rgb) / 0.55);
}
.bs-batch-message__label {
font-size: 11px;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--nx-text-muted);
}
.bs-batch-message__body {
margin: 0;
white-space: pre-wrap;
word-break: break-word;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 12px;
line-height: 1.45;
color: var(--nx-text);
}
.bs-batch-message--alert {
border-color: rgba(248, 113, 113, 0.28);
background: rgba(127, 29, 29, 0.22);
}
.bs-batch-message--alert .bs-batch-message__label {
color: #fca5a5;
}
.bs-batch-message--alert .bs-batch-message__body {
color: #fecaca;
}
.bs-msg-cell {
max-width: 220px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 12px;
}
.bs-cmd-stat {
font-size: 11px;
white-space: nowrap;
}
.bs-collect-detail-modal .bs-sheet-table {
max-height: min(48vh, 480px);
overflow: auto;
}
.bs-collect-detail-modal .bs-collect-detail-table table {
border-collapse: separate;
border-spacing: 0;
}
.bs-collect-detail-modal .bs-collect-detail-table thead th {
position: sticky;
top: 0;
z-index: 3;
background: rgb(var(--nx-ink-rgb) / 0.97);
box-shadow: 0 1px 0 rgba(148, 163, 184, 0.25);
}
.bs-rawlog-pre {
flex: 1 1 auto;
margin: 0;
padding: 12px 14px;
max-height: min(56vh, 560px);
overflow: auto;
border-radius: 8px;
border: 1px solid rgba(148, 163, 184, 0.22);
background: rgb(var(--nx-ink-deep-rgb) / 0.72);
color: var(--nx-text);
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 12px;
line-height: 1.5;
white-space: pre-wrap;
word-break: break-word;
}
.bs-sheet-filter {
align-items: center;
}
.bs-sheet-count {
white-space: nowrap;
font-size: 12px;
}
.bs-sheet-table {
flex: 1 1 auto;
min-height: 240px;
max-height: min(48vh, 520px);
overflow: auto;
border-collapse: separate;
}
.bs-workbook-modal .bs-sheet-table {
overflow: auto;
}
.bs-workbook-modal .bs-sheet-table table {
border-collapse: separate;
border-spacing: 0;
}
.bs-workbook-modal .bs-sheet-table thead th {
position: sticky;
top: 0;
z-index: 2;
background: rgb(var(--nx-ink-rgb) / 0.98) !important;
box-shadow: 0 1px 0 rgba(148, 163, 184, 0.22);
}
.bs-cmp-result-table.bs-sheet-table {
max-height: none;
}
.bs-sheet-tabs {
display: flex;
flex-wrap: wrap;
gap: 4px;
align-items: flex-end;
margin-top: 4px;
padding: 6px 4px 0;
border-top: 1px solid rgba(148, 163, 184, 0.2);
}
.bs-sheet-tabs--top {
align-items: center;
margin-top: 0;
margin-bottom: 2px;
padding: 0 0 8px;
border-top: none;
border-bottom: 1px solid rgba(148, 163, 184, 0.22);
max-height: 88px;
overflow: auto;
}
.bs-sheet-tabs--top .bs-sheet-tab {
border-radius: 6px;
border-bottom: 1px solid rgba(148, 163, 184, 0.28);
}
.bs-sheet-tabs--top .bs-sheet-tab.is-active {
box-shadow: none;
border-color: rgb(var(--nx-accent-rgb) / 0.55);
background: rgba(37, 99, 235, 0.2);
color: var(--nx-accent-text);
}
.bs-sheet-tab {
appearance: none;
border: 1px solid rgba(148, 163, 184, 0.28);
border-bottom: none;
border-radius: 6px 6px 0 0;
background: rgb(var(--nx-ink-rgb) / 0.55);
color: var(--nx-text-soft);
padding: 6px 12px;
font-size: 12px;
cursor: pointer;
line-height: 1.2;
}
.bs-sheet-tab:hover {
background: rgb(var(--nx-surface-3-rgb) / 0.9);
color: var(--nx-text);
}
.bs-sheet-tab.is-active {
background: rgb(var(--nx-surface-3-rgb) / 0.98);
border-color: rgb(var(--nx-accent-rgb) / 0.55);
color: var(--nx-text-strong);
font-weight: 600;
box-shadow: 0 -1px 0 rgb(var(--nx-accent-rgb) / 0.45) inset;
}
.bs-sheet-tab__count {
margin-left: 6px;
opacity: 0.65;
font-variant-numeric: tabular-nums;
}

View file

@ -0,0 +1,171 @@
/* Batch collection page */
.collect-commands {
width: 100%;
min-height: 160px;
font-family: ui-monospace, Consolas, monospace;
font-size: 13px;
line-height: 1.4;
padding: 10px;
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 6px;
background: var(--nx-field);
color: var(--nx-text);
resize: vertical;
}
.collect-meta {
font-size: 13px;
color: var(--nx-text-muted);
margin-right: auto;
}
.collect-create-panel__head {
margin-bottom: 0;
}
.collect-create-panel--collapsed {
padding-bottom: 16px;
}
.collect-create-panel h3 {
margin: 0;
font-size: 15px;
font-weight: 600;
color: var(--nx-text-strong);
}
.collect-selected-block,
.collect-pick-block {
margin-top: 20px;
padding-top: 16px;
border-top: 1px solid rgba(148, 163, 184, 0.18);
}
.collect-selected-block__head {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 10px 16px;
margin-bottom: 10px;
}
.collect-selected-list {
display: flex;
flex-direction: column;
gap: 8px;
max-height: 220px;
overflow: auto;
padding: 4px 0;
}
.collect-selected-chip {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 8px 12px;
background: rgb(var(--nx-ink-rgb) / 0.85);
border: 1px solid rgba(148, 163, 184, 0.22);
border-radius: 8px;
color: var(--nx-text);
}
.collect-selected-chip__main {
display: flex;
flex-direction: column;
gap: 2px;
min-width: 0;
}
.collect-selected-chip__meta {
font-size: 12px;
color: var(--nx-text-muted);
}
.collect-pick-filters {
margin-bottom: 12px;
}
.collect-cmd-preview {
font-size: 12px;
background: rgb(var(--nx-ink-deep-rgb) / 0.55);
border: 1px solid rgba(148, 163, 184, 0.22);
border-radius: 6px;
padding: 10px;
max-height: 120px;
overflow: auto;
white-space: pre-wrap;
color: var(--nx-text-soft);
font-family: ui-monospace, Consolas, monospace;
}
.collect-cmd-preview--modal {
flex: 0 0 auto;
margin: 0 0 10px;
max-height: 88px;
}
.collect-create-modal .collect-selected-block,
.collect-create-modal .collect-pick-block {
margin-top: 16px;
}
.collect-create-modal .panel__toolbar {
margin-bottom: 10px;
padding-bottom: 8px;
}
.collect-runs-panel {
display: flex;
flex-direction: column;
gap: 10px;
}
.collect-runs-toolbar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 12px;
}
.collect-runs-filter {
display: flex;
align-items: center;
gap: 8px;
font-size: 13px;
color: var(--nx-text-muted);
}
.collect-runs-filter select {
min-width: 140px;
padding: 6px 8px;
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 6px;
background: var(--nx-field);
color: var(--nx-text);
}
.collect-runs-filter input {
min-width: 180px;
padding: 6px 8px;
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 6px;
background: var(--nx-field);
color: var(--nx-text);
}
.collect-run-message {
max-width: 420px;
max-height: 160px;
overflow: auto;
white-space: pre-wrap;
word-break: break-word;
font-size: 12px;
line-height: 1.45;
color: var(--nx-text-soft);
padding: 6px 8px;
background: rgb(var(--nx-ink-deep-rgb) / 0.55);
border: 1px solid rgba(148, 163, 184, 0.22);
border-radius: 6px;
}

View file

@ -0,0 +1,543 @@
/* Login page */
.login-page {
--login-accent: var(--nx-accent-strong);
--login-accent-deep: var(--nx-accent-strong);
--login-ink: rgba(255, 255, 255, 0.92);
--login-muted: rgba(255, 255, 255, 0.55);
--login-field: rgba(255, 255, 255, 0.08);
--login-field-border: rgba(255, 255, 255, 0.14);
--login-danger: #fda29b;
--login-rail-w: clamp(360px, 30vw, 420px);
position: relative;
isolation: isolate;
min-height: 100vh;
overflow: hidden;
display: grid;
grid-template-columns: minmax(0, 1fr) var(--login-rail-w);
align-items: stretch;
background: #00050a;
font-family: "Segoe UI", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
color: var(--login-ink);
}
.login-page__space {
position: absolute;
inset: 0;
z-index: 1;
display: flex;
align-items: center;
/* Center earth within the left stage (not under the form rail). */
justify-content: center;
padding: 3vh calc(var(--login-rail-w) + 3vw) 3vh 5vw;
background: url("/login-space.webp") center / cover no-repeat;
}
.login-page__space::before {
content: "";
position: absolute;
inset: 0;
z-index: 2;
pointer-events: none;
background:
linear-gradient(
90deg,
transparent 0%,
transparent 52%,
rgb(var(--nx-ink-deep-rgb) / 0.18) 70%,
rgb(var(--nx-ink-deep-rgb) / 0.48) 88%,
rgb(var(--nx-ink-deep-rgb) / 0.72) 100%
),
linear-gradient(180deg, rgba(0, 0, 0, 0.1) 0%, transparent 30%, transparent 72%, rgba(0, 0, 0, 0.38) 100%);
}
/* Tiny sun flare — upper-left void. */
.login-page__flares {
position: absolute;
inset: 0;
z-index: 4;
pointer-events: none;
overflow: hidden;
}
.login-page__flare {
position: absolute;
border-radius: 50%;
pointer-events: none;
opacity: 0.85;
}
.login-page__flare--a {
width: 44px;
height: 44px;
left: 7%;
top: 11%;
background:
radial-gradient(
circle at 50% 50%,
rgba(245, 250, 255, 0.92) 0%,
rgba(170, 210, 255, 0.48) 28%,
rgba(90, 150, 245, 0.14) 55%,
transparent 78%
);
box-shadow: 0 0 16px 3px rgba(120, 180, 255, 0.2);
animation: login-flare-pulse-a 10s ease-in-out infinite alternate;
}
.login-planet {
position: relative;
z-index: 1;
width: min(500px, 38vw, 62vmin);
height: min(500px, 38vw, 62vmin);
border-radius: 50%;
transform: rotate(5deg);
animation: login-planet-enter 1.8s cubic-bezier(0.76, -0.46, 0.37, 0.99) both;
}
.login-planet__earth {
position: relative;
z-index: 1;
width: 100%;
height: 100%;
border-radius: 50%;
overflow: hidden;
/* Soft dissolve into space — no outer glow (Earth does not emit light). */
-webkit-mask-image: radial-gradient(circle at 50% 50%, #000 87%, transparent 100%);
mask-image: radial-gradient(circle at 50% 50%, #000 87%, transparent 100%);
transform-origin: center center;
}
/* Gentle volume shade — cooler blue midtones. */
.login-planet__earth::before {
content: "";
position: absolute;
z-index: 1;
inset: 0;
border-radius: 50%;
pointer-events: none;
background: linear-gradient(
148deg,
rgba(70, 130, 210, 0.16) 0%,
rgba(45, 100, 185, 0.08) 20%,
transparent 42%,
rgb(var(--nx-ink-deep-rgb) / 0.22) 72%,
rgb(var(--nx-ink-deep-rgb) / 0.42) 100%
);
}
/*
* Blue atmospheric limb (scattered sunlight) — stays on the sphere only.
*/
.login-planet__earth::after {
content: "";
position: absolute;
z-index: 2;
inset: 0;
border-radius: 50%;
pointer-events: none;
background:
radial-gradient(
120% 95% at 10% 12%,
rgba(55, 130, 230, 0.42) 0%,
rgba(40, 110, 210, 0.22) 28%,
rgba(30, 90, 185, 0.08) 48%,
transparent 66%
),
radial-gradient(
circle at 50% 50%,
transparent 74%,
rgba(40, 105, 200, 0.14) 88%,
rgba(50, 120, 215, 0.22) 94%,
transparent 100%
);
box-shadow:
inset 0 0 20px 4px rgba(45, 110, 200, 0.28),
inset 22px 26px 32px 4px rgba(60, 130, 220, 0.12),
inset -20px -24px 40px 10px rgb(var(--nx-ink-deep-rgb) / 0.3);
animation: login-earth-inner 2.2s ease-in-out 0.7s both;
}
.login-planet__textures {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
background-color: rgba(8, 28, 72, 0.2);
/* Pre-brightened asset — no live CSS filter (that was the GPU thrash). */
background-image: url("/login-earth-night-bright.webp");
background-repeat: repeat-x;
background-size: 200%;
animation: login-earth-spin 80s linear infinite;
}
.login-page__rail {
position: relative;
z-index: 5;
grid-column: 2;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
min-width: 0;
padding: 48px clamp(32px, 3.5vw, 52px) 48px 8px;
}
.login-card {
width: 100%;
max-width: 340px;
display: flex;
flex-direction: column;
gap: 15px;
padding: 26px 24px 28px;
border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgb(var(--nx-ink-rgb) / 0.82);
/* Lighter blur — full blur over the spinning globe was a steady GPU cost. */
backdrop-filter: blur(8px) saturate(1.08);
-webkit-backdrop-filter: blur(8px) saturate(1.08);
box-shadow:
0 18px 48px rgba(0, 0, 0, 0.32),
0 0 0 1px rgba(120, 170, 255, 0.07),
inset 0 1px 0 rgba(255, 255, 255, 0.07);
animation: login-card-in 520ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
.login-card__head {
display: flex;
align-items: baseline;
justify-content: flex-start;
gap: 10px;
flex-wrap: wrap;
margin-bottom: 2px;
}
.login-card__brand,
.login-card__title {
margin: 0;
font-family: "Segoe UI", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
font-size: clamp(1.55rem, 4vw, 1.85rem);
font-weight: 700;
line-height: 1.15;
color: rgba(226, 232, 240, 0.88);
}
.login-card__brand {
letter-spacing: 0.1em;
text-shadow: 0 0 22px rgb(var(--nx-accent-rgb) / 0.28);
animation: login-brand-in 700ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
.login-card__title {
font-weight: 650;
letter-spacing: 0.02em;
color: rgba(203, 213, 225, 0.9);
}
.login-card__hint {
margin: -4px 0 4px;
color: var(--login-muted);
font-size: 13px;
line-height: 1.45;
}
.login-card__sr {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.login-card__label {
position: relative;
display: block;
}
.login-card__label input,
.login-card__password input {
width: 100%;
height: 44px;
padding: 0 14px;
border: 1px solid var(--login-field-border);
border-radius: 10px;
background: var(--login-field);
color: #fff;
font: inherit;
font-size: 15px;
box-sizing: border-box;
transition: border-color 160ms ease, box-shadow 160ms ease, background 160ms ease;
}
.login-card__label input::placeholder,
.login-card__password input::placeholder {
color: rgba(255, 255, 255, 0.42);
}
.login-card__password {
position: relative;
display: block;
width: 100%;
}
.login-card__password input {
padding-right: 44px !important;
}
.login-card__eye {
position: absolute;
top: 50%;
right: 6px;
z-index: 2;
transform: translateY(-50%);
width: 34px;
height: 34px;
padding: 0;
border: 0;
border-radius: 8px;
background: transparent;
color: rgba(255, 255, 255, 0.55);
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.login-card__eye:hover {
color: var(--nx-accent-text);
}
.login-card__eye:focus-visible {
outline: none;
color: var(--nx-accent-text);
box-shadow: 0 0 0 2px rgb(var(--nx-accent-rgb) / 0.35);
}
.login-card__eye svg {
display: block;
pointer-events: none;
}
.login-card__label input:focus,
.login-card__password input:focus {
outline: none;
border-color: rgb(var(--nx-accent-rgb) / 0.7);
box-shadow: 0 0 0 3px rgb(var(--nx-accent-rgb) / 0.22);
background: rgba(255, 255, 255, 0.1);
}
.login-card__label input:disabled,
.login-card__password input:disabled {
opacity: 0.65;
cursor: not-allowed;
}
.login-card__error {
color: var(--login-danger);
font-size: 13px;
line-height: 1.4;
padding: 8px 10px;
border-radius: 8px;
background: rgba(180, 35, 24, 0.22);
border: 1px solid rgba(253, 162, 155, 0.28);
animation: login-error-in 220ms ease both;
}
.login-card__submit {
margin-top: 8px;
height: 44px;
border: 0;
border-radius: 9999px;
background: linear-gradient(to right, var(--nx-accent-strong), var(--nx-accent-strong), var(--nx-accent-strong));
color: #fff;
font-family: "Segoe UI", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
font-size: 15px;
font-weight: 600;
letter-spacing: 0.04em;
box-shadow:
0 8px 15px -3px rgb(var(--nx-accent-rgb) / 0.5),
0 4px 6px -4px rgb(var(--nx-accent-rgb) / 0.5);
cursor: pointer;
transition: transform 140ms ease, filter 140ms ease, opacity 140ms ease;
}
.login-card__submit:hover:not(:disabled) {
filter: brightness(1.06);
transform: translateY(-1px);
}
.login-card__submit:active:not(:disabled) {
transform: translateY(0);
filter: brightness(0.98);
}
.login-card__submit:disabled {
opacity: 0.55;
cursor: not-allowed;
}
.login-card__submit--ghost,
.login-card__submit + .login-card__submit {
margin-top: 0;
background: transparent;
border: 1px solid rgb(var(--nx-accent-rgb) / 0.7);
color: var(--nx-accent-text);
box-shadow: none;
}
.login-card__submit--ghost:hover:not(:disabled),
.login-card__submit + .login-card__submit:hover:not(:disabled) {
background: rgb(var(--nx-accent-rgb) / 0.12);
filter: none;
}
@keyframes login-planet-enter {
0% {
transform: scale(0.92) rotate(-5deg);
opacity: 0.65;
}
100% {
transform: rotate(5deg);
opacity: 1;
}
}
@keyframes login-earth-spin {
from {
background-position: calc(120% + 120px) 0;
}
to {
background-position: calc(-80% + 120px) 0;
}
}
@keyframes login-earth-inner {
0% {
opacity: 0.55;
}
100% {
opacity: 1;
}
}
@keyframes login-card-in {
from {
opacity: 0;
transform: translateY(12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes login-brand-in {
from {
opacity: 0;
letter-spacing: 0.24em;
transform: translateY(8px);
}
to {
opacity: 1;
letter-spacing: 0.12em;
transform: translateY(0);
}
}
@keyframes login-error-in {
from {
opacity: 0;
transform: translateY(-4px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes login-flare-pulse-a {
from { opacity: 0.7; transform: scale(0.96); }
to { opacity: 1; transform: scale(1.08); }
}
/* Pause infinite loops when the login tab is backgrounded (class set by LoginShell). */
html.login-page--paused .login-planet__textures,
html.login-page--paused .login-page__flare {
animation-play-state: paused !important;
}
@media (prefers-reduced-motion: reduce) {
/* Keep ambient earth spin; only drop entrance flourishes. */
.login-planet,
.login-planet__earth::after,
.login-card,
.login-card__brand,
.login-card__error,
.login-page__flare {
animation: none !important;
}
.login-page__flare {
opacity: 0.85;
}
.login-planet {
transform: rotate(5deg);
}
.login-card__submit:hover:not(:disabled) {
transform: none;
}
}
@media (max-width: 1200px) {
.login-page {
--login-rail-w: clamp(340px, 34vw, 400px);
}
.login-planet {
width: min(440px, 40vw, 58vmin);
height: min(440px, 40vw, 58vmin);
}
}
@media (max-width: 820px) {
.login-page {
grid-template-columns: 1fr;
}
.login-page__space {
justify-content: center;
padding: 0;
}
.login-page__space::before {
background:
linear-gradient(180deg, rgba(0, 0, 0, 0.18) 0%, transparent 30%, transparent 48%, rgba(0, 0, 0, 0.72) 100%);
}
.login-planet {
width: min(420px, 78vmin);
height: min(420px, 78vmin);
opacity: 0.9;
}
.login-page__rail {
grid-column: 1;
min-height: 100vh;
padding: 28px 18px 36px;
}
.login-card {
max-width: 380px;
padding: 20px 18px 22px;
}
.login-card__brand,
.login-card__title {
font-size: 1.4rem;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,833 @@
/*
* NetX design language — loaded last. Modern blue.
*
* Deep navy surfaces with soft gradients, 8/12px rounded shapes, a vivid blue
* accent for primary actions and focus, gentle glows, lift-on-hover.
*
* Palette comes from theme/tokens.css. This layer re-shapes primitives that
* legacy page CSS styled inconsistently. Prefer editing the owning
* component/page file; add here only for cross-cutting visual language.
*
* Sections: 1 base · 2 header · 3 workbench · 4 nav/panels · 5 buttons ·
* 6 fields/forms · 7 tables · 8 tags · 9 modals · 10 login
*/
/* ------------------------------------------------------------------ 1. Base */
html {
scrollbar-color: var(--nx-line-strong) transparent;
}
*::-webkit-scrollbar-track,
*::-webkit-scrollbar-corner {
background: transparent;
}
*::-webkit-scrollbar-thumb {
background: var(--nx-line-strong);
border: 2px solid transparent;
background-clip: padding-box;
border-radius: 999px;
}
*::-webkit-scrollbar-thumb:hover {
background: #64748b;
background-clip: padding-box;
}
body {
background: var(--nx-bg);
color: var(--nx-text);
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
::selection {
background: rgb(var(--nx-accent-rgb) / 0.35);
color: #fff;
}
:where(a, button, [role="button"], summary, [tabindex]):focus-visible {
outline: none;
box-shadow: var(--nx-ring);
}
input[type="checkbox"],
input[type="radio"] {
accent-color: var(--nx-accent-strong);
}
table,
.wb-stat__value,
.wb-fleet__row strong,
.pt-list-kpi__value {
font-variant-numeric: tabular-nums;
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* ----------------------------------------------------------------- 2. Header */
/* Height stays 48px: several pages use calc(100vh - 48px). */
.app--shell .app-brand {
background: linear-gradient(180deg, var(--nx-surface-2) 0%, var(--nx-surface-1) 100%);
border-bottom: 1px solid var(--nx-line);
box-shadow: 0 1px 0 rgb(var(--nx-accent-rgb) / 0.06);
}
.app--shell .app-brand__logo {
font-size: 16px;
font-weight: 800;
letter-spacing: 0.22em;
background: linear-gradient(90deg, #ffffff 0%, #9fcbff 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.app--shell .app-brand__sep {
background: var(--nx-line-strong);
}
.app--shell .app-brand__module-title {
font-size: 14px;
font-weight: 600;
color: var(--nx-text);
}
.app--shell .app-brand .app-brand__apps {
border-radius: var(--nx-radius-sm);
color: var(--nx-text-muted);
}
.app--shell .app-brand .app-brand__apps:hover,
.app--shell .app-brand .app-brand__apps:focus-visible {
background: var(--nx-accent-soft);
color: #fff;
}
.app--shell .app-brand .conn-pill.conn-pill--on-brand,
.app--shell .app-brand .header-menu__trigger.header-menu__trigger--on-brand {
height: 26px;
border-radius: 999px;
border-color: var(--nx-line-strong);
background: rgb(255 255 255 / 0.05);
color: var(--nx-text-muted);
font-size: 12px;
transition: background 0.14s ease, border-color 0.14s ease, color 0.14s ease;
}
.app--shell .app-brand .conn-pill.conn-pill--on-brand.conn-pill--user {
color: var(--nx-text);
font-weight: 500;
}
.app--shell .app-brand .conn-pill.conn-pill--on-brand:hover,
.app--shell .app-brand .header-menu__trigger.header-menu__trigger--on-brand:hover {
background: var(--nx-accent-soft);
border-color: rgb(var(--nx-accent-rgb) / 0.6);
color: #fff;
}
/* -------------------------------------------------------------- 3. Workbench */
.app--shell .app-main:has(> .workbench) {
background:
radial-gradient(900px 380px at 12% -8%, rgb(var(--nx-accent-rgb) / 0.1), transparent 65%),
radial-gradient(700px 320px at 100% 0%, rgb(52 211 153 / 0.05), transparent 60%),
var(--nx-bg);
}
.app--shell .workbench {
gap: 16px;
}
/* Soft gradient plate instead of the corner-bracket HUD frame. */
.app--shell .wb-panel {
border: 1px solid var(--nx-line);
border-radius: var(--nx-radius-lg);
background: linear-gradient(180deg, var(--nx-surface-2) 0%, var(--nx-surface-1) 100%);
box-shadow: var(--nx-shadow-panel);
}
.app--shell .wb-head__title {
font-family: var(--nx-font-sans);
font-size: 22px;
font-weight: 700;
letter-spacing: 0.01em;
color: var(--nx-text-strong);
}
.app--shell .wb-head__health {
height: 24px;
padding: 0 10px;
border-radius: 999px;
font-family: var(--nx-font-sans);
font-size: 12px;
letter-spacing: 0;
}
/* Section captions: sans, readable, with a small gradient bar. */
.app--shell .wb-section__title,
.app--shell .wb-fleet__title,
.app--shell .wb-rail__title,
.app--shell .wb-fleet__card-label {
font-family: var(--nx-font-sans);
font-size: 13px;
font-weight: 650;
letter-spacing: 0.02em;
text-transform: none;
color: var(--nx-text);
}
.app--shell .wb-section__title {
display: flex;
align-items: center;
gap: 8px;
}
.app--shell .wb-section__title::before {
content: "";
width: 3px;
height: 14px;
border-radius: 2px;
background: var(--nx-gradient-accent);
}
.app--shell .wb-strip__tag,
.app--shell .wb-strip__tag--soft {
font-size: 11px;
color: var(--nx-text-faint);
}
.app--shell .wb-stat__label {
font-size: 12px;
color: var(--nx-text-muted);
}
.app--shell .wb-stat__value {
font-size: 13px;
}
.app--shell .wb-stat__track {
height: 3px;
border-radius: 2px;
}
/* Content-height layout: no stretched empty panel above/below the tiles. */
.app--shell .wb-body {
flex: 0 0 auto;
grid-template-columns: minmax(0, 1fr) clamp(320px, 26vw, 400px);
gap: 16px;
}
.app--shell .wb-main {
height: auto;
gap: 16px;
}
.app--shell .wb-modules {
flex: 0 0 auto;
justify-content: flex-start;
gap: 22px;
padding: 20px 22px 24px;
}
.app--shell .wb-tiles {
grid-template-columns: repeat(auto-fill, minmax(176px, 1fr));
gap: 12px;
}
.app--shell .app-main .wb-tile {
min-height: 72px;
padding: 14px 16px;
gap: 14px;
border: 1px solid var(--nx-line);
border-radius: 10px;
background: var(--nx-surface-2);
transition: border-color 0.16s ease, background 0.16s ease, transform 0.16s ease, box-shadow 0.16s ease;
}
.app--shell .app-main .wb-tile:hover,
.app--shell .app-main .wb-tile:focus-visible {
border-color: rgb(var(--nx-accent-rgb) / 0.6);
background: linear-gradient(180deg, rgb(var(--nx-accent-rgb) / 0.16), var(--nx-surface-2));
box-shadow: 0 6px 18px rgb(0 0 0 / 0.3);
transform: translateY(-2px);
}
.app--shell .wb-tile__label {
font-size: 14px;
font-weight: 600;
color: var(--nx-text);
}
.app--shell .wb-card__icon {
--wb-icon: var(--nx-text-muted);
flex: 0 0 auto;
display: inline-flex;
align-items: center;
justify-content: center;
width: 38px;
height: 38px;
border-radius: 10px;
color: var(--wb-icon);
background: color-mix(in oklab, var(--wb-icon) 14%, transparent);
box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--wb-icon) 28%, transparent);
}
.app--shell .wb-card__icon svg {
width: 20px;
height: 20px;
}
.app--shell .wb-card__icon--blue {
--wb-icon: var(--nx-accent);
}
.app--shell .wb-card__icon--green {
--wb-icon: #34d399;
}
.app--shell .wb-card__icon--amber {
--wb-icon: var(--nx-warn);
}
.app--shell .wb-card__icon--slate {
--wb-icon: var(--nx-text-soft);
}
.app--shell .wb-fleet {
padding: 14px 16px 16px;
gap: 12px;
}
.app--shell .wb-fleet__head {
padding-bottom: 8px;
border-bottom-color: var(--nx-line-soft);
}
.app--shell .wb-fleet__grid {
gap: 12px;
}
.app--shell .wb-fleet__card {
padding: 12px 12px 10px;
border: 1px solid var(--nx-line);
border-radius: 10px;
background: rgb(var(--nx-ink-deep-rgb) / 0.45);
}
.app--shell button.wb-fleet__card:hover,
.app--shell button.wb-fleet__card:focus-visible,
.app--shell .wb-fleet__card--sched:hover,
.app--shell .wb-fleet__card--sched:focus-visible {
border-color: rgb(var(--nx-accent-rgb) / 0.55);
background: rgb(var(--nx-accent-rgb) / 0.1);
}
.app--shell .wb-fleet__card-badge,
.app--shell .wb-fleet__donut-unit,
.app--shell .wb-fleet__foot,
.app--shell .wb-fleet__row-age,
.app--shell .wb-fleet__sched-age,
.app--shell .wb-rail__meta,
.app--shell .wb-rail__progress,
.app--shell .wb-rail__empty {
color: var(--nx-text-faint);
}
.app--shell .wb-fleet__card-badge,
.app--shell .wb-fleet__foot {
font-size: 11px;
}
.app--shell .wb-rail {
padding: 16px 16px 14px;
}
.app--shell .wb-rail__count {
border-radius: 999px;
min-width: 20px;
height: 20px;
background: var(--nx-accent-soft);
color: var(--nx-accent-text);
}
.app--shell .wb-rail__list {
gap: 8px;
}
.app--shell .app-main button.wb-rail__item,
.app--shell .wb-rail__item {
padding: 11px 12px;
border: 1px solid var(--nx-line);
border-radius: 10px;
background: rgb(var(--nx-ink-deep-rgb) / 0.45);
}
.app--shell .app-main button.wb-rail__item:hover,
.app--shell .app-main button.wb-rail__item:focus-visible {
background: var(--nx-accent-soft);
border-color: rgb(var(--nx-accent-rgb) / 0.5);
}
.app--shell .wb-rail__item-title {
font-size: 13px;
}
.app--shell .wb-rail__item-meta {
font-size: 12px;
color: var(--nx-text-muted);
}
/* ---------------------------------------------------------- 4. Nav + panels */
.app--shell .network-nav {
width: 236px;
background: linear-gradient(180deg, var(--nx-surface-1) 0%, rgb(var(--nx-ink-deep-rgb) / 0.55) 100%);
border-right: 1px solid var(--nx-line);
}
.app--shell .network-nav__scroll {
padding: 12px 10px 18px;
}
.app--shell .network-nav__group-toggle,
.app--shell .app-main .network-nav__group-toggle,
.app--shell .network-nav .accordion__trigger.network-nav__group-toggle {
padding: 9px 10px;
border-radius: var(--nx-radius);
font-size: 12.5px;
font-weight: 650;
letter-spacing: 0.02em;
text-transform: none;
color: var(--nx-text-muted);
transition: background 0.14s ease, color 0.14s ease;
}
.app--shell .network-nav__group-toggle:hover,
.app--shell .app-main .network-nav__group-toggle:hover,
.app--shell .network-nav .accordion__trigger.network-nav__group-toggle:hover {
background: var(--nx-surface-2);
color: var(--nx-text);
}
.app--shell .network-nav__group.is-active-group .network-nav__group-toggle,
.app--shell .network-nav__group.is-active-group .accordion__trigger.network-nav__group-toggle {
color: var(--nx-accent);
}
.app--shell .network-nav__list {
gap: 2px;
margin-left: 18px;
padding-left: 8px;
border-left-color: var(--nx-line);
}
/* Single-level menus (audit) are not a tree: no indent, no guide line. */
.app--shell .network-nav__list--flat {
margin-left: 0;
padding-left: 0;
border-left: 0;
gap: 4px;
}
.app--shell .network-nav__link {
padding: 8px 12px;
border-radius: var(--nx-radius);
font-size: 13px;
color: var(--nx-text-muted);
}
.app--shell .network-nav__link:hover {
background: var(--nx-surface-2);
color: var(--nx-text);
}
.app--shell .network-nav__link.is-active {
background: rgb(var(--nx-accent-rgb) / 0.14);
color: #fff;
font-weight: 600;
box-shadow: inset 0 0 0 1px rgb(var(--nx-accent-rgb) / 0.3);
}
.app--shell .network-main {
background:
radial-gradient(1100px 420px at 0% 0%, rgb(var(--nx-accent-rgb) / 0.08), transparent 60%),
var(--nx-bg);
}
.app--shell .network-main > .panel,
.app--shell .network-main .page-stack > .panel,
.app--shell .network-main > .nm-page-panel,
.app--shell .app-main .card,
.app--shell .app-main .panel {
border: 1px solid var(--nx-line);
border-radius: var(--nx-radius-lg);
background: var(--nx-surface-1);
box-shadow: var(--nx-shadow-panel);
}
.app--shell .network-main .panel__toolbar {
border-bottom-color: var(--nx-line-soft);
}
.app--shell .network-main .panel__toolbar h2,
.app--shell .app-main .panel > h2 {
font-size: 18px;
font-weight: 700;
letter-spacing: 0;
color: var(--nx-text-strong);
}
.app--shell .network-main .filter-inline,
.app--shell .app-main .filter-inline {
border-radius: 10px !important;
background: rgb(var(--nx-ink-deep-rgb) / 0.5) !important;
border-color: var(--nx-line) !important;
}
.muted,
.app-main .muted {
color: var(--nx-text-muted);
}
/* Links on dark surfaces. */
a,
.link-btn,
.system-page button.linkish {
color: var(--nx-accent);
}
.system-page button.linkish:hover,
.link-btn:hover {
color: var(--nx-accent-text);
}
/* ---------------------------------------------------------------- 5. Buttons */
/* :where() keeps specificity at (0,1,1): enough to beat `.app-main button`,
while any component class (.wb-tile, .wb-rail__all …) still wins. */
:where(.app-main, .app-heroui-modal, .topo-heroui-modal) button.button {
border-radius: var(--nx-radius);
font-weight: 550;
transition: background 0.14s ease, border-color 0.14s ease, color 0.14s ease, box-shadow 0.14s ease,
transform 0.1s ease;
}
:where(.app-main, .app-heroui-modal, .topo-heroui-modal) button.button:where(:active:not(:disabled)) {
transform: translateY(1px);
}
:where(.app-main, .app-heroui-modal, .topo-heroui-modal) button.button:where(:disabled, [data-disabled="true"]) {
opacity: 0.45;
cursor: not-allowed;
}
:where(.app-main, .app-heroui-modal, .topo-heroui-modal) button.button--secondary {
background: var(--nx-surface-3);
border-color: var(--nx-line);
color: var(--nx-text);
}
:where(.app-main, .app-heroui-modal, .topo-heroui-modal) button.button--secondary:where(:hover:not(:disabled)) {
background: #1f3250;
border-color: rgb(var(--nx-accent-rgb) / 0.55);
}
:where(.app-main, .app-heroui-modal, .topo-heroui-modal) button.button--primary {
background: var(--nx-gradient-accent);
border-color: var(--nx-accent-strong);
color: #fff;
box-shadow: 0 1px 0 rgb(255 255 255 / 0.2) inset, 0 2px 10px rgb(37 99 235 / 0.3);
}
:where(.app-main, .app-heroui-modal, .topo-heroui-modal) button.button--primary:where(:hover:not(:disabled)) {
background: linear-gradient(180deg, #5b9bf8 0%, #3a74eb 100%);
}
:where(.app-main, .app-heroui-modal, .topo-heroui-modal) button.button--danger {
background: rgb(248 113 113 / 0.1);
border-color: rgb(248 113 113 / 0.38);
color: #fda4a4;
}
:where(.app-main, .app-heroui-modal, .topo-heroui-modal) button.button--danger:where(:hover:not(:disabled)) {
background: rgb(248 113 113 / 0.2);
border-color: rgb(248 113 113 / 0.65);
color: #fecaca;
}
:where(.app-main, .app-heroui-modal, .topo-heroui-modal) :is(button.button--tertiary, button.button--ghost) {
background: rgb(255 255 255 / 0.03);
border-color: var(--nx-line);
color: var(--nx-text);
}
:where(.app-main, .app-heroui-modal, .topo-heroui-modal)
:is(button.button--tertiary, button.button--ghost):where(:hover:not(:disabled)) {
background: var(--nx-surface-3);
border-color: rgb(var(--nx-accent-rgb) / 0.45);
}
/* ------------------------------------------------------------ 6. Fields/forms */
:where(.app-main, .app-heroui-modal, .topo-heroui-modal)
:is(input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]), select, textarea) {
border-color: var(--nx-line);
border-radius: var(--nx-radius);
transition: border-color 0.14s ease, box-shadow 0.14s ease;
}
:where(.app-main, .app-heroui-modal, .topo-heroui-modal)
:is(input:not([type="checkbox"], [type="radio"], [type="range"]), select, textarea):where(:hover:not(:disabled)) {
border-color: #42597a;
}
:is(.app-main, .app-heroui-modal, .topo-heroui-modal)
:is(input:not([type="checkbox"], [type="radio"], [type="range"]), select, textarea):focus {
outline: none;
border-color: var(--nx-accent) !important;
box-shadow: var(--nx-ring);
}
:where(.app-main, .app-heroui-modal, .topo-heroui-modal) :is(input, textarea)::placeholder {
color: var(--nx-text-faint);
}
.ui-field__label,
.ui-field__hint {
color: var(--nx-text-muted);
}
.ui-field__select {
border-radius: var(--nx-radius);
}
/* HeroUI TextField (.textfield) and native .ui-field share one grid.
`.form-grid label { flex-direction: column }` stacked the required-star
::after under the label text; keep labels inline and give every control the
same label gap + height so both columns line up. */
.form-grid {
align-items: start;
gap: 14px 16px;
}
.form-grid > :is(.textfield, .ui-field) {
display: flex;
flex-direction: column;
gap: 6px;
min-width: 0;
}
.form-grid label.label,
.form-grid .ui-field__label {
display: inline-flex;
flex-direction: row;
align-items: baseline;
gap: 4px;
font-size: 12.5px;
font-weight: 550;
color: var(--nx-text-muted);
}
.form-grid .label--required::after {
color: var(--nx-bad);
}
.form-grid :is(input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]), select) {
height: 38px;
min-height: 38px;
padding: 0 12px;
font-size: 14px;
}
.form-field-hint,
.form-hint,
.help-hint__trigger,
.app-main .help-hint__trigger {
color: var(--nx-text-faint);
}
.form-field-hint,
.form-hint {
font-size: 12px;
}
.form-fieldset {
border-color: var(--nx-line);
border-radius: 10px;
}
/* ----------------------------------------------------------------- 7. Tables */
:is(.app-main, .app-heroui-modal) .pt-list-table-wrap {
border-radius: 10px;
overflow-x: auto;
background: rgb(var(--nx-ink-deep-rgb) / 0.35);
}
:is(.app-main, .app-heroui-modal) .pt-list-table thead th,
:is(.app-main, .app-heroui-modal) .data-table thead th {
padding: 10px 12px;
background: var(--nx-surface-3) !important;
color: var(--nx-text-muted) !important;
font-size: 12px;
font-weight: 650;
letter-spacing: 0.02em;
text-transform: none;
border-bottom: 1px solid var(--nx-line-strong);
white-space: nowrap;
}
:is(.app-main, .app-heroui-modal) .pt-list-table tbody td,
:is(.app-main, .app-heroui-modal) .data-table tbody td {
padding: 10px 12px;
font-size: 13px;
line-height: 1.45;
vertical-align: middle;
border-bottom: 1px solid var(--nx-line-soft);
color: var(--nx-text);
}
:is(.app-main, .app-heroui-modal) .pt-list-table tbody tr:last-child td,
:is(.app-main, .app-heroui-modal) .data-table tbody tr:last-child td {
border-bottom: 0;
}
:is(.app-main, .app-heroui-modal) .pt-list-table tbody tr:hover td,
:is(.app-main, .app-heroui-modal) .data-table tbody tr:hover td {
background: rgb(var(--nx-accent-rgb) / 0.09) !important;
}
/* ------------------------------------------------------------------- 8. Tags */
.conn-pill,
.ne-stats-pill,
.pt-list-status,
.pill {
border-radius: 999px;
}
.chip {
font-weight: 600;
letter-spacing: 0;
}
.ne-stats-pill {
font-weight: 600;
}
/* ---------------------------------------------------------------- 9. Modals */
.app-heroui-modal .modal__dialog,
.app-heroui-modal__dialog,
.topo-heroui-modal .modal__dialog,
.topo-heroui-modal__dialog {
background: var(--nx-surface-1);
border: 1px solid var(--nx-line-strong);
border-radius: 14px;
box-shadow: var(--nx-shadow-pop);
}
.modal-backdrop,
.token-scopes-modal__backdrop,
.topo-modal__backdrop {
background: rgb(var(--nx-ink-deep-rgb) / 0.7) !important;
backdrop-filter: blur(3px);
}
.modal,
.app-main .modal,
.token-scopes-modal__panel,
.topo-modal__panel {
background: var(--nx-surface-1) !important;
border-color: var(--nx-line-strong) !important;
border-radius: 14px !important;
}
.toast,
.app-toast {
border-radius: 10px;
background: var(--nx-surface-2);
border-color: var(--nx-line-strong);
}
/* ------------------------------------------------------------------ 10. Login */
.login-page {
--login-accent: var(--nx-accent-strong);
--login-muted: var(--nx-text-muted);
}
.login-card {
max-width: 372px;
gap: 18px;
padding: 32px 30px 30px;
border-radius: 20px;
border-color: rgb(255 255 255 / 0.12);
background: rgb(var(--nx-ink-rgb) / 0.78);
backdrop-filter: blur(14px) saturate(1.15);
-webkit-backdrop-filter: blur(14px) saturate(1.15);
}
.login-card__head {
flex-direction: column-reverse;
align-items: flex-start;
gap: 4px;
margin-bottom: 4px;
}
.login-card__brand {
font-size: 2rem;
font-weight: 800;
letter-spacing: 0.28em;
background: linear-gradient(90deg, #ffffff 0%, #8fc2ff 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
text-shadow: none;
}
.login-card__title {
font-size: 14px;
font-weight: 500;
letter-spacing: 0.04em;
color: var(--nx-text-muted);
}
/* The username TextField sits outside .login-card__label/__password, so it
rendered with HeroUI defaults and did not match the password field. */
.login-card__form input {
width: 100%;
height: 46px;
padding: 0 14px;
border: 1px solid var(--login-field-border);
border-radius: 12px;
background: var(--login-field);
color: #fff;
font: inherit;
font-size: 15px;
box-sizing: border-box;
transition: border-color 160ms ease, box-shadow 160ms ease, background 160ms ease;
}
.login-card__form input::placeholder {
color: rgb(255 255 255 / 0.45);
}
.login-card__form input:focus {
outline: none;
border-color: rgb(var(--nx-accent-rgb) / 0.8);
box-shadow: 0 0 0 3px rgb(var(--nx-accent-rgb) / 0.25);
background: rgb(255 255 255 / 0.1);
}
.login-card__form {
gap: 14px;
}
.login-card__submit {
height: 46px;
border-radius: 12px;
letter-spacing: 0.08em;
}

View file

@ -0,0 +1,109 @@
/*
* NetX design tokens — the ONLY place raw palette values live.
*
* Direction: modern blue on the original NetX navy palette. Deep navy surfaces with soft gradients, 8/12px
* rounded shapes, the original blue accent used for primary actions and focus,
* gentle glows and lift-on-hover. Status colors stay semantic.
*
* Rules for new CSS:
* - Use var(--nx-*) — never raw hex / rgb() for surfaces, text, lines, accent.
* - Translucent surfaces: rgb(var(--nx-ink-rgb) / .6), not rgba(15,23,42,.6).
* - Status colors are semantic: --nx-ok / --nx-warn / --nx-bad.
*/
:root {
/* Surfaces — original navy, 4 elevation steps + inset field */
--nx-bg: #070b14;
--nx-surface-1: #0c1521;
--nx-surface-2: #111c2a;
--nx-surface-3: #162232;
--nx-field: #0b1220;
/* Channel triplets for translucent fills: rgb(var(--nx-ink-rgb) / .6) */
--nx-ink-rgb: 15 23 42; /* = surface-1 */
--nx-ink-deep-rgb: 2 8 23; /* darker than bg, for scrims / insets */
--nx-surface-3-rgb: 30 41 59;
--nx-accent-rgb: 59 130 246;
/* Lines */
--nx-line: #2b3748;
--nx-line-strong: #3a4a60;
--nx-line-soft: rgb(148 163 184 / 0.14);
/* Text — five tones, all >= 4.5:1 on surface-1 */
--nx-text-strong: #f1f5f9;
--nx-text: #e2e8f0;
--nx-text-soft: #cbd5e1;
--nx-text-muted: #94a3b8;
--nx-text-faint: #74849b;
/* Accent: blue. Primary actions, selection, focus, gradients. */
--nx-accent: #6ba9ec;
--nx-accent-strong: #3b82f6;
--nx-accent-text: #93c5fd;
--nx-accent-soft: rgb(var(--nx-accent-rgb) / 0.14);
/* Status — semantic only */
--nx-ok: #4ade80;
--nx-warn: #fbbf24;
--nx-bad: #f87171;
--nx-bad-text: #fecaca; /* readable text on a red wash */
--nx-ok-rgb: 74 222 128;
--nx-warn-rgb: 251 191 36;
--nx-bad-rgb: 248 113 113;
/* Shape: soft rounded corners */
--nx-radius-sm: 6px;
--nx-radius: 8px;
--nx-radius-lg: 12px;
--nx-ring: 0 0 0 3px rgb(var(--nx-accent-rgb) / 0.35);
--nx-shadow-panel: 0 1px 0 rgb(255 255 255 / 0.04) inset, 0 10px 28px rgb(0 0 0 / 0.28);
--nx-shadow-pop: 0 18px 48px rgb(0 0 0 / 0.55);
--nx-font-sans: "Segoe UI", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
--nx-font-mono: ui-monospace, "Cascadia Mono", "SF Mono", Consolas, monospace;
--nx-gradient-accent: linear-gradient(180deg, #3b82f6 0%, #2563eb 100%);
--nx-header-h: 48px; /* pages size themselves with calc(100vh - 48px) */
}
/* Legacy --nm-* tokens (hundreds of rules still read them) → single source. */
.app--shell {
--nm-accent: var(--nx-accent-strong);
--nm-header: var(--nx-bg);
--nm-chrome: var(--nx-bg);
--nm-main: var(--nx-bg);
--nm-nav: var(--nx-surface-1);
--nm-nav-border: var(--nx-line);
--nm-nav-hover: rgb(var(--nx-accent-rgb) / 0.08);
--nm-nav-active: rgb(var(--nx-accent-rgb) / 0.14);
--nm-nav-ink: var(--nx-text);
--nm-nav-muted: var(--nx-text-muted);
--nm-panel: var(--nx-surface-1);
--nm-panel-solid: var(--nx-surface-1);
--nm-panel-border: var(--nx-line);
--nm-brand: var(--nx-text-strong);
--nm-text: var(--nx-text);
--nm-muted: var(--nx-text-muted);
--nm-glass: rgb(var(--nx-ink-rgb) / 0.9);
--nm-glass-border: var(--nx-line);
--nm-ops-line: var(--nx-line);
--nm-ops-muted: var(--nx-text-muted);
--nm-ops-accent: var(--nx-accent);
--nm-ops-surface: var(--nx-surface-2);
}
/* HeroUI v3 tokens (oklch in its defaults) aligned to the same palette. */
.dark,
[data-theme="dark"] {
--background: var(--nx-bg);
--foreground: var(--nx-text);
--surface: var(--nx-surface-1);
--surface-secondary: var(--nx-surface-2);
--overlay: var(--nx-surface-1);
--accent: var(--nx-accent-strong);
--accent-foreground: #fff;
--muted: var(--nx-text-muted);
--border: var(--nx-line);
--field-background: var(--nx-field);
}