/* Shared spatial UI contract -------------------------------------------- Keep geometry consistent across legacy modules without changing their domain-specific colors, content density, or interaction behavior. Hierarchy: control 10px -> card 13px -> section 15px -> panel 16px -> modal 20px. All modules consume the same semantic color tokens. */ :root { --ui-control-height-compact: 30px; --ui-control-height: 38px; --ui-control-size-icon: 36px; --ui-font-card-title: 13px; --ui-font-section-title: 15px; --ui-font-panel-title: 16px; --ui-inline-action-width: 88px; --ui-radius-control-inner: calc(var(--radius) - 2px); --ui-radius-control: var(--radius); --ui-radius-item: calc(var(--radius) + 2px); --ui-radius-section: calc(var(--radius) + 6px); --ui-radius-panel: calc(var(--radius) + 8px); --ui-radius-modal: calc(var(--radius) + 12px); --ui-space-card: 10px; --ui-border-subtle: 1px solid var(--border); --ui-shadow-item: 0 5px 14px color-mix(in oklch, var(--foreground) 6%, transparent); --ui-shadow-panel: 0 14px 32px color-mix(in oklch, var(--foreground) 8%, transparent), inset 0 1px 0 color-mix(in oklch, var(--card) 78%, transparent); --ui-shadow-modal: 0 28px 72px color-mix(in oklch, var(--foreground) 22%, transparent), 0 4px 18px color-mix(in oklch, var(--primary) 8%, transparent), inset 0 1px 0 color-mix(in oklch, var(--card) 84%, transparent); --ui-focus-ring: 0 0 0 3px color-mix(in oklch, var(--ring) 22%, transparent); } /* One readable type scale prevents large legacy headings and tiny newer card titles from competing inside the same workspace. */ .console-v2 :is( .v2-operation-heading h2, .joint-twin-shell .twin-heading h3, .v2-device-sync-board > header h3, .v2-extension-sync-heading h3, .v2-sync-sidebar-heading h2, .workspace-panel-title h3, .config-panel-heading h3 ) { font-size: var(--ui-font-panel-title) !important; line-height: 1.25; letter-spacing: -0.02em; } .console-v2 :is( .v2-pet-card-region > header h4, .v2-gscu-actions > header strong, .v2-gscu-command-catalog > header strong ) { font-size: var(--ui-font-section-title) !important; line-height: 1.3; } .console-v2 :is( .v2-device-card-focus strong, .v2-nfc-inline strong, .v2-extension-gateway strong, .v2-extension-synced-device header strong, .v2-pet-presence-card > header strong, .v2-pet-card > header > strong ) { font-size: var(--ui-font-card-title) !important; line-height: 1.35; } /* Top-level workspace surfaces share one frame. */ .console-v2.v2-passive-display.v2-interactive-sync :is( .v2-operation-shell, .joint-twin-shell > .twin-band, #v2DevicePanel, #v2ExtensionPanel .v2-extension-sync-mount ) { border: var(--ui-border-subtle); border-radius: var(--ui-radius-panel); box-shadow: var(--ui-shadow-panel); } /* The operation shell owns the frame; its active view must not draw a second border directly inside the same spatial boundary. */ .console-v2.v2-passive-display.v2-interactive-sync .v2-operation-shell > .v2-natural-panel { border: 0; border-radius: inherit; box-shadow: none; } /* Modal surfaces and their backdrops use one elevation level. */ :is( .mode-gallery-backdrop .mode-gallery, .mode-editor-backdrop .mode-editor, .energy-monitor-layer .energy-monitor-page ) { border: 1px solid color-mix(in oklch, var(--primary) 18%, var(--border)); border-radius: var(--ui-radius-modal); box-shadow: var(--ui-shadow-modal); } .mode-gallery-backdrop, .mode-editor-backdrop, .energy-monitor-layer { background: color-mix(in oklch, var(--foreground) 42%, transparent); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); } /* Section containers sit between panels and individual cards. */ .v2-sync-log, .mode-gallery-group, .energy-trend-card, .energy-devices-card { border-radius: var(--ui-radius-section); } /* Repeated content cards share radius and elevation while retaining their own semantic state colors and specialized internal layouts. */ .v2-synced-device, .v2-extension-gateway, .v2-nfc-inline, .mode-gallery-card, .mode-editor-flow, .mode-editor-command-card, .energy-kpi { border-radius: var(--ui-radius-item); box-shadow: var(--ui-shadow-item); } .energy-kpi-primary { box-shadow: 0 8px 20px color-mix(in oklch, var(--primary) 10%, transparent); } .v2-extension-gateway, .v2-nfc-inline { padding: var(--ui-space-card); } /* Sidebar cards and their nested segmented controls preserve a clear parent/child radius relationship. */ .console-v2 :is( .v2-sync-transport-field, .v2-sync-execution-field, .v2-can-command-panel ) { border-radius: var(--ui-radius-item); } /* The compact-sidebar rules in console-v2.css intentionally use highly specific selectors. Keep all peer cards on the shared item radius even when that layout is active. */ .console-v2.v2-passive-display.v2-interactive-sync :is( .v2-sync-transport-field, .v2-sync-execution-field, .v2-can-command-panel ) { border-radius: var(--ui-radius-item) !important; } .console-v2.v2-passive-display.v2-interactive-sync .v2-sync-log { border-radius: var(--ui-radius-section) !important; } .console-v2 :is(.segmented, .twin-selector) { gap: 4px; padding: 3px; background: var(--muted); border: var(--ui-border-subtle); border-radius: var(--ui-radius-control); } .console-v2 .segmented > :is(.segment, .mode-option), .console-v2 .twin-selector > .twin-seat-button { border-radius: var(--ui-radius-control-inner); } .console-v2 .segmented > .mode-option { min-height: var(--ui-control-height); height: var(--ui-control-height); gap: 5px; } .console-v2 .twin-selector > .twin-seat-button { height: 32px; } /* Primary header controls use one medium size. */ .console-v2 #v2PanelControlDock > .v2-panel-control-button, .console-v2.v2-passive-display.v2-interactive-sync .v2-mode-rail .mode-rail-actions > :is( #modeGalleryToggle, #saveModeToggle, #modeRailToggle ) { min-height: var(--ui-control-height); height: var(--ui-control-height); border-radius: var(--ui-radius-control); } .console-v2.v2-passive-display.v2-interactive-sync #v2PanelControlDock > .v2-panel-control-button, .console-v2.v2-passive-display.v2-interactive-sync #v2PanelControlDock > #v2SidebarToggle.v2-panel-control-button { border-radius: var(--ui-radius-control) !important; } .console-v2.v2-passive-display.v2-interactive-sync .v2-mode-rail #modeRailToggle { width: var(--ui-control-height); min-width: var(--ui-control-height); } /* Repeated inline actions use one compact size. */ .console-v2 :is( .v2-device-adjust-toggle, .v2-pet-settings-launch, .v2-extension-nfc-launch, .v2-extension-gateway > button, .v2-nfc-inline button ), .energy-trend-tabs button { min-height: var(--ui-control-height-compact); height: var(--ui-control-height-compact); border-radius: var(--ui-radius-control-inner); } /* Related extension actions use equal columns and a shared trailing action width, so every card keeps the same horizontal rhythm. */ .console-v2 .v2-extension-sync-actions { width: calc(var(--ui-inline-action-width) * 2 + 6px); display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; } .console-v2 .v2-extension-sync-actions > :is( .v2-pet-settings-launch, .v2-extension-nfc-launch ) { width: 100%; min-width: 0; height: var(--ui-control-height-compact); justify-content: center; padding-inline: 7px; font-size: 10px; } .console-v2 :is( .v2-nfc-inline > button, .v2-extension-gateway > button ) { width: var(--ui-inline-action-width); min-width: var(--ui-inline-action-width); justify-content: center; } /* Header icon actions are distinct from circular record/send actions. */ .assistant-drawer-actions .context-reset, .assistant-drawer-close, .mode-gallery-close, .mode-editor-header > button, #energyMonitorClose { width: var(--ui-control-size-icon); min-width: var(--ui-control-size-icon); height: var(--ui-control-size-icon); min-height: var(--ui-control-size-icon); border-radius: var(--ui-radius-control); } /* Text fields align with medium controls and use the same focus treatment. */ .mode-editor-field input, .mode-editor-field textarea { border-radius: var(--ui-radius-control); } /* Reserve the right side for the microphone/send actions. Anchoring the hint from the content edge prevents the legacy right offsets from pushing it outside narrow assistant composers. */ .console-v2.assistant-chat-enabled.v2-passive-display.v2-interactive-sync .v2-request-form .composer-hint { left: 16px !important; right: auto !important; bottom: 8px; max-width: calc(100% - 132px); } /* Delivery states use the same semantic feedback language in the sidebar and in the compact assistant command card. */ .console-v2.v2-passive-display.v2-interactive-sync .v2-can-command-list li[data-can-channel] .v2-can-command-delivery[data-delivery-state="failed"] { color: var(--destructive); background: color-mix(in oklch, var(--destructive) 10%, var(--card)); border-color: color-mix(in oklch, var(--destructive) 28%, var(--border)); } .console-v2.v2-passive-display.v2-interactive-sync .v2-can-command-list li[data-can-channel] .v2-can-command-delivery[data-delivery-state="blocked"] { color: var(--status-warning-foreground); background: var(--status-warning-soft); border-color: color-mix(in oklch, var(--status-warning) 38%, var(--border)); } .console-v2.v2-passive-display.v2-interactive-sync .v2-can-command-list li[data-can-channel] .v2-can-command-delivery[data-delivery-state="aborted"] { color: var(--muted-foreground); background: var(--muted); border-color: var(--border); } .console-v2.v2-passive-display.v2-interactive-sync .v2-can-command-list li[data-can-channel] .v2-can-command-delivery-detail { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 6px; margin: 1px 0 2px; padding: 5px 7px; color: var(--muted-foreground); background: color-mix(in oklch, var(--muted) 62%, transparent); border-left: 2px solid var(--border); border-radius: var(--ui-radius-control-inner); font-size: 9px; line-height: 1.45; white-space: normal; } .console-v2.v2-passive-display.v2-interactive-sync .v2-can-command-list li[data-delivery-state="failed"] .v2-can-command-delivery-detail { color: var(--status-error-foreground); border-left-color: var(--destructive); } .console-v2.v2-passive-display.v2-interactive-sync .v2-can-command-list li[data-delivery-state="blocked"] .v2-can-command-delivery-detail { color: var(--status-warning-foreground); border-left-color: var(--status-warning); } .assistant-dispatched-controls-list > li[data-delivery-state="failed"] { background: color-mix(in oklch, var(--destructive) 4%, var(--card)); } .assistant-dispatched-controls-list > li[data-delivery-state="failed"] .assistant-dispatched-control-icon { color: var(--destructive); } .assistant-dispatched-controls-list > li[data-delivery-state="blocked"] { background: var(--status-warning-soft); } .assistant-dispatched-controls-list > li[data-delivery-state="blocked"] .assistant-dispatched-control-icon { color: var(--status-warning-foreground); } .assistant-dispatched-controls-list > li[data-delivery-state="aborted"] { background: color-mix(in oklch, var(--muted) 68%, transparent); } .assistant-dispatched-controls-list > li[data-delivery-state="aborted"] .assistant-dispatched-control-icon { color: var(--muted-foreground); } .console-v2 :is( #v2PanelControlDock > .v2-panel-control-button, .v2-mode-rail .mode-rail-actions > button, .segmented > button, .twin-selector > button, .v2-device-adjust-toggle, .v2-pet-settings-launch, .v2-extension-nfc-launch, .v2-extension-gateway > button, .v2-nfc-inline button ):focus-visible, .mode-gallery :is(button, input, textarea):focus-visible, .mode-editor :is(button, input, textarea):focus-visible, .energy-monitor-page button:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); } @media (max-width: 900px) { :root { --ui-control-height: 40px; --ui-control-height-compact: 32px; --ui-control-size-icon: 38px; } .console-v2 .v2-extension-sync-actions { width: 100%; } } @media (prefers-reduced-motion: reduce) { .v2-synced-device, .mode-gallery-card, .energy-kpi, .console-v2 button { transition-duration: 0.01ms !important; } }