390 lines
11 KiB
CSS
390 lines
11 KiB
CSS
/* N7 Web Console design-system contract.
|
|
* Loaded last by Vite so every legacy surface consumes one geometry,
|
|
* typography, state and elevation scale while the runtime is migrated to
|
|
* Vue components incrementally. */
|
|
|
|
:root {
|
|
--n7-control-height-sm: 32px;
|
|
--n7-control-height: 38px;
|
|
--n7-icon-button-size: 38px;
|
|
--n7-radius-control: 10px;
|
|
--n7-radius-card: 14px;
|
|
--n7-radius-section: 16px;
|
|
--n7-radius-panel: 18px;
|
|
--n7-radius-dialog: 22px;
|
|
--n7-font-caption: 12px;
|
|
--n7-font-body: 13px;
|
|
--n7-font-card-title: 14px;
|
|
--n7-font-panel-title: 16px;
|
|
--n7-font-dialog-title: 22px;
|
|
--n7-shadow-card: inset 0 1px 0 var(--glass-highlight), 0 7px 20px color-mix(in oklch, var(--foreground) 8%, transparent);
|
|
--n7-shadow-panel: inset 0 1px 0 var(--glass-highlight), 0 14px 34px color-mix(in oklch, var(--foreground) 13%, transparent);
|
|
--n7-shadow-dialog: inset 0 1px 0 var(--glass-highlight), 0 28px 84px color-mix(in oklch, var(--foreground) 28%, transparent);
|
|
}
|
|
|
|
#app {
|
|
min-width: inherit;
|
|
min-height: 100dvh;
|
|
display: contents;
|
|
}
|
|
|
|
/* Workspace panels: one top-level geometry, distinct from their children. */
|
|
body.console-v2.v2-passive-display.v2-interactive-sync :is(
|
|
.main-panel > .v2-mode-rail,
|
|
#assistantDrawer,
|
|
.joint-twin-shell > .twin-band,
|
|
#v2DevicePanel,
|
|
#v2ExtensionPanel .v2-extension-sync-mount
|
|
) {
|
|
border-radius: var(--n7-radius-panel) !important;
|
|
box-shadow: var(--n7-shadow-panel) !important;
|
|
}
|
|
|
|
body.console-v2 :is(
|
|
.v2-sync-transport-field,
|
|
.v2-sync-execution-field,
|
|
.v2-can-command-panel,
|
|
.v2-control-link-card,
|
|
.v2-nfc-inline,
|
|
.v2-extension-gateway,
|
|
.v2-extension-synced-device,
|
|
.v2-extension-empty,
|
|
.v2-pet-card,
|
|
.v2-pet-presence-card,
|
|
.v2-device-card,
|
|
.v2-synced-device,
|
|
.mode-gallery-card,
|
|
.mode-editor-command-card,
|
|
.energy-kpi,
|
|
.energy-device-row,
|
|
.assistant-dispatched-controls,
|
|
.assistant-mode-draft,
|
|
.assistant-mode-created,
|
|
.assistant-control-suggestion
|
|
) {
|
|
border-radius: var(--n7-radius-card) !important;
|
|
box-shadow: var(--n7-shadow-card) !important;
|
|
}
|
|
|
|
body.console-v2 :is(
|
|
.v2-sync-log,
|
|
.v2-pet-card-region,
|
|
.mode-gallery-group,
|
|
.mode-editor-flow,
|
|
.v2-nfc-stage,
|
|
.energy-trend-card,
|
|
.energy-devices-card
|
|
) {
|
|
border-radius: var(--n7-radius-section) !important;
|
|
}
|
|
|
|
/* Only actionable cards float. Read-only panels remain spatially stable. */
|
|
body.console-v2 :is(
|
|
.v2-sync-log,
|
|
.v2-pet-card-region,
|
|
.mode-editor-flow,
|
|
.energy-trend-card,
|
|
.energy-devices-card
|
|
):is(:hover, :focus-within) {
|
|
transform: none !important;
|
|
box-shadow: var(--n7-shadow-card) !important;
|
|
}
|
|
|
|
/* The current DOM uses .twin-selector; the previous glass selector targeted
|
|
* the removed .twin-seat-switch class and produced white-on-white tabs. */
|
|
body.console-v2 .joint-twin-shell :is(.twin-selector, .twin-selector button, .twin-reset, .twin-focus-badge) {
|
|
color: var(--muted-foreground) !important;
|
|
background: var(--glass-card) !important;
|
|
border-color: var(--glass-line) !important;
|
|
box-shadow: inset 0 1px 0 var(--glass-highlight) !important;
|
|
}
|
|
|
|
body.console-v2 .joint-twin-shell .twin-selector button.active {
|
|
color: var(--primary-foreground) !important;
|
|
background: var(--primary) !important;
|
|
border-color: color-mix(in oklch, var(--primary) 72%, white 18%) !important;
|
|
}
|
|
|
|
/* Shared heading hierarchy. */
|
|
body.console-v2 :is(
|
|
#assistantDrawer h2,
|
|
.joint-twin-shell .twin-heading h3,
|
|
.v2-device-sync-board > header h3,
|
|
.v2-extension-sync-heading h3,
|
|
.v2-mode-rail .mode-rail-title
|
|
) {
|
|
font-size: var(--n7-font-panel-title) !important;
|
|
font-weight: 750 !important;
|
|
line-height: 1.25 !important;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
|
|
/* The log title shares a 217 px header with its filter, so it needs the
|
|
* compact card-title scale instead of the full panel-title scale. */
|
|
body.console-v2 .v2-sync-log h3 {
|
|
min-width: 0;
|
|
margin: 0;
|
|
overflow: hidden;
|
|
font-size: var(--n7-font-card-title) !important;
|
|
font-weight: 750 !important;
|
|
line-height: 1.25 !important;
|
|
letter-spacing: -0.02em;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* Sidebar disclosure, connection status and control-command readability use
|
|
* the same semantic tokens in both day and night themes. */
|
|
body.console-v2 .v2-sync-log[data-collapsed="true"] {
|
|
min-height: 0;
|
|
align-self: start;
|
|
grid-template-rows: auto;
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
body.console-v2 .v2-sync-log[data-collapsed="true"] > header {
|
|
border-bottom-color: transparent;
|
|
}
|
|
|
|
body.console-v2 .v2-sync-log[data-collapsed="true"] #v2LogFilter {
|
|
display: none;
|
|
}
|
|
|
|
body.console-v2 .v2-sync-log #v2SyncLogList[hidden] {
|
|
display: none !important;
|
|
}
|
|
|
|
body.console-v2 .v2-sync-log > header > div:first-child {
|
|
min-width: 0;
|
|
}
|
|
|
|
body.console-v2 .v2-sync-log .v2-sync-log-actions {
|
|
display: inline-flex;
|
|
flex: 0 0 auto;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
body.console-v2 .v2-sync-log .v2-sync-log-toggle {
|
|
min-width: 46px;
|
|
min-height: var(--n7-control-height-sm);
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 4px;
|
|
padding: 0 7px;
|
|
color: var(--muted-foreground);
|
|
background: var(--secondary);
|
|
border: 1px solid var(--input);
|
|
border-radius: var(--n7-radius-control);
|
|
cursor: pointer;
|
|
}
|
|
|
|
body.console-v2 .v2-sync-log .v2-sync-log-toggle:is(:hover, :focus-visible) {
|
|
color: var(--accent-foreground);
|
|
background: var(--accent);
|
|
border-color: var(--ring);
|
|
outline: none;
|
|
}
|
|
|
|
body.console-v2 .v2-sync-log .v2-sync-log-toggle svg {
|
|
width: 15px;
|
|
height: 15px;
|
|
transition: transform 160ms ease;
|
|
}
|
|
|
|
body.console-v2 .v2-sync-log .v2-sync-log-toggle[aria-expanded="true"] svg {
|
|
transform: rotate(180deg);
|
|
}
|
|
|
|
body.console-v2.v2-passive-display.v2-interactive-sync .v2-control-link-card {
|
|
min-height: 56px;
|
|
grid-template-columns: 10px minmax(0, 1fr);
|
|
gap: 10px;
|
|
margin: 0 !important;
|
|
padding: 10px 11px !important;
|
|
color: var(--card-foreground);
|
|
background: var(--glass-card) !important;
|
|
border: 1px solid var(--glass-line) !important;
|
|
border-radius: var(--n7-radius-card) !important;
|
|
box-shadow: var(--n7-shadow-card) !important;
|
|
-webkit-backdrop-filter: blur(16px) saturate(1.2);
|
|
backdrop-filter: blur(16px) saturate(1.2);
|
|
}
|
|
|
|
body.console-v2 .v2-control-link-card strong {
|
|
color: var(--card-foreground) !important;
|
|
}
|
|
|
|
body.console-v2 .v2-control-link-card small {
|
|
color: var(--muted-foreground) !important;
|
|
}
|
|
|
|
body.console-v2 .v2-control-link-card[data-state="online"] .v2-live-dot {
|
|
background: var(--status-online);
|
|
box-shadow: 0 0 0 4px color-mix(in oklch, var(--status-online) 18%, transparent);
|
|
}
|
|
|
|
body.console-v2 .v2-control-link-card[data-state="connecting"] .v2-live-dot {
|
|
background: var(--status-info);
|
|
box-shadow: 0 0 0 4px color-mix(in oklch, var(--status-info) 18%, transparent);
|
|
}
|
|
|
|
body.console-v2 .v2-control-link-card[data-state="degraded"] .v2-live-dot {
|
|
background: var(--status-warning);
|
|
box-shadow: 0 0 0 4px color-mix(in oklch, var(--status-warning) 18%, transparent);
|
|
}
|
|
|
|
body.console-v2 .v2-control-link-card[data-state="offline"] .v2-live-dot {
|
|
background: var(--status-offline);
|
|
box-shadow: 0 0 0 4px color-mix(in oklch, var(--status-offline) 18%, transparent);
|
|
}
|
|
|
|
body.console-v2.v2-passive-display.v2-interactive-sync
|
|
.v2-can-command-list li[data-can-channel]
|
|
.v2-can-command-actual code {
|
|
color: var(--card-foreground) !important;
|
|
}
|
|
|
|
body.console-v2 :is(
|
|
.mode-gallery-header h2,
|
|
.mode-editor-header h2,
|
|
.v2-extension-dialog > header h2,
|
|
.v2-extension-dialog form > header h2,
|
|
.energy-monitor-heading h2
|
|
) {
|
|
font-size: var(--n7-font-dialog-title) !important;
|
|
font-weight: 750 !important;
|
|
line-height: 1.2 !important;
|
|
}
|
|
|
|
body.console-v2 :is(
|
|
.mode-gallery-card-heading strong,
|
|
.v2-device-card-focus strong,
|
|
.v2-nfc-inline strong,
|
|
.v2-extension-gateway strong,
|
|
.v2-pet-card > header > strong,
|
|
.energy-trend-card h3,
|
|
.energy-devices-card h3
|
|
) {
|
|
font-size: var(--n7-font-card-title) !important;
|
|
line-height: 1.35 !important;
|
|
}
|
|
|
|
body.console-v2 :is(
|
|
.mode-editor-status,
|
|
.mode-gallery-footer,
|
|
.v2-pet-settings-footnote,
|
|
.v2-pet-card-fields > label > span,
|
|
.v2-pet-nfc-field output,
|
|
.energy-kpi > small,
|
|
.energy-kpi > em,
|
|
.energy-devices-card > footer
|
|
) {
|
|
font-size: var(--n7-font-caption) !important;
|
|
line-height: 1.45 !important;
|
|
}
|
|
|
|
/* One dialog radius, elevation and close-button size. */
|
|
body.console-v2 :is(
|
|
.mode-gallery,
|
|
.mode-editor,
|
|
.v2-nfc-dialog,
|
|
.v2-gscu-tcp-dialog,
|
|
.v2-pet-settings-dialog,
|
|
.energy-monitor-page
|
|
) {
|
|
border-radius: var(--n7-radius-dialog) !important;
|
|
box-shadow: var(--n7-shadow-dialog) !important;
|
|
}
|
|
|
|
body.console-v2 :is(
|
|
.mode-gallery-close,
|
|
.mode-editor-header > button,
|
|
.v2-extension-dialog [data-dialog-close],
|
|
.v2-extension-dialog [data-close-extension-dialog],
|
|
.v2-extension-dialog [data-close-nfc-dialog],
|
|
#energyMonitorClose
|
|
) {
|
|
width: var(--n7-icon-button-size) !important;
|
|
height: var(--n7-icon-button-size) !important;
|
|
min-width: var(--n7-icon-button-size);
|
|
min-height: var(--n7-icon-button-size);
|
|
border-radius: var(--n7-radius-control) !important;
|
|
}
|
|
|
|
/* Compact icon actions still meet a usable hit target without becoming a
|
|
* second visual system. */
|
|
body.console-v2 :is(
|
|
.twin-reset,
|
|
.mode-gallery-edit,
|
|
.mode-gallery-delete,
|
|
.v2-pet-card > header > button
|
|
) {
|
|
width: var(--n7-control-height-sm) !important;
|
|
height: var(--n7-control-height-sm) !important;
|
|
min-width: var(--n7-control-height-sm);
|
|
min-height: var(--n7-control-height-sm);
|
|
border-radius: var(--n7-radius-control) !important;
|
|
}
|
|
|
|
/* Offline hardware is a destructive state, not a primary/active state. */
|
|
body.console-v2 .v2-nfc-stage:has(.v2-nfc-waiting.offline) > header {
|
|
color: var(--status-error-foreground) !important;
|
|
background: color-mix(in oklch, var(--destructive) 16%, var(--card)) !important;
|
|
border-bottom: 1px solid color-mix(in oklch, var(--destructive) 32%, var(--border));
|
|
}
|
|
|
|
body.console-v2 .v2-nfc-stage:has(.v2-nfc-waiting.offline) > header :is(span, small, h3, p, b) {
|
|
color: var(--status-error-foreground) !important;
|
|
}
|
|
|
|
/* Keep the global appearance control out of content and below every modal. */
|
|
.glass-theme-toggle {
|
|
left: max(18px, env(safe-area-inset-left)) !important;
|
|
bottom: max(18px, env(safe-area-inset-bottom)) !important;
|
|
z-index: 1100 !important;
|
|
}
|
|
|
|
body.mode-gallery-open .glass-theme-toggle,
|
|
body.mode-editor-open .glass-theme-toggle,
|
|
body:has(.v2-extension-dialog[open]) .glass-theme-toggle,
|
|
body:has(.energy-monitor-layer:not([hidden])) .glass-theme-toggle {
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* The sidebar reserves the floating control's footprint instead of allowing
|
|
* it to cover the log timeline. */
|
|
body.console-v2 .v2-sync-log {
|
|
margin-bottom: 58px;
|
|
}
|
|
|
|
/* Top mode rail communicates that more content is available. */
|
|
body.console-v2 .v2-mode-rail .mode-rail-content {
|
|
position: relative;
|
|
min-width: 0;
|
|
}
|
|
|
|
body.console-v2 .v2-mode-rail .mode-rail-content::after {
|
|
width: 28px;
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0 0 0 auto;
|
|
pointer-events: none;
|
|
background: linear-gradient(90deg, transparent, color-mix(in oklch, var(--glass-panel) 94%, transparent));
|
|
}
|
|
|
|
@media (max-width: 1360px) {
|
|
.glass-theme-toggle {
|
|
width: 42px !important;
|
|
height: 42px !important;
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
body.console-v2 * {
|
|
scroll-behavior: auto !important;
|
|
}
|
|
}
|