/* ============================================================================= Playground Design System — components-tier4-project-view.css v0.6.0 — Tier 4 project-view archetype ============================================================================ Generic "project as artifact-collection" archetype. Default-view is an aggregated overview dashboard; clicking a sidebar item swaps main to a per-artifact render. Tracks 0-N read-only artifacts; edit-mode is paste- import only (markdown from terminal → parser → store). First adopters: ms-ai-architect v1.15.0 (17 artifacts, 5 categories) + llm-security v7.7.0 (≥18 artifacts, 6 categories). Each plugin injects a PROJECT_VIEW_CONFIG object that maps commands → renderers, categories, verdict-aggregators, missing-report heuristics. The CSS in this file is plugin-agnostic. Plugin-specific shape (category names, artifact ordering, custom severity-mappings) lives in JS config. State-driven visibility is NOT handled here — production playgrounds emit only the active state (overview | artifact | empty | import) per render pass. The mockup uses body[data-state="..."] for prototyping; production renders one branch at a time. ============================================================================= */ /* === 1. Project-view top-level layout ===================================== */ .project-view { display: flex; flex-direction: column; gap: var(--space-6); } .project-view__layout { display: grid; grid-template-columns: var(--project-view-nav-width) 1fr; gap: var(--space-6); align-items: start; } @media (max-width: 1279px) { .project-view__layout { grid-template-columns: 240px 1fr; } } @media (max-width: 959px) { .project-view__layout { grid-template-columns: 1fr; } } /* === 2. Project-view header =============================================== */ .project-view__header { background: var(--color-surface); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-md); padding: var(--space-5) var(--space-6); display: grid; grid-template-columns: 1fr auto; grid-template-areas: "title verdict" "title keystats" "actions actions"; gap: var(--space-4) var(--space-6); align-items: start; } .project-view__title-block { grid-area: title; } .project-view__verdict { grid-area: verdict; justify-self: end; } .project-view__key-stats { grid-area: keystats; justify-self: end; } .project-view__actions { grid-area: actions; display: flex; gap: var(--space-2); justify-content: flex-end; } .project-view__eyebrow { font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--color-text-tertiary); font-weight: var(--font-weight-semibold); margin: 0 0 var(--space-2) 0; } .project-view__title { font-size: var(--font-size-2xl); font-weight: var(--font-weight-bold); color: var(--color-text-primary); margin: 0 0 var(--space-2) 0; } .project-view__lede { color: var(--color-text-secondary); margin: 0; max-width: 60ch; } .project-view__key-stats { display: flex; gap: var(--space-5); } .project-view__key-stat-label { font-size: 10px; text-transform: uppercase; color: var(--color-text-tertiary); letter-spacing: 0.06em; } .project-view__key-stat-value { font-size: var(--font-size-lg); font-weight: var(--font-weight-semibold); font-variant-numeric: tabular-nums; } /* === 3. Verdict-pill (small) ============================================== Companion to .verdict-pill-lg (Tier 2). Inline-flex pill used in project header + sidebar status badges. The larger -lg variant lives in components-tier2.css; both share the same severity-band semantics. */ .verdict-pill { display: inline-flex; align-items: center; gap: var(--space-1); padding: 4px 12px; border-radius: 999px; font-weight: var(--font-weight-semibold); font-size: var(--font-size-sm); } .verdict-pill--positive { background: var(--color-state-success); color: #fff; } .verdict-pill--medium { background: var(--color-severity-medium); color: var(--color-severity-medium-on); } .verdict-pill--critical { background: var(--color-severity-critical); color: #fff; } .verdict-pill--in-progress { background: var(--color-bg-soft); color: var(--color-text-secondary); border: 1px dashed var(--color-border-moderate); } /* === 4. Sidebar nav ======================================================= */ .project-view__nav { position: sticky; top: var(--space-6); background: var(--color-surface); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-md); padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-3); } .project-view__nav-search input { width: 100%; box-sizing: border-box; padding: 6px 10px; font-size: var(--font-size-sm); background: var(--color-bg); color: var(--color-text-primary); border: 1px solid var(--color-border-moderate); border-radius: var(--radius-sm); } /* === 5. Artifact-list ===================================================== */ .artifact-list { display: flex; flex-direction: column; gap: var(--space-4); margin: 0; padding: 0; list-style: none; } .artifact-list__group { display: flex; flex-direction: column; gap: var(--space-1); } .artifact-list__group-label { display: flex; justify-content: space-between; align-items: center; font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-tertiary); font-weight: var(--font-weight-semibold); padding: 0 var(--space-2); } .artifact-list__group-count { background: var(--color-bg-soft); color: var(--color-text-tertiary); font-family: var(--font-family-mono); font-size: 10px; padding: 1px 6px; border-radius: 999px; } .artifact-list__group-items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; } .artifact-list__item { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-2); padding: var(--artifact-list-item-pad-y) var(--artifact-list-item-pad-x); border-radius: var(--radius-sm); cursor: pointer; background: transparent; border: 1px solid transparent; transition: background 120ms ease, border-color 120ms ease; } .artifact-list__item:hover { background: var(--color-bg-soft); } .artifact-list__item[data-state="active"] { background: var(--color-bg-soft); border-color: var(--color-primary-500); box-shadow: inset 3px 0 0 var(--color-primary-500); padding-left: calc(var(--artifact-list-item-pad-x) - 3px); } .artifact-list__item-marker { width: var(--artifact-marker-size); height: var(--artifact-marker-size); border-radius: 50%; border: var(--artifact-marker-border) solid var(--color-border-moderate); background: transparent; flex-shrink: 0; } .artifact-list__item[data-state="filled"][data-severity="positive"] .artifact-list__item-marker { background: var(--color-state-success); border-color: var(--color-state-success); } .artifact-list__item[data-state="filled"][data-severity="medium"] .artifact-list__item-marker { background: var(--color-severity-medium); border-color: var(--color-severity-medium); } .artifact-list__item[data-state="filled"][data-severity="critical"] .artifact-list__item-marker { background: var(--color-severity-critical); border-color: var(--color-severity-critical); } .artifact-list__item-body { min-width: 0; } .artifact-list__item-name { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); color: var(--color-text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .artifact-list__item[data-state="empty"] .artifact-list__item-name { color: var(--color-text-tertiary); font-weight: var(--font-weight-regular); } .artifact-list__item-meta { font-size: 11px; color: var(--color-text-tertiary); } /* === 6. Artifact-status (mini pill in sidebar) =========================== */ .artifact-status { font-family: var(--font-family-mono); font-size: 10px; font-weight: var(--font-weight-semibold); padding: 1px 5px; border-radius: var(--radius-sm); letter-spacing: 0.04em; } .artifact-status[data-severity="positive"] { background: var(--color-severity-low-soft); color: var(--color-severity-low-on); } .artifact-status[data-severity="medium"] { background: var(--color-severity-medium-soft); color: var(--color-severity-medium-on); } .artifact-status[data-severity="critical"] { background: var(--color-severity-critical-soft); color: var(--color-severity-critical-on); } /* === 7. Project-view main panel ========================================== */ .project-view__main { min-width: 0; display: flex; flex-direction: column; gap: var(--space-5); } /* === 8. Project-overview (default dashboard) ============================= */ .project-overview { display: flex; flex-direction: column; gap: var(--space-6); } .project-overview__intro { background: var(--color-surface); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-md); padding: var(--space-5); } .project-overview__intro h2 { font-size: var(--font-size-lg); margin: 0 0 var(--space-2) 0; } .project-overview__intro p { color: var(--color-text-secondary); margin: 0; } .project-overview__verdict-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--space-3); } .project-overview__verdict-tile { background: var(--color-surface); border: 1px solid var(--color-border-subtle); border-left: 4px solid var(--color-border-moderate); border-radius: var(--radius-md); padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-1); } .project-overview__verdict-tile[data-severity="positive"] { border-left-color: var(--color-state-success); } .project-overview__verdict-tile[data-severity="medium"] { border-left-color: var(--color-severity-medium); } .project-overview__verdict-tile[data-severity="critical"] { border-left-color: var(--color-severity-critical); } .project-overview__verdict-tile[data-severity="empty"] { border-left-style: dashed; } .project-overview__verdict-tile-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-tertiary); font-weight: var(--font-weight-semibold); } .project-overview__verdict-tile-value { font-size: var(--font-size-lg); font-weight: var(--font-weight-semibold); } .project-overview__verdict-tile-meta { font-size: var(--font-size-xs); color: var(--color-text-secondary); } .project-overview__section h3 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--color-text-tertiary); font-weight: var(--font-weight-semibold); margin: 0 0 var(--space-3) 0; } .project-overview__top-risks, .project-overview__next-actions { background: var(--color-surface); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-md); padding: var(--space-5); } .project-overview__top-risks ol, .project-overview__next-actions ol { list-style: none; counter-reset: rank; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); } .project-overview__top-risks li, .project-overview__next-actions li { counter-increment: rank; display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); background: var(--color-bg-soft); } .project-overview__top-risks li::before, .project-overview__next-actions li::before { content: counter(rank); font-family: var(--font-family-mono); font-weight: var(--font-weight-bold); color: var(--color-text-tertiary); font-size: var(--font-size-sm); min-width: 20px; } .project-overview__missing-reports { background: var(--color-surface); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-md); padding: var(--space-5); } .project-overview__missing-reports ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); } .project-overview__missing-reports li { display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-3); background: var(--color-bg-soft); border-radius: var(--radius-sm); border-left: 3px dashed var(--color-border-moderate); } /* === 9. Artifact-view (one report rendered) ============================== */ .project-view__artifact { background: var(--color-surface); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-md); padding: var(--space-6); display: flex; flex-direction: column; gap: var(--space-5); } .project-view__artifact-header { display: flex; justify-content: space-between; align-items: start; gap: var(--space-4); padding-bottom: var(--space-4); border-bottom: 1px solid var(--color-border-subtle); } .project-view__artifact-title { font-size: var(--font-size-xl); margin: 0 0 var(--space-1) 0; } .project-view__artifact-meta { font-size: var(--font-size-sm); color: var(--color-text-tertiary); margin: 0; } .project-view__artifact-actions { display: flex; gap: var(--space-2); flex-shrink: 0; } .project-view__artifact-body { display: flex; flex-direction: column; gap: var(--space-5); } /* === 10. Empty-artifact-prompt (no report imported yet) ================== */ .empty-artifact-prompt { background: var(--color-surface); border: 2px dashed var(--color-border-moderate); border-radius: var(--radius-md); padding: var(--space-8); display: flex; flex-direction: column; align-items: center; gap: var(--space-3); text-align: center; } .empty-artifact-prompt__icon { font-size: 48px; opacity: 0.5; } .empty-artifact-prompt__title { font-size: var(--font-size-lg); margin: 0; } .empty-artifact-prompt__text { color: var(--color-text-secondary); margin: 0; max-width: 50ch; } .empty-artifact-prompt__actions { display: flex; gap: var(--space-2); margin-top: var(--space-2); } /* === 11. Import-modal (overlay) ========================================== */ .import-modal { position: fixed; inset: 0; z-index: 200; display: none; } .import-modal[data-open="true"] { display: flex; align-items: center; justify-content: center; } .import-modal__backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.55); } .import-modal__panel { position: relative; width: min(720px, 92vw); max-height: 90vh; overflow: auto; background: var(--color-surface); border: 1px solid var(--color-border-strong); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); display: flex; flex-direction: column; } .import-modal__head { display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--color-border-subtle); } .import-modal__title { margin: 0; font-size: var(--font-size-lg); font-weight: var(--font-weight-semibold); } .import-modal__close { background: transparent; border: none; cursor: pointer; padding: 4px 10px; color: var(--color-text-tertiary); font-size: 20px; line-height: 1; border-radius: var(--radius-sm); } .import-modal__close:hover { background: var(--color-bg-soft); color: var(--color-text-primary); } .import-modal__form { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-4); } .import-modal__form .field { display: flex; flex-direction: column; gap: var(--space-1); } .import-modal__form label { font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--color-text-secondary); } .import-modal__form select, .import-modal__form textarea { width: 100%; box-sizing: border-box; padding: var(--space-2) var(--space-3); background: var(--color-bg); color: var(--color-text-primary); border: 1px solid var(--color-border-moderate); border-radius: var(--radius-sm); font-family: var(--font-family-mono); font-size: var(--font-size-sm); } .import-modal__form textarea { resize: vertical; min-height: 180px; } .import-modal__detect { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); background: var(--color-severity-low-soft); color: var(--color-severity-low-on); font-size: var(--font-size-sm); } .import-modal__preview { border: 1px solid var(--color-border-subtle); border-radius: var(--radius-sm); padding: var(--space-3); background: var(--color-bg); max-height: 200px; overflow: auto; } .import-modal__preview-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-tertiary); margin-bottom: var(--space-2); } .import-modal__footer { display: flex; justify-content: flex-end; gap: var(--space-2); padding: var(--space-3) var(--space-5); border-top: 1px solid var(--color-border-subtle); background: var(--color-bg-soft); }