/* SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-27-p12-cadence-scheduler-monitor-web. */ :root { color-scheme: light; --bg: #f5f7f8; --panel: #ffffff; --panel-soft: #f9fbfb; --text: #17201f; --muted: #5e6b68; --line: #dce3e1; --line-strong: #b8c4c0; --red: #d43c35; --red-soft: #ffe8e5; --amber: #b7791f; --amber-soft: #fff2d6; --green: #1f8a5b; --green-soft: #e4f6ed; --blue: #2a6fbb; --ink: #203330; --shadow: 0 10px 28px rgba(32, 51, 48, 0.08); font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; } * { box-sizing: border-box; } html, body, #monitor-web-root { height: 100%; margin: 0; } body { background: var(--bg); color: var(--text); overflow: hidden; } button, select, input { font: inherit; } .monitor-shell { display: flex; height: 100dvh; min-height: 0; flex-direction: column; gap: 10px; overflow: hidden; padding: 12px; } .topbar, .status-strip, .entry-strip, .trend-stage, .workspace-grid { width: min(100%, 1760px); margin: 0 auto; } .topbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex: 0 0 auto; min-height: 58px; } .title-block { display: flex; min-width: 0; align-items: center; gap: 12px; } .mark { width: 34px; height: 34px; border: 2px solid var(--ink); border-radius: 8px; background: linear-gradient(135deg, #ffffff 0%, #e7f1ef 100%); box-shadow: inset 0 -8px 0 rgba(31, 138, 91, 0.16); } h1, h2, h3, p { margin: 0; } h1 { font-size: 20px; line-height: 1.15; letter-spacing: 0; } .subtitle { display: flex; min-width: 0; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 4px; color: var(--muted); font-size: 12px; } code, .mono { font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace; } .pill, .toolbar-button, .entry-link, .legend-item, .metric, .timeline-item, .run-row, .finding-card, .check-chip { border: 1px solid var(--line); border-radius: 8px; background: var(--panel); } .toolbar { display: flex; flex: 0 0 auto; flex-wrap: wrap; justify-content: flex-end; gap: 8px; } .toolbar-button, select { min-height: 34px; border: 1px solid var(--line-strong); border-radius: 8px; background: #ffffff; color: var(--text); cursor: pointer; } .toolbar-button { padding: 0 12px; } select { padding: 0 28px 0 10px; } .pill { display: inline-flex; align-items: center; gap: 6px; min-height: 30px; padding: 0 10px; color: var(--muted); font-size: 12px; white-space: nowrap; } .pill::before { content: ""; width: 7px; height: 7px; border-radius: 999px; background: var(--muted); } .pill.blocked, .pill.degraded { border-color: #efb3ad; background: var(--red-soft); color: #8b1f1a; } .pill.blocked::before, .pill.degraded::before { background: var(--red); } .pill.warning { border-color: #e5c06b; background: var(--amber-soft); color: #73500f; } .pill.warning::before { background: var(--amber); } .pill.healthy, .pill.idle { border-color: #b9ddc9; background: var(--green-soft); color: #17633f; } .pill.healthy::before, .pill.idle::before { background: var(--green); } .entry-strip { display: grid; grid-template-columns: minmax(180px, 240px) minmax(0, 1fr); gap: 10px; flex: 0 0 auto; align-items: stretch; } .entry-copy { display: flex; min-height: 52px; flex-direction: column; justify-content: center; color: var(--muted); font-size: 12px; } .entry-copy strong { color: var(--text); font-size: 15px; } .entry-links { display: flex; min-width: 0; gap: 8px; overflow-x: auto; padding-bottom: 2px; } .entry-link { display: grid; grid-template-columns: minmax(130px, 1fr) auto; min-width: 220px; max-width: 360px; gap: 10px; align-items: center; padding: 9px 10px; color: var(--text); text-decoration: none; } .entry-link.current { border-color: var(--green); box-shadow: inset 3px 0 0 var(--green); } .entry-link.disabled { opacity: 0.55; } .entry-link span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .entry-link small { color: var(--muted); font-size: 11px; } .trend-stage { display: grid; grid-template-columns: minmax(420px, 1.55fr) minmax(300px, 0.9fr); gap: 10px; flex: 0 0 auto; min-height: 212px; } .trend-panel, .timeline-panel, .pane, .status-strip { border: 1px solid var(--line); border-radius: 8px; background: var(--panel); box-shadow: var(--shadow); } .trend-panel, .timeline-panel { min-width: 0; padding: 12px; } .panel-header { display: flex; align-items: start; justify-content: space-between; gap: 12px; margin-bottom: 10px; } .panel-header h2 { font-size: 15px; line-height: 1.25; } .panel-header p, .muted { color: var(--muted); font-size: 12px; } .trend-chart-wrap { position: relative; min-height: 142px; border: 1px solid var(--line); border-radius: 8px; background: linear-gradient(180deg, #ffffff 0%, #f7faf9 100%); overflow: visible; } .trend-chart { display: block; width: 100%; height: 142px; } .trend-empty { position: absolute; inset: 0; display: grid; place-items: center; color: var(--muted); font-size: 13px; } .trend-red { fill: none; stroke: var(--red); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; } .trend-warning { fill: none; stroke: var(--amber); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; } .trend-total { fill: none; stroke: var(--blue); stroke-width: 2; stroke-dasharray: 5 6; stroke-linecap: round; stroke-linejoin: round; opacity: 0.75; } .trend-grid-line { stroke: #e5ecea; stroke-width: 1; } .trend-dot-red { fill: var(--red); } .trend-dot-warning { fill: var(--amber); } .trend-dot-hit { cursor: default; outline: none; } .trend-dot-hit:focus-visible .trend-hit-area { stroke: var(--blue); stroke-width: 1.5; } .trend-hit-area { fill: transparent; stroke: transparent; } .trend-tooltip { position: absolute; z-index: 8; display: grid; width: min(218px, calc(100% - 16px)); max-width: calc(100% - 16px); gap: 3px; transform: translate(-50%, -100%); border: 1px solid var(--line-strong); border-radius: 8px; background: #ffffff; box-shadow: 0 12px 28px rgba(32, 51, 48, 0.16); color: var(--muted); padding: 9px 10px; pointer-events: none; font-size: 12px; line-height: 1.35; } .trend-tooltip strong { overflow: hidden; color: var(--text); text-overflow: ellipsis; white-space: nowrap; } .trend-legend { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; } .legend-item { display: inline-flex; align-items: center; gap: 6px; min-height: 28px; padding: 0 9px; color: var(--muted); font-size: 12px; } .legend-swatch { width: 18px; height: 3px; border-radius: 999px; } .legend-swatch.red { background: var(--red); } .legend-swatch.warning { background: var(--amber); } .legend-swatch.total { background: var(--blue); } .timeline-panel { display: flex; min-height: 0; flex-direction: column; } .timeline-list { display: grid; max-height: 150px; gap: 7px; overflow: auto; padding-right: 2px; } .timeline-item { display: grid; grid-template-columns: 78px minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 7px 8px; font-size: 12px; } .timeline-item strong, .run-row strong, .finding-card strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .timeline-marker { width: 9px; height: 9px; border-radius: 999px; background: var(--green); } .timeline-item.red .timeline-marker, .run-row.red .severity-dot, .finding-card.red .severity-dot { background: var(--red); } .timeline-item.warning .timeline-marker, .run-row.warning .severity-dot, .finding-card.warning .severity-dot { background: var(--amber); } .timeline-item.info .timeline-marker, .run-row.info .severity-dot, .finding-card.info .severity-dot { background: var(--blue); } .status-strip { display: grid; grid-template-columns: repeat(5, minmax(120px, 1fr)); gap: 8px; flex: 0 0 auto; padding: 8px; } .metric { display: flex; min-width: 0; flex-direction: column; gap: 2px; padding: 8px 10px; background: var(--panel-soft); } .metric span { color: var(--muted); font-size: 11px; } .metric strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; } .metric.warning { border-color: #e5c06b; background: var(--amber-soft); } .workspace-grid { display: grid; grid-template-columns: minmax(260px, 0.82fr) minmax(420px, 1.34fr) minmax(300px, 1fr); gap: 10px; flex: 1 1 auto; min-height: 0; overflow: hidden; } .pane { position: relative; isolation: isolate; display: flex; min-width: 0; min-height: 0; flex-direction: column; overflow: auto; padding: 12px; } .pane-header { position: sticky; top: -12px; z-index: 12; display: flex; align-items: start; justify-content: space-between; gap: 10px; margin: -12px -12px 10px; padding: 12px 12px 13px; border-bottom: 1px solid var(--line); background: var(--panel); box-shadow: 0 10px 16px rgba(32, 51, 48, 0.08); } .pane-header::before { position: absolute; right: 0; left: 0; top: -18px; height: 18px; background: var(--panel); content: ""; } .pane-header h2 { font-size: 15px; } .filter-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; } .filter-row input, .filter-row select { min-width: 0; min-height: 32px; border: 1px solid var(--line-strong); border-radius: 8px; padding: 0 10px; background: #ffffff; } .run-list, .finding-list, .detail-stack { display: grid; gap: 8px; } .run-row, .finding-card { display: grid; gap: 6px; padding: 10px; text-align: left; } .run-row { cursor: pointer; } .run-row.selected { border-color: var(--blue); box-shadow: inset 3px 0 0 var(--blue); } .row-line { display: flex; min-width: 0; align-items: center; justify-content: space-between; gap: 8px; } .severity-line { display: flex; align-items: center; gap: 6px; min-width: 0; } .severity-dot { width: 8px; height: 8px; flex: 0 0 auto; border-radius: 999px; background: var(--green); } .tag { display: inline-flex; align-items: center; min-height: 22px; max-width: 100%; border-radius: 999px; background: #eef3f1; color: var(--muted); padding: 0 8px; font-size: 11px; } .tag.red { background: var(--red-soft); color: #8b1f1a; } .tag.warning { background: var(--amber-soft); color: #73500f; } .detail-card { border: 1px solid var(--line); border-radius: 8px; background: var(--panel-soft); padding: 12px; } .detail-card h3 { margin-bottom: 8px; font-size: 14px; } .detail-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; } .detail-grid .metric { background: #ffffff; } pre { max-height: 240px; margin: 0; overflow: auto; border: 1px solid var(--line); border-radius: 8px; background: #10211e; color: #eef8f4; padding: 10px; font-size: 12px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; } .check-grid { display: flex; flex-wrap: wrap; gap: 6px; } .check-chip { min-height: 26px; padding: 5px 8px; color: var(--muted); font-size: 11px; } .check-chip.ok { border-color: #b9ddc9; background: var(--green-soft); color: #17633f; } .check-chip.bad { border-color: #efb3ad; background: var(--red-soft); color: #8b1f1a; } .banner { width: min(100%, 1760px); margin: 0 auto; flex: 0 0 auto; border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; font-size: 13px; } .banner.error { border-color: #efb3ad; background: var(--red-soft); color: #8b1f1a; } .empty { display: grid; min-height: 120px; place-items: center; border: 1px dashed var(--line-strong); border-radius: 8px; color: var(--muted); font-size: 13px; } @media (max-width: 1120px) { body { overflow: auto; } .monitor-shell { height: auto; min-height: 100dvh; overflow: visible; } .trend-stage, .workspace-grid, .entry-strip { grid-template-columns: 1fr; } .workspace-grid { overflow: visible; } .pane { max-height: 72dvh; } .status-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); } } @media (max-width: 640px) { .monitor-shell { padding: 8px; } .topbar { align-items: stretch; flex-direction: column; } .toolbar { justify-content: stretch; } .toolbar-button, .toolbar select { flex: 1 1 96px; } .entry-link { min-width: 190px; } .status-strip, .detail-grid { grid-template-columns: 1fr; } .timeline-item { grid-template-columns: 62px minmax(0, 1fr); } .timeline-item .tag { grid-column: 2; width: max-content; } }