diff --git a/design-qa.md b/design-qa.md index 6422133d..85ce88d6 100644 --- a/design-qa.md +++ b/design-qa.md @@ -1,82 +1,109 @@ -# Vehicle Data Platform Semi UI System QA +# Semi UI shell vNext — Design QA -## Evidence +- Source visual truth: `/Users/lingniu/.codex/attachments/e33960ff-ed87-40f8-9da6-8e6615a653c5/image-1.png` +- Desktop implementation: `/tmp/lingniu-ui-audit-20260720/14-after-desktop-pass2.png` +- Mobile implementation: `/tmp/lingniu-ui-audit-20260720/05-after-mobile-pass2.png` +- Mobile secondary navigation: `/tmp/lingniu-ui-audit-20260720/06-mobile-more.png` +- Mobile cross-page state: `/tmp/lingniu-ui-audit-20260720/07-mobile-statistics.png` +- 2K implementation: `/tmp/lingniu-ui-audit-20260720/15-after-2k.png` +- Full-view comparison: `/tmp/lingniu-ui-audit-20260720/16-reference-comparison-final.png` +- Focused navigation comparison: `/tmp/lingniu-ui-audit-20260720/17-sidebar-comparison.png` +- Viewports: 1440 × 900, 2560 × 1440, 390 × 844 +- State: authenticated mock administrator; Monitor list mode with four vehicles -- Accepted source truth: the production application immediately before shared identity convergence. -- Desktop source contact sheet: `.codex-audit/semi-system-20260720/desktop-all-routes-before-normalized.png`. -- Desktop implementation contact sheet: `.codex-audit/semi-system-20260720/desktop-all-routes-after-contact.png`. -- Desktop same-state comparison: `.codex-audit/semi-system-20260720/desktop-before-after-comparison.png`. -- Mobile source contact sheet: `.codex-audit/semi-system-20260720/mobile-all-routes-before-normalized.png`. -- Mobile implementation contact sheet: `.codex-audit/semi-system-20260720/mobile-all-routes-after-contact.png`. -- Mobile same-state comparison: `.codex-audit/semi-system-20260720/mobile-before-after-comparison.png`. -- Desktop viewport and state: 1280 × 720, authenticated administrator, default route state. -- Mobile viewport and state: 390 × 844, authenticated administrator, default route state. -- Audited routes: `/monitor`, `/vehicles`, `/tracks`, `/history`, `/statistics`, `/alerts`, `/access`, `/users`, `/operations`. -- Production release: `semi-system-audit-20260720025208`. +## Comparison scope -## Full-view comparison +The supplied Semi image is a different product and data state, so it is not a +pixel-for-pixel content specification. The comparison treats its application +shell, navigation rhythm, whitespace, typography, surface treatment and +interaction hierarchy as the visual truth. The vehicle table keeps the width +required by the operational task instead of copying the reference's team rail. -All nine primary routes retain the accepted product grammar: persistent desktop navigation, mobile bottom navigation, cool-gray canvas, white operational surfaces, compact filters, restrained semantic color and data-first content density. Maps remain dominant on monitoring and replay; tables or queues remain dominant on the remaining workspaces. +## Findings and iteration history -The implementation changes the source of the identity styling rather than the visible hierarchy. Primary, warning, authority and health identity tones are now owned by `WorkspaceCommandBar` and shared CSS custom properties. Page-specific rules retain only genuine layout differences such as the compact replay rail, the larger vehicle record identity, the hidden mobile alert copy and the short-landscape operations header. +### Pass 1 -Live vehicle, mileage, alert and access values changed between the before and after captures because both sets use production data. Component placement, spacing, responsive behavior and visual hierarchy remain continuous. +- **[P1] Layered navigation chrome made the shell feel heavy.** + - Evidence: the baseline used a soft square behind every icon, gradient + selection fills and several shadow layers; the reference uses quiet icons, + one selected row and neutral white space. + - Fix: removed icon plates and gradients, simplified hover/selected states, + aligned group labels and introduced one restrained active indicator. + - Post-fix evidence: focused navigation comparison. +- **[P1] Mobile hierarchy was too compressed.** + - Evidence: `/tmp/lingniu-ui-audit-20260720/02-before-mobile.png` used an + unbranded title bar, 9px navigation labels and truncated vehicle facts. + - Fix: added the supplied brand mark, rebuilt the bottom navigation rhythm, + increased the essential text scale and redistributed the four vehicle + metrics evenly without reducing the visible vehicle count. + - Post-fix evidence: mobile implementation and mobile cross-page state. +- **[P2] Page transitions rebuilt the content container.** + - Evidence: the shell keyed the entire content container by pathname. + - Fix: kept the content container stable and animated only the newly mounted + route surface; reduced-motion users receive no transition. + - Post-fix evidence: Monitor → Mileage route change retained the shell and + updated the title, active navigation and page content. -## Focused comparison +### Pass 2 -Desktop and mobile comparisons were viewed as combined before/after images at matching route viewports. The warning tone remains amber in Alert Center, the authority tone remains purple in Account Management, the health tone remains green in Operations Quality, and the remaining identity workspaces retain the primary blue treatment. +- **[P2] Collapsed sidebar hid its reopen affordance.** + - Evidence: `/tmp/lingniu-ui-audit-20260720/08-desktop-collapsed.png` showed + an empty collapse footer because a legacy selector hid every nested span, + including Semi's icon wrapper. + - Fix: restored only the icon wrapper, rotated the chevron and preserved the + text-hidden compact state. + - Post-fix evidence: + `/tmp/lingniu-ui-audit-20260720/11-desktop-collapsed-final.png`; browser + state changed from `收起侧栏` to `展开侧栏` and back. +- **[P2] Desktop data type remained optically smaller than the reference.** + - Evidence: first full-view comparison showed the header, filter controls, + table headings and primary row values losing hierarchy at 1440px. + - Fix: increased the desktop shell header to 76px, raised navigation and + table type sizes, and increased control and row heights while retaining + the operational density. + - Post-fix evidence: final full-view comparison and 2K implementation. -At 390 × 844, command bars preserve the existing single-screen density. Descriptions and metadata continue to collapse only where the prior mobile behavior already required it. All nine routes report `scrollWidth === clientWidth`; no page-level horizontal overflow was introduced. +## Required fidelity surfaces -## Fidelity ledger +- **Fonts and typography:** system/PingFang stack is appropriate for Chinese; + page titles, navigation, controls and primary values now form a clear scale. + Tabular figures are enabled for telemetry. No actionable P0–P2 issue remains. +- **Spacing and layout rhythm:** the shell uses a 220px desktop rail, 76px + desktop header, 56px mobile header and 64px safe-area-aware mobile + navigation. Cards use quieter 9–10px radii and one-pixel boundaries. +- **Colors and tokens:** white surfaces, `#f5f6f7` canvas, `#e6e8eb` borders + and Semi blue `#0064fa` now match the reference's foreground/background + balance. Operational green/red tones remain semantic. +- **Image quality and assets:** supplied brand SVG assets are used directly. + No placeholder illustration, custom SVG or CSS-drawn brand asset was added. +- **Icons:** all shell actions use the existing Semi icon family. Selected, + hover, pressed and collapsed states remain optically aligned. +- **Copy and content:** each page title now has a short task description on + desktop. Mobile keeps only the title to protect first-screen task density. +- **Responsiveness:** 390px mobile, 1440px desktop and 2560px 2K states were + rendered without overlap, hidden persistent controls or shell overflow. +- **Accessibility:** semantic navigation names and page headings remain intact; + mobile targets are at least 42px in the shell, focus styles are preserved, + and `prefers-reduced-motion` disables the new transitions. Screenshot review + cannot prove full assistive-technology compatibility. -| Surface | Source evidence | Render evidence | Result | -| --- | --- | --- | --- | -| Navigation and workspace frame | Consistent desktop rail and mobile bottom navigation | All nine routes retain the same navigation, canvas and viewport ownership | Passed | -| Identity hierarchy | Icon, eyebrow, task title, supporting context and actions | Shared `WorkspaceCommandBar` anatomy is unchanged across desktop and mobile | Passed | -| Semantic colors | Blue operational work, amber warnings, purple authority, green health | Four explicit tones resolve to the accepted icon, glow and status-tag colors | Passed | -| Typography | Compact operational hierarchy with restrained supporting copy | Existing Semi title, text and tag scale is preserved at both viewports | Passed | -| Spacing and density | Maps, tables and queues dominate their workspaces | Header convergence does not reduce visible rows, cards or map area | Passed | -| Responsive behavior | Mobile descriptions and actions collapse selectively | Existing per-workspace breakpoints remain; all routes have zero page overflow | Passed | -| Component architecture | Repeated identity styling existed in page-specific CSS | Semantic variables now centralize palette and shared anatomy without page coupling | Passed | -| Runtime behavior | Production routes must load without unstable placeholders | No skeletons, spin overlays, loading copy or browser errors remained at capture | Passed | +## Interaction and console checks -## Above-the-fold copy diff +- Mobile More opens a Semi SideSheet with grouped analysis and governance + destinations, then closes without changing page state. +- Mobile Mileage navigation changes URL, heading and active tab and renders the + fixed-column mileage matrix. +- Desktop sidebar collapses and expands with a visible affordance in both + states. +- No framework error overlay or application runtime error was observed. + Semi UI's known React `findDOMNode` development deprecation warning remains. -- No user-facing product copy changed. -- No route, field, status label, action or business claim changed. -- The only DOM contract change is the semantic identity class: `is-primary`, `is-warning`, `is-authority` or `is-health`. +## Follow-up polish -## Comparison history - -1. P2 — Identity colors, icon surfaces and status tags were repeated in vehicle, replay, history, alert, access, account and operations CSS blocks. - - Fix: introduced a typed `tone` property on `WorkspaceCommandBar` and centralized semantic CSS custom properties. - - Post-fix evidence: both combined contact sheets preserve the accepted appearance while production computed-style checks confirm all four tones. -2. P2 — The repeated page rules allowed title, description, icon and mobile breakpoint values to drift independently. - - Fix: moved shared color and component anatomy to the base identity rules; retained only layout-specific page overrides. - - Post-fix evidence: desktop and mobile route contact sheets show continuous hierarchy and density. -3. P2 — A shared refactor could have caused mobile overflow or reduced one-screen data density. - - Fix: audited every primary route at 390 × 844 and recorded document dimensions after stable render. - - Post-fix evidence: all nine routes have `scrollWidth = 390`, `clientWidth = 390`, no loading overlays and no layout clipping. - -## Findings - -- No actionable P0, P1 or P2 visual differences remain in this batch. -- Production browser warnings and errors after route traversal: 0. -- Build output retains the upstream Semi Sass `@import` deprecation warning; it does not affect this release. - -## Core interaction and release verification - -- Nine desktop routes rendered at 1280 × 720 without horizontal overflow. -- Nine mobile routes rendered at 390 × 844 without horizontal overflow. -- Primary, warning, authority and health classes and computed colors were verified in production. -- Full web suite: 73 files, 369 tests passed. -- Production build gate: passed. -- Web release smoke suite: passed. -- ECS HTTP check: 200 OK. -- ECS active release: `/opt/lingniu-vehicle-platform/releases/semi-system-audit-20260720025208`. -- Served assets: `app-fqr7mrEB.js`, `app-BHAi6qMP.css`. - -## Final result +- P3: continue raising secondary explanatory text on legacy page-specific + surfaces as each page enters the Semi migration. +- P3: consolidate older workspace CSS overrides after the visual migration is + complete; removing them now would expand regression scope without changing + this shell's rendered result. final result: passed diff --git a/vehicle-data-platform/apps/web/src/v2/layout/AppShell.test.tsx b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.test.tsx index df1d232a..639f27df 100644 --- a/vehicle-data-platform/apps/web/src/v2/layout/AppShell.test.tsx +++ b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.test.tsx @@ -74,9 +74,11 @@ test('reschedules likely route preloads when the active module changes', async ( ); expect(routing.scheduleIdleRoutePreloads).toHaveBeenCalledWith({ activePathname: '/monitor' }); + expect(screen.getByText('查看全车队实时位置、状态和最新上报。')).toBeInTheDocument(); fireEvent.click(screen.getByRole('link', { name: '历史数据' })); await waitFor(() => expect(routing.scheduleIdleRoutePreloads).toHaveBeenLastCalledWith({ activePathname: '/history' })); + expect(screen.getByText('查询车辆原始历史数据并导出证据。')).toBeInTheDocument(); expect(firstCleanup).toHaveBeenCalledTimes(1); cleanup(); @@ -194,6 +196,7 @@ test('uses the compact mobile navigation and opens secondary modules in a Semi S ); expect(screen.getByRole('heading', { name: '全局监控' })).toHaveClass('v2-topbar-page-title'); + expect(document.querySelector('.v2-mobile-topbar-mark')).toHaveAttribute('src', '/brand-mark.svg'); expect(screen.getByRole('navigation', { name: '主导航' })).toHaveStyle({ '--v2-mobile-nav-count': '5' }); expect(screen.getByRole('link', { name: '全局监控' })).toBeInTheDocument(); expect(screen.getByRole('link', { name: '车辆查询' })).toBeInTheDocument(); diff --git a/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx index 2f275306..9f4fa231 100644 --- a/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx +++ b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx @@ -141,6 +141,7 @@ export function AppShell() { const [passwordOpen, setPasswordOpen] = useState(false); const mobileLayout = useMobileLayout(); const roleLabel = { viewer: '只读', operator: '处置员', admin: '管理员', customer: '客户' }[session.role]; + const pageSummary = pageHelp[section]?.summary ?? '统一查看车辆数据、运行状态与业务证据。'; useEffect(() => scheduleIdleRoutePreloads({ activePathname: activeRoutePath }), [activeRoutePath]); useLayoutEffect(() => { const reset = () => { @@ -165,7 +166,13 @@ export function AppShell() { {mobileLayout ? : }
-
羚牛车辆数据中台{pageNames[section] ?? '车辆数据中台'}
+
+ + + {pageNames[section] ?? '车辆数据中台'} + {pageSummary} + +
- +
setHelpOpen(false)} /> {passwordOpen ? setPasswordOpen(false)} onChanged={logout} /> : null} diff --git a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css index 7c8ce9f6..5e2ef5bc 100644 --- a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css +++ b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css @@ -28596,3 +28596,716 @@ min-width: 70px; } } + +/* + * Semi UI shell vNext. + * + * The reference experience relies on calm white surfaces, a readable + * navigation rhythm and one clear content hierarchy. Keep these rules last: + * they intentionally replace the accumulated dense shell overrides without + * changing any page's data or task model. + */ +:root { + --v2-bg: #f5f6f7; + --v2-border: #e6e8eb; + --v2-blue: #0064fa; + --v2-blue-soft: #e8f3ff; + --v2-sidebar-width: 220px; + --v2-shell-header-height: 72px; + --v2-shell-motion: 180ms cubic-bezier(.2, .8, .2, 1); + --v2-surface-border: #e6e8eb; + --v2-surface-shadow: 0 1px 2px rgba(17, 24, 39, .035); +} + +body { + background: var(--v2-bg); + color: #1c1f23; + font-feature-settings: "tnum" 1, "cv02" 1, "cv03" 1; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + --semi-color-primary: var(--v2-blue); + --semi-color-primary-hover: #0057db; + --semi-color-primary-active: #004ec4; + --semi-color-primary-light-default: var(--v2-blue-soft); + --semi-color-border: var(--v2-border); + --semi-color-bg-0: var(--v2-bg); +} + +.v2-shell, +.v2-main, +.v2-content { + background: var(--v2-bg); +} + +.v2-sidebar { + width: var(--v2-sidebar-width); + border-right-color: var(--v2-border); + background: #fff; + box-shadow: none; +} + +.v2-brand { + height: var(--v2-shell-header-height); + flex: 0 0 var(--v2-shell-header-height); + border-bottom-color: var(--v2-border); + padding-inline: 20px; +} + +.v2-brand-logo { + width: 154px; +} + +.v2-navigation.semi-navigation { + padding: 14px 12px 12px; +} + +.v2-navigation.semi-navigation .semi-navigation-item { + min-height: 42px; + margin: 1px 0; + border-radius: 8px; + color: #545b66; + transition: + background-color var(--v2-shell-motion), + color var(--v2-shell-motion), + transform var(--v2-shell-motion); +} + +.v2-navigation.semi-navigation .semi-navigation-item-link, +.v2-navigation.semi-navigation .semi-navigation-item-inner { + min-height: 42px; +} + +.v2-navigation.semi-navigation .semi-navigation-item-inner { + gap: 10px; + padding-inline: 12px; +} + +.v2-navigation.semi-navigation .semi-navigation-item-text { + color: inherit; + font-size: 13px; + font-weight: 590; + letter-spacing: 0; +} + +.v2-navigation.semi-navigation .semi-navigation-item-icon, +.v2-navigation.semi-navigation .semi-navigation-item:hover .semi-navigation-item-icon, +.v2-navigation.semi-navigation .semi-navigation-item-selected .semi-navigation-item-icon { + display: grid; + width: 24px; + height: 24px; + flex: 0 0 24px; + place-items: center; + border-radius: 0; + background: transparent; + box-shadow: none; + color: #7b818b; + font-size: 17px; + transition: color var(--v2-shell-motion), transform var(--v2-shell-motion); +} + +.v2-navigation.semi-navigation .semi-navigation-item:hover { + background: #f5f6f7; + color: #1f2329; + transform: translateX(1px); +} + +.v2-navigation.semi-navigation .semi-navigation-item:hover .semi-navigation-item-icon { + color: #4e5969; +} + +.v2-navigation.semi-navigation .semi-navigation-item-selected { + background: var(--v2-blue-soft); + color: var(--v2-blue); + box-shadow: none; +} + +.v2-navigation.semi-navigation .semi-navigation-item-selected::after { + position: absolute; + top: 9px; + bottom: 9px; + left: 0; + width: 3px; + border-radius: 0 3px 3px 0; + background: var(--v2-blue); + content: ""; +} + +.v2-navigation.semi-navigation .semi-navigation-item-selected .semi-navigation-item-icon { + color: var(--v2-blue); + transform: scale(1.04); +} + +.v2-navigation.semi-navigation .semi-navigation-item.v2-nav-group-start { + margin-top: 31px; +} + +.v2-navigation.semi-navigation .semi-navigation-item.v2-nav-group-start::before { + top: -23px; + right: 12px; + left: 12px; + color: #8f959e; + font-size: 10px; + font-weight: 600; + letter-spacing: .04em; +} + +.v2-collapse.semi-button { + height: 52px; + flex: 0 0 52px; + border-top-color: var(--v2-border); + padding-inline: 22px; + color: #6f7680; + font-size: 12px; + font-weight: 560; +} + +.v2-collapse.semi-button:hover { + background: #f5f6f7; + color: var(--v2-blue); +} + +.v2-sidebar.is-collapsed .v2-collapse.semi-button { + justify-content: center; + padding: 0; + transform: none; +} + +.v2-sidebar.is-collapsed .v2-collapse.semi-button .semi-button-content { + display: flex; + align-items: center; + justify-content: center; +} + +.v2-sidebar.is-collapsed .v2-collapse.semi-button .semi-icon { + display: inline-flex; + color: #6f7680; + font-size: 16px; + transform: rotate(180deg); +} + +.v2-main { + margin-left: var(--v2-sidebar-width); +} + +.v2-topbar { + height: var(--v2-shell-header-height); + flex-basis: var(--v2-shell-header-height); + border-bottom-color: var(--v2-border); + background: rgba(255, 255, 255, .97); + padding: 0 24px; + box-shadow: none; + backdrop-filter: blur(14px); +} + +.v2-topbar-title { + display: flex; + min-width: 0; + align-items: center; + flex-direction: row; + gap: 0; +} + +.v2-mobile-topbar-mark { + display: none; +} + +.v2-topbar-heading { + display: grid; + min-width: 0; + gap: 3px; +} + +.v2-topbar-title > .v2-topbar-heading > .v2-topbar-page-title.semi-typography { + overflow: hidden; + margin: 0; + color: #1f2329; + font-size: 21px; + font-weight: 680; + letter-spacing: -.025em; + line-height: 1.2; + text-overflow: ellipsis; + white-space: nowrap; +} + +.v2-topbar-title > .v2-topbar-heading > .v2-topbar-description.semi-typography { + overflow: hidden; + margin: 0; + color: #8f959e; + font-size: 11px; + font-weight: 450; + letter-spacing: 0; + line-height: 1.3; + text-overflow: ellipsis; + white-space: nowrap; +} + +.v2-topbar-actions { + gap: 6px; +} + +.v2-topbar-actions > .v2-help-trigger.semi-button { + min-width: 96px; + height: 40px; + border-color: transparent; + border-radius: 8px; + background: #f5f6f7; + color: #5f6670; + font-size: 12px; + font-weight: 560; +} + +.v2-topbar-actions > .v2-help-trigger.semi-button:hover, +.v2-topbar-actions > .v2-help-trigger.semi-button[aria-expanded="true"] { + border-color: transparent; + background: var(--v2-blue-soft); + color: var(--v2-blue); +} + +.v2-topbar-actions > .v2-current-user.semi-button { + height: 40px; + border-radius: 8px; + color: #4e5969; +} + +.v2-current-user b { + font-size: 12px; +} + +.v2-content { + scrollbar-gutter: stable; +} + +.v2-content > * { + animation: v2-shell-content-enter var(--v2-shell-motion) both; +} + +.v2-content .semi-card { + border-color: var(--v2-surface-border); + box-shadow: var(--v2-surface-shadow); +} + +.v2-content .semi-table-thead > .semi-table-row > .semi-table-row-head { + border-bottom-color: var(--v2-border); + background: #fafafa; + color: #6f7680; +} + +.v2-content .semi-table-tbody > .semi-table-row:hover { + background: #f5f8ff; +} + +.v2-monitor-filterbar.semi-card, +.v2-monitor-summary-rail.semi-card, +.v2-monitor-table-panel.semi-card { + border-radius: 10px; + box-shadow: var(--v2-surface-shadow); +} + +.v2-monitor-table-panel > .semi-card-body > .v2-monitor-list-header { + min-height: 62px; + padding: 10px 16px; +} + +.v2-monitor-table-panel > .semi-card-body > .v2-monitor-list-header .v2-workspace-panel-copy > h5 { + color: #1f2329; + font-size: 16px; + font-weight: 650; +} + +.v2-monitor-table .semi-table-thead > .semi-table-row > .semi-table-row-head { + height: 44px; + color: #6f7680; + font-size: 12px; + font-weight: 560; +} + +.v2-monitor-table .semi-table-tbody > .semi-table-row > .semi-table-row-cell { + height: 62px; + color: #2e3338; + font-size: 13px; +} + +.v2-monitor-table-vehicle strong { + color: #1f2329; + font-size: 14px; + font-weight: 650; +} + +.v2-monitor-table-vehicle span { + color: #8f959e; + font-size: 10px; +} + +@keyframes v2-shell-content-enter { + from { + opacity: .72; + transform: translateY(3px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@media (max-width: 900px) { + .v2-main, + .v2-sidebar.is-collapsed + .v2-main { + margin-left: 0; + } +} + +@media (min-width: 681px) { + :root { + --v2-shell-header-height: 76px; + } + + .v2-navigation.semi-navigation .semi-navigation-item, + .v2-navigation.semi-navigation .semi-navigation-item-link, + .v2-navigation.semi-navigation .semi-navigation-item-inner { + min-height: 44px; + } + + .v2-navigation.semi-navigation .semi-navigation-item-text { + font-size: 14px; + } + + .v2-navigation.semi-navigation .semi-navigation-item-icon, + .v2-navigation.semi-navigation .semi-navigation-item:hover .semi-navigation-item-icon, + .v2-navigation.semi-navigation .semi-navigation-item-selected .semi-navigation-item-icon { + font-size: 18px; + } + + .v2-topbar-title > .v2-topbar-heading > .v2-topbar-page-title.semi-typography { + font-size: 23px; + } + + .v2-topbar-title > .v2-topbar-heading > .v2-topbar-description.semi-typography { + font-size: 12px; + } + + .v2-monitor-page { + gap: 12px; + padding: 12px 14px 14px; + } + + .v2-monitor-page > .v2-filterbar > .semi-card-body { + gap: 12px; + padding: 11px 13px; + } + + .v2-monitor-page .v2-monitor-filter-fields > .v2-search-field, + .v2-monitor-page .v2-monitor-filter-fields > .semi-select, + .v2-monitor-page .v2-monitor-filter-fields > .v2-filter-reset.semi-button, + .v2-monitor-page .v2-monitor-filter-actions > .v2-monitor-mobile-entry.semi-button { + height: 40px; + min-height: 40px; + } + + .v2-monitor-page .v2-monitor-filter-fields > .semi-select .semi-select-selection-text { + height: 38px; + font-size: 13px; + } + + .v2-monitor-page .v2-search-field .semi-input, + .v2-monitor-page .v2-monitor-filter-fields > .v2-filter-reset.semi-button, + .v2-monitor-page .v2-monitor-filter-actions > .v2-monitor-mobile-entry.semi-button { + font-size: 13px; + } + + .v2-monitor-page .v2-monitor-mode.v2-segmented-tabs { + height: 40px; + } + + .v2-monitor-page .v2-monitor-mode.v2-segmented-tabs > .semi-button { + height: 34px; + font-size: 12px; + } + + .v2-monitor-page .v2-filter-live-status { + height: 38px; + border-radius: 19px; + font-size: 11px; + } + + .v2-monitor-table-panel > .semi-card-body > .v2-monitor-list-header { + min-height: 66px; + } + + .v2-monitor-table-panel > .semi-card-body > .v2-monitor-list-header .v2-workspace-panel-copy > h5 { + font-size: 17px; + } + + .v2-monitor-table-panel > .semi-card-body > .v2-monitor-list-header .v2-workspace-panel-copy > .semi-typography:not(h5) { + font-size: 11px; + } + + .v2-monitor-table .semi-table-thead > .semi-table-row > .semi-table-row-head { + height: 46px; + font-size: 13px; + } + + .v2-monitor-table .semi-table-tbody > .semi-table-row > .semi-table-row-cell { + height: 66px; + font-size: 14px; + } + + .v2-monitor-table-vehicle strong { + font-size: 15px; + } + + .v2-monitor-table-vehicle span { + font-size: 11px; + } +} + +@media (max-width: 680px) { + :root { + --v2-shell-header-height: 56px; + } + + .v2-topbar { + height: var(--v2-shell-header-height); + flex-basis: var(--v2-shell-header-height); + padding: 0 8px 0 12px; + } + + .v2-topbar-title { + flex: 1 1 auto; + gap: 9px; + } + + .v2-mobile-topbar-mark { + display: block; + width: 27px; + height: 27px; + flex: 0 0 27px; + object-fit: contain; + } + + .v2-topbar-title > .v2-topbar-heading > .v2-topbar-page-title.semi-typography { + max-width: min(51vw, 198px); + font-size: 18px; + font-weight: 660; + } + + .v2-topbar-title > .v2-topbar-heading > .v2-topbar-description.semi-typography { + display: none; + } + + .v2-topbar-actions { + gap: 0; + } + + .v2-topbar-actions > .v2-help-trigger.semi-button, + .v2-topbar-actions > .v2-current-user.semi-button { + width: 42px; + min-width: 42px; + height: 42px; + border-radius: 10px; + background: transparent; + } + + .v2-main, + .v2-sidebar.is-collapsed + .v2-main { + padding-bottom: calc(64px + env(safe-area-inset-bottom)); + } + + .v2-content { + scrollbar-gutter: auto; + } + + .v2-mobile-navigation { + height: calc(64px + env(safe-area-inset-bottom)); + border-top-color: var(--v2-border); + background: rgba(255, 255, 255, .985); + padding: 4px 6px calc(4px + env(safe-area-inset-bottom)); + box-shadow: 0 -1px 0 rgba(17, 24, 39, .025); + } + + .v2-mobile-navigation .v2-mobile-nav-item, + .v2-mobile-navigation > .semi-button.v2-mobile-nav-item { + min-height: 56px; + gap: 2px; + border-radius: 8px; + color: #8a9099; + transition: color var(--v2-shell-motion), transform var(--v2-shell-motion); + } + + .v2-mobile-navigation .v2-mobile-nav-item:active, + .v2-mobile-navigation > .semi-button.v2-mobile-nav-item:active { + transform: scale(.96); + } + + .v2-mobile-navigation .v2-mobile-nav-item > .semi-icon, + .v2-mobile-navigation > .semi-button.v2-mobile-nav-item .semi-icon { + width: 32px; + height: 28px; + border-radius: 8px; + font-size: 19px; + } + + .v2-mobile-navigation .v2-mobile-nav-item > span, + .v2-mobile-navigation > .semi-button.v2-mobile-nav-item .semi-button-content { + color: inherit; + font-size: 10px; + font-weight: 560; + line-height: 1.2; + } + + .v2-mobile-navigation .v2-mobile-nav-item.is-active { + color: var(--v2-blue); + } + + .v2-mobile-navigation .v2-mobile-nav-item.is-active > .semi-icon, + .v2-mobile-navigation > .semi-button.v2-mobile-nav-item.is-active .semi-icon { + background: var(--v2-blue-soft); + box-shadow: none; + } + + .v2-monitor-page { + gap: 8px; + padding: 8px; + } + + .v2-monitor-filterbar.semi-card, + .v2-monitor-summary-rail.semi-card, + .v2-monitor-table-panel.semi-card { + border-radius: 10px; + } + + .v2-monitor-summary-rail .v2-workspace-metric-list > span > small { + color: #6f7680; + font-size: 9.5px; + font-weight: 560; + } + + .v2-monitor-summary-rail .v2-workspace-metric-list > span > strong, + .v2-monitor-summary-rail .v2-workspace-metric-list > span.is-secondary > strong { + font-size: 19px; + font-weight: 650; + } + + .v2-monitor-summary-rail .v2-workspace-metric-list > span > em { + color: #a0a5ad; + font-size: 8.5px; + } + + .v2-monitor-summary-support small { + color: #7a818b; + font-size: 9.5px; + } + + .v2-monitor-summary-support strong { + color: #3d4249; + font-size: 13px; + } + + .v2-monitor-table-panel > .semi-card-body > .v2-monitor-list-header { + min-height: 52px; + padding: 7px 10px; + } + + .v2-monitor-table-panel > .semi-card-body > .v2-monitor-list-header .v2-workspace-panel-copy > h5 { + font-size: 14px; + } + + .v2-monitor-table-panel > .semi-card-body > .v2-monitor-list-header .v2-workspace-panel-copy > .semi-typography:not(h5) { + color: #8f959e; + font-size: 9.5px; + } + + .v2-monitor-mobile-cards { + gap: 6px; + padding: 6px; + } + + .v2-monitor-mobile-cards > .v2-monitor-mobile-card.semi-card { + min-height: 114px; + border-color: var(--v2-border); + border-radius: 9px; + background: #fff; + box-shadow: var(--v2-surface-shadow); + contain-intrinsic-size: auto 114px; + } + + .v2-monitor-mobile-card .v2-monitor-mobile-card-header { + height: 40px; + min-height: 40px; + padding: 5px 8px 4px 10px; + } + + .v2-monitor-mobile-card .v2-monitor-mobile-identity > strong { + color: #1f2329; + font-size: 14.5px; + font-weight: 660; + } + + .v2-monitor-mobile-card .v2-monitor-mobile-identity > span { + color: #989fa8; + font-size: 9.5px; + } + + .v2-monitor-card-heading-actions > .v2-monitor-card-locate.semi-button { + width: 56px; + height: 31px; + min-height: 31px; + border-radius: 7px; + font-size: 9.5px; + font-weight: 600; + } + + .v2-monitor-mobile-cards .v2-monitor-mobile-primary { + grid-template-columns: repeat(4, minmax(0, 1fr)); + padding: 3px 8px; + } + + .v2-monitor-mobile-cards .v2-monitor-mobile-primary > div { + padding-inline: 5px; + } + + .v2-monitor-mobile-cards .v2-monitor-mobile-primary dt { + color: #8f959e; + font-size: 9.5px; + } + + .v2-monitor-mobile-cards .v2-monitor-mobile-primary dd { + color: #3d4249; + font-size: 10.5px; + font-weight: 620; + } + + .v2-monitor-mobile-cards .v2-monitor-mobile-primary dd > small { + font-size: 8.5px; + font-weight: 520; + } + + .v2-monitor-mobile-location { + height: 34px; + min-height: 34px; + background: #fafafa; + } + + .v2-monitor-mobile-coordinate > :is(code, small) { + color: #767d87; + font-size: 9.5px; + } + + .v2-monitor-mobile-location .v2-monitor-address-action.semi-button, + .v2-monitor-mobile-location .v2-monitor-address-update.semi-button { + min-width: 72px; + height: 28px; + min-height: 28px; + font-size: 9.5px; + font-weight: 600; + } +} + +@media (prefers-reduced-motion: reduce) { + .v2-content > *, + .v2-navigation.semi-navigation .semi-navigation-item, + .v2-mobile-navigation .v2-mobile-nav-item, + .v2-mobile-navigation > .semi-button.v2-mobile-nav-item { + animation: none; + transition: none; + } +}