/* SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-26-p9-desktop-view-density. */ /* Responsibility: Responsive visual foundation for the web-probe sentinel dashboard. */ :root { color-scheme: light; --bg: #f6f7f9; --panel: #ffffff; --panel-soft: #f0f5f7; --text: #18212f; --muted: #667085; --border: #d9e0e7; --border-soft: #edf0f4; --blue: #2563eb; --green: #059669; --amber: #b7791f; --red: #c2413d; --violet: #6d5bd0; --shadow-overlay: 0 12px 32px rgb(30 41 59 / 14%); } * { box-sizing: border-box; } html, body { min-height: 100%; } body { margin: 0; background: var(--bg); color: var(--text); font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; letter-spacing: 0; } button, select, input { font: inherit; } .sentinel-shell { width: min(1440px, 100%); margin: 0 auto; padding: 16px 20px; } .sentinel-topbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 10px; } .sentinel-title { display: flex; align-items: center; min-width: 0; gap: 12px; } .sentinel-mark { width: 32px; height: 32px; border-radius: 8px; background: linear-gradient(135deg, rgb(37 99 235 / 90%), rgb(5 150 105 / 88%)), #2563eb; box-shadow: inset 0 0 0 1px rgb(255 255 255 / 30%); flex: 0 0 auto; } h1, h2, p { margin: 0; } h1 { font-size: 20px; line-height: 1.18; font-weight: 700; } h2 { font-size: 14px; line-height: 1.3; font-weight: 700; } #sentinel-subtitle, .panel-subtitle { color: var(--muted); } #sentinel-subtitle { display: flex; align-items: center; flex-wrap: wrap; gap: 3px 6px; margin-top: 2px; font-size: 12px; overflow-wrap: anywhere; } .sentinel-subtitle-separator { color: #a3adba; } .sentinel-id-chip { display: inline-flex; align-items: center; max-width: min(58vw, 560px); min-height: 18px; padding: 1px 5px; border: 1px solid #d8e0ea; border-radius: 5px; background: #eef2f7; color: #344054; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; font-size: 11px; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; white-space: normal; } #sentinel-origin-note { color: #97a1b0; font-size: 11px; } .sentinel-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 6px; } .status-pill, .severity-pill { display: inline-flex; align-items: center; min-height: 24px; padding: 2px 9px; border-radius: 999px; border: 1px solid transparent; font-size: 12px; font-weight: 700; white-space: nowrap; } .status-healthy, .status-operational { background: #e8f7ef; color: var(--green); border-color: #b9e6cc; } .status-warning, .status-degraded, .severity-warning, .severity-amber { background: #fff6df; color: var(--amber); border-color: #f2d893; } .status-blocked, .status-error, .severity-red, .severity-critical, .severity-error { background: #fdecea; color: var(--red); border-color: #f4bbb7; } .status-idle, .severity-info, .severity-unknown { background: #eef2f7; color: #526071; border-color: #d8e0ea; } .refresh-toggle { display: inline-flex; align-items: center; gap: 6px; min-height: 32px; padding: 2px 6px; color: #344054; font-size: 12px; white-space: nowrap; } .refresh-toggle input { width: 16px; height: 16px; } select, .icon-button { min-height: 32px; border: 1px solid var(--border); border-radius: 6px; background: #ffffff; color: #1f2937; } select { padding: 0 24px 0 9px; } .icon-button { padding: 0 10px; font-size: 12px; font-weight: 600; cursor: pointer; } .icon-button:disabled { cursor: progress; opacity: 0.62; } .icon-button.active { border-color: var(--blue); background: #edf4ff; color: var(--blue); } .banner { margin-bottom: 10px; padding: 8px 12px; border-radius: 6px; border: 1px solid var(--border); font-size: 13px; overflow-wrap: anywhere; } .banner-muted { background: #edf4ff; color: #1d4ed8; border-color: #bfd5ff; } .banner-danger { background: #fff0ee; color: var(--red); border-color: #f2c0bc; } /* 状态摘要条:合并 4 metric cards,单行 ~48px */ .status-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 24px; margin: 0 0 10px; padding: 8px 14px; border: 1px solid var(--border); border-radius: 6px; background: var(--panel); } .summary-item { display: inline-flex; align-items: baseline; gap: 6px; min-width: 0; } .summary-label { color: var(--muted); font-size: 11px; font-weight: 600; white-space: nowrap; } .summary-item strong { font-size: 14px; font-weight: 700; line-height: 1.2; overflow-wrap: anywhere; } .summary-item small { color: var(--muted); font-size: 11px; overflow-wrap: anywhere; } .summary-checks { margin-left: auto; } .sentinel-registry-strip { display: grid; grid-template-columns: minmax(160px, 220px) 1fr; align-items: center; gap: 10px; margin-bottom: 10px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 6px; background: #ffffff; } .sentinel-registry-copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; } .sentinel-registry-copy strong { font-size: 13px; line-height: 1.25; } .sentinel-registry-copy span { color: var(--muted); font-size: 11px; } .sentinel-registry-links { display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; } .sentinel-registry-link { display: inline-flex; align-items: center; gap: 7px; max-width: 100%; min-height: 28px; padding: 4px 8px; border: 1px solid #d8e0ea; border-radius: 6px; background: #f8fafc; color: #344054; font-size: 12px; font-weight: 650; text-decoration: none; } .sentinel-registry-link.current { border-color: #a7c5f9; background: #edf5ff; color: #1d4ed8; } .sentinel-registry-link.disabled { opacity: 0.62; } .sentinel-registry-link span { overflow-wrap: anywhere; } .sentinel-registry-link small { color: var(--muted); font-size: 10px; font-weight: 700; text-transform: uppercase; } .check-summary-pill { min-height: 26px; padding: 3px 10px; border: 1px solid #d8e0ea; border-radius: 999px; background: #ffffff; color: #475467; font-size: 12px; font-weight: 700; cursor: pointer; } .check-summary-pill.check-ok { border-color: #b9e6cc; background: #eefaf4; color: var(--green); } .check-summary-pill.check-blocked { border-color: #f4bbb7; background: #fff0ee; color: var(--red); } /* overview checks 默认折叠为单 pill,展开看明细 */ .overview-checks { margin: 0 0 10px; } .overview-checks-collapsed .overview-checks-detail { display: none; } .overview-checks:not(.overview-checks-collapsed) .check-summary-pill { margin-bottom: 8px; } .overview-checks-detail { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 6px; } .check-chip { display: flex; align-items: center; min-height: 28px; max-width: 100%; padding: 4px 9px; border: 1px solid #d8e0ea; border-radius: 6px; background: #ffffff; color: #475467; font-size: 12px; font-weight: 600; overflow-wrap: anywhere; } .check-ok { border-color: #b9e6cc; background: #eefaf4; color: var(--green); } .check-blocked { border-color: #f4bbb7; background: #fff0ee; color: var(--red); } /* 三栏 master-detail 布局:Runs | Detail | Findings */ .dashboard-grid { display: grid; grid-template-columns: minmax(280px, 0.85fr) minmax(0, 1.4fr) minmax(280px, 0.85fr); align-items: stretch; gap: 10px; margin-bottom: 10px; } .panel { background: var(--panel); border: 1px solid var(--border); border-radius: 6px; min-width: 0; overflow: hidden; display: flex; flex-direction: column; } .panel-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 40px; padding: 9px 12px; border-bottom: 1px solid var(--border); } .panel-subtitle { font-size: 12px; } .panel-runs .table-frame, .panel-findings .finding-list, .panel-detail .detail-content { flex: 1 1 auto; } /* filter 默认折叠为单行摘要 chip */ .filter-collapse { border-bottom: 1px solid var(--border); background: #fbfcfe; } .filter-summary { display: block; width: 100%; padding: 8px 12px; border: 0; background: transparent; color: #475467; font-size: 12px; font-weight: 600; text-align: left; cursor: pointer; } .filter-summary::before { content: "▸"; margin-right: 6px; color: var(--muted); } .filter-summary[aria-expanded="true"]::before { content: "▾"; } .runs-filter, .findings-filter { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px; padding: 10px 12px; } .runs-filter label, .findings-filter label { display: grid; gap: 3px; min-width: 0; flex: 1 1 110px; } .runs-filter .filter-search { flex: 1 1 160px; } .runs-filter label span, .findings-filter label span { color: var(--muted); font-size: 11px; font-weight: 600; } .runs-filter input, .runs-filter select, .findings-filter input, .findings-filter select { width: 100%; min-height: 30px; padding: 0 8px; border: 1px solid var(--border); border-radius: 6px; background: #ffffff; color: #1f2937; font-size: 12px; } .runs-filter .icon-button, .findings-filter .icon-button { min-height: 30px; align-self: end; } .table-frame { width: 100%; overflow: auto; } .runs-table { width: 100%; min-width: 420px; border-collapse: collapse; } .runs-table th, .runs-table td { padding: 7px 10px; border-bottom: 1px solid var(--border-soft); text-align: left; vertical-align: top; font-size: 12px; } .runs-table th { color: var(--muted); background: #f8fafc; font-size: 11px; font-weight: 700; } .runs-table tr { cursor: pointer; border-left: 3px solid transparent; } .runs-table tr:hover { background: #f7fbff; } .runs-table tr.selected-row { background: #eef7ff; border-left-color: var(--blue); } /* 行级 severity 色条 */ .runs-table tr.severity-red, .runs-table tr.severity-critical, .runs-table tr.severity-error { border-left-color: var(--red); } .runs-table tr.severity-warning, .runs-table tr.severity-amber { border-left-color: var(--amber); } .runs-table tr.severity-info { border-left-color: #97a1b0; } .runs-table tr.selected-row.severity-red, .runs-table tr.selected-row.severity-critical, .runs-table tr.selected-row.severity-error { border-left-color: var(--red); background: #fdeff0; } .runs-table tr.limit-row { cursor: default; border-left-color: transparent; } .runs-table tr.limit-row:hover { background: transparent; } .runs-table tr.limit-row td { color: var(--muted); font-size: 12px; text-align: center; } .runs-table td small { display: block; margin-top: 2px; color: var(--muted); font-size: 11px; overflow-wrap: anywhere; } .run-identity { display: grid; gap: 2px; min-width: 0; } .run-identity code { min-width: 0; font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace; font-size: 11px; overflow-wrap: anywhere; } .run-identity small { color: var(--muted); font-size: 10px; overflow-wrap: anywhere; } .mono { font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace; font-size: 12px; overflow-wrap: anywhere; } /* Detail tab */ .detail-tabs { display: flex; flex-wrap: wrap; gap: 2px; padding: 6px 8px 0; border-bottom: 1px solid var(--border); background: #fbfcfe; } .detail-tab { min-height: 30px; padding: 4px 12px; border: 1px solid transparent; border-bottom: 0; border-radius: 6px 6px 0 0; background: transparent; color: var(--muted); font-size: 12px; font-weight: 600; cursor: pointer; } .detail-tab:hover { background: #ffffff; color: #344054; } .detail-tab.active { background: var(--panel); border-color: var(--border); color: var(--blue); } .detail-content { padding: 12px 14px 14px; overflow: auto; } .detail-block { min-width: 0; margin-bottom: 14px; padding: 0 0 0 10px; border-left: 2px solid #dbe5ee; } .detail-block:last-child { margin-bottom: 0; } .detail-block strong { display: block; margin-bottom: 6px; font-size: 12px; color: #344054; } .detail-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 4px 16px; } .detail-grid > div { display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 8px; align-items: baseline; } .detail-grid span { color: var(--muted); font-size: 11px; } .detail-grid code, .detail-grid em { font-style: normal; font-size: 12px; overflow-wrap: anywhere; } .detail-table-frame { width: 100%; overflow: auto; } .detail-table { width: 100%; min-width: 520px; border-collapse: collapse; } .detail-table th, .detail-table td { padding: 6px 8px; border-bottom: 1px solid var(--border-soft); text-align: left; vertical-align: top; font-size: 12px; } .detail-table th { color: var(--muted); font-size: 11px; font-weight: 700; } .command-list { display: grid; gap: 8px; } .command-row { display: grid; grid-template-columns: minmax(80px, 0.3fr) minmax(0, 1fr) auto; gap: 8px; align-items: center; } .command-row .command-label { color: var(--muted); font-size: 11px; font-weight: 600; } .copy-button { min-height: 28px; padding: 3px 9px; border: 1px solid var(--border); border-radius: 6px; background: #ffffff; color: #344054; font-size: 11px; font-weight: 600; cursor: pointer; white-space: nowrap; } .copy-button:hover { border-color: var(--blue); color: var(--blue); } .copy-button.copied { border-color: var(--green); color: var(--green); } .command-code { display: block; width: 100%; padding: 6px 8px; border: 1px solid #e3e8ef; border-radius: 6px; background: #f8fafc; color: #1f2937; font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace; font-size: 11px; line-height: 1.4; overflow-wrap: anywhere; white-space: pre-wrap; } .view-note { color: var(--muted); font-size: 11px; margin-bottom: 6px; } .detail-pre { display: block; width: 100%; max-width: 100%; margin: 6px 0 0; padding: 9px; border: 1px solid #e3e8ef; border-radius: 6px; background: #f8fafc; color: #1f2937; font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace; font-size: 12px; line-height: 1.45; overflow: auto; white-space: pre-wrap; } .detail-pre { min-height: 120px; max-height: 380px; } .trace-reader-grid { display: grid; grid-template-columns: minmax(200px, 0.7fr) minmax(0, 1.3fr); gap: 10px; } .trace-turn-picker, .trace-frame-view { min-width: 0; } .trace-choice-list { display: grid; gap: 6px; margin-top: 6px; max-height: 360px; overflow: auto; } .trace-choice { display: grid; gap: 3px; width: 100%; padding: 7px 9px; border: 1px solid #d8e0ea; border-radius: 6px; background: #ffffff; color: #344054; cursor: pointer; text-align: left; } .trace-choice.active { border-color: #95c7ff; background: #edf6ff; } .trace-choice span { min-width: 0; font-size: 12px; font-weight: 600; overflow-wrap: anywhere; } .trace-choice small { color: var(--muted); font-size: 11px; overflow-wrap: anywhere; } .trace-frame-pre { min-height: 280px; max-height: 520px; } .trace-source-note { margin-top: 8px; color: var(--muted); font-size: 11px; } .final-response-block { margin-top: 10px; padding: 9px; border: 1px solid #b9e6cc; border-radius: 6px; background: #eefaf4; } .final-response-block.empty, .final-response-block.unavailable { border-color: #d8e0ea; background: #f8fafc; } .final-response-block strong { display: block; margin-bottom: 4px; color: #1f2937; font-size: 12px; } .final-response-text { min-height: 56px; max-height: 240px; margin: 6px 0 0; padding: 8px; border: 1px solid #d8e0ea; border-radius: 6px; background: #ffffff; color: #1f2937; font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace; font-size: 12px; line-height: 1.45; overflow: auto; white-space: pre-wrap; } /* Findings:聚合优先,drill-down 到列表 */ .finding-aggregation { display: grid; grid-template-columns: 1fr; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--border); background: #ffffff; } .aggregation-group { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; } .aggregation-group > span { color: var(--muted); font-size: 11px; font-weight: 600; min-width: 50px; } .aggregation-group .finding-meta { font-size: 12px; } .aggregation-root-cause { align-items: stretch; } .root-cause-chip { max-width: 100%; justify-content: flex-start; white-space: normal; text-align: left; } .finding-list { display: grid; gap: 8px; padding: 10px; } .findings-drilldown-back { margin-bottom: 8px; padding: 0; } .finding-group { min-width: 0; border: 1px solid #e3e8ef; border-radius: 6px; background: #ffffff; } .finding-group summary { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 36px; padding: 7px 10px; cursor: pointer; } .finding-group summary span { font-size: 12px; font-weight: 700; } .finding-group summary strong { font-size: 16px; line-height: 1; } .finding-group summary small { color: var(--muted); font-size: 11px; } .finding-group-list { display: grid; gap: 8px; padding: 0 8px 8px; } /* finding item 默认折叠,只显示 title + severity + count */ .finding-item { display: grid; gap: 6px; padding: 9px 10px; border: 1px solid #e3e8ef; border-radius: 6px; background: var(--panel-soft); } .finding-item.is-collapsed .finding-detail { display: none; } .finding-item.is-collapsed { gap: 5px; } .finding-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; cursor: pointer; } .finding-title { min-width: 0; font-size: 12px; font-weight: 600; overflow-wrap: anywhere; } .finding-title small { margin-left: 6px; color: var(--muted); } .finding-detail { display: grid; gap: 6px; } .finding-direct-cause { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 6px; align-items: start; color: #1f2937; font-size: 11px; line-height: 1.35; overflow-wrap: anywhere; } .finding-direct-cause strong { color: #1d4ed8; } .finding-summary { color: #1f2937; font-size: 12px; line-height: 1.45; overflow-wrap: anywhere; } .finding-root-cause { display: grid; gap: 3px; padding: 7px 8px; border-left: 3px solid #2563eb; border-radius: 4px; background: #f5f9ff; color: #1f2937; font-size: 12px; line-height: 1.45; overflow-wrap: anywhere; } .finding-root-cause strong { color: #1d4ed8; font-size: 11px; } .finding-actions { display: flex; flex-wrap: wrap; gap: 6px; } .filter-chip, .link-button { min-width: 0; border: 1px solid var(--border); border-radius: 999px; background: #ffffff; color: #344054; cursor: pointer; font-size: 11px; font-weight: 600; line-height: 1.3; } .filter-chip { min-height: 24px; padding: 2px 8px; overflow-wrap: anywhere; text-align: left; } .filter-chip.active { border-color: #bdd7ff; background: #edf4ff; color: #1d4ed8; } .link-button { justify-self: start; min-height: 26px; padding: 3px 9px; } .link-button:disabled { cursor: default; opacity: 0.6; } .finding-meta { color: var(--muted); font-size: 11px; line-height: 1.45; } /* Timeline 底部紧凑条 */ .timeline-panel { margin-bottom: 0; } .timeline-toggle { min-height: 26px; padding: 2px 9px; border: 1px solid var(--border); border-radius: 6px; background: #ffffff; color: #344054; font-size: 11px; font-weight: 600; cursor: pointer; } .timeline-panel.collapsed .run-timeline { display: none; } .run-timeline { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; min-height: 40px; padding: 10px 12px; overflow: visible; } .timeline-node { display: inline-flex; align-items: center; gap: 5px; width: auto; min-width: 0; max-width: none; border: 0; background: transparent; color: #475467; cursor: pointer; } .timeline-node::before { content: ""; width: 8px; height: 8px; border: 2px solid currentColor; border-radius: 999px; background: #ffffff; flex: 0 0 auto; } .timeline-node + .timeline-node::before { margin-left: 2px; } .timeline-label { font-size: 11px; font-weight: 600; white-space: nowrap; } .timeline-age { color: var(--muted); font-size: 10px; } .copy-toast { position: fixed; bottom: 16px; right: 16px; padding: 8px 14px; border-radius: 6px; background: #18212f; color: #ffffff; font-size: 12px; font-weight: 600; box-shadow: var(--shadow-overlay); z-index: 100; } .empty-state { padding: 20px 14px; color: var(--muted); text-align: center; font-size: 13px; } .empty-state.compact { padding: 8px; text-align: left; } [hidden] { display: none !important; } /* 桌面端 ≥1024px:三栏;移动端保持原有 @media 断点行为 */ @media (max-width: 1240px) { .dashboard-grid { grid-template-columns: minmax(260px, 1fr) minmax(0, 1.6fr) minmax(260px, 1fr); } } @media (max-width: 1024px) { .dashboard-grid { grid-template-columns: 1fr; } .status-summary { gap: 4px 16px; } } @media (max-width: 980px) { .sentinel-shell { padding: 12px 14px; } .sentinel-topbar { align-items: flex-start; flex-direction: column; } .sentinel-toolbar { justify-content: flex-start; width: 100%; } .summary-checks { margin-left: 0; } .sentinel-registry-strip { grid-template-columns: 1fr; } .runs-filter { flex-wrap: wrap; } .findings-filter { flex-wrap: wrap; } .detail-grid { grid-template-columns: 1fr; } .trace-reader-grid { grid-template-columns: 1fr; } .command-row { grid-template-columns: 1fr auto; } .command-row .command-label { grid-column: 1 / -1; } } @media (max-width: 560px) { .sentinel-shell { padding: 10px; } h1 { font-size: 18px; } .sentinel-toolbar > * { flex: 1 1 auto; } .sentinel-id-chip { max-width: 100%; } .status-pill { justify-content: center; } .icon-button { width: 100%; } .panel-header { align-items: flex-start; flex-direction: column; } .runs-filter, .findings-filter { flex-direction: column; align-items: stretch; } .runs-filter label, .findings-filter label { flex: 1 1 auto; } .table-frame { overflow: visible; } .runs-table, .runs-table tbody, .runs-table tr, .runs-table td { display: block; width: 100%; min-width: 0; } .runs-table { min-width: 0; } .runs-table thead { display: none; } .runs-table tr { padding: 8px 10px; border-bottom: 1px solid var(--border-soft); } .runs-table tr.limit-row { padding: 10px; } .runs-table td { display: grid; grid-template-columns: 70px minmax(0, 1fr); gap: 6px; padding: 4px 0; border-bottom: 0; } .runs-table td::before { content: attr(data-label); color: var(--muted); font-size: 10px; font-weight: 700; } .runs-table tr.limit-row td { display: block; padding: 0; text-align: left; } .runs-table tr.limit-row td::before { content: none; } .finding-group:not([open]) summary { min-height: 34px; } }