feat(playground-design-system): v0.3.0 — playground/report-page foundation primitives [skip-docs]
Hoists 13 generic CSS components (sections 13-25 in tier3-supplement) from
ms-ai-architect inline CSS to shared/ so all 5 plugin consumers get the same
vocabulary and visual signature.
Shared additions:
- .eyebrow utility, .page__* page-shell (header/title/eyebrow/lede/meta)
- .key-stats grid + .key-stat + severity modifiers (large tabular-nums values)
- .verdict-pill-lg 5-band extension (critical/high/medium/low/positive/n-a)
- .tab-list / .tab / .tab-panel generic tab-component
- .top-risks / .top-risk[data-severity] severity-ordered risk list
- .recommendation-card[data-severity] emphasized advisory callout
- .card__head/title/desc/id/meta/hint/actions/pill subcomponents
- .card--severity-{level} 4px left-border modifier
- Form patterns (.field-row, .field-label, .field-help, .multi-select,
.checkbox-row, .required-mark)
- .stack-lg/.stack-md/.stack-sm vertical rhythm utilities
- .pyramide-tier-detail expandable details below pyramide
- .scenario-card-grid + .scenario-card[data-status="winner"] grid pattern
- .app-shell / .app-shell--wide / .app-shell--narrow page wrappers
Total: 567 new lines in tier3-supplement.css, 107 new selectors. Purely
additive — no existing selector changed or removed. v0.2 -> v0.3.
DS CHANGELOG.md updated with full v0.3 entry.
ms-ai-architect playground:
- Re-synced vendored DS to v0.3 (force flag — overwrites stale v0.2 vendor)
- Deleted 8 inline DUPLICATE definitions (.app-shell* + form patterns) now
served by shared DS
- Inline <style> block: 210 -> 202 lines (start of multi-session refactor;
remaining PARALLEL classes migrate in Session 2)
Tests: 215 + 201 + 70 + 7 = 493 PASS. No regressions.
Plugin user-facing docs (README, CLAUDE.md, marketplace landing) update in
Session 3 (Phase 9) when full v1.11.0 ships. This commit is internal
foundation work — DS CHANGELOG already documents the shared changes.
Session 1 of 3 in v1.11.0 design-system 100%-adoption refactor.
Plan: /Users/ktg/.claude/plans/jeg-skal-pr-ve-effervescent-token.md
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
|
@ -49,8 +49,8 @@
|
|||
setter eksplisitt display, som overstyrer HTMLs default [hidden] {display:none}.
|
||||
Globalt override slik at hidden-attributt faktisk skjuler elementet. */
|
||||
[hidden] { display: none !important; }
|
||||
.app-shell { max-width: 1200px; margin: 0 auto; padding: var(--space-6) var(--space-5); }
|
||||
.app-shell--wide { max-width: 1400px; }
|
||||
|
||||
/* .app-shell + .app-shell--wide hentet fra vendored DS v0.3 (tier3-supplement section 25) */
|
||||
|
||||
/* Topbar — vises på alle surfaces unntatt onboarding (uten projekt-kontekst) */
|
||||
.topbar { display: flex; align-items: center; justify-content: space-between; padding: var(--space-3) var(--space-5); border-bottom: 1px solid var(--color-border-subtle); background: var(--color-surface); position: sticky; top: 0; z-index: 10; }
|
||||
|
|
@ -68,13 +68,10 @@
|
|||
.onboarding-header p { color: var(--color-text-secondary); margin: 0; max-width: 60ch; }
|
||||
.onboarding-groups { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-6); }
|
||||
.onboarding-fields { display: flex; flex-direction: column; gap: var(--space-4); padding: var(--space-2) 0; }
|
||||
.field-row { display: flex; flex-direction: column; gap: 6px; }
|
||||
.field-label { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); color: var(--color-text-primary); }
|
||||
.field-help { font-size: var(--font-size-xs); color: var(--color-text-tertiary); }
|
||||
.multi-select { display: flex; flex-direction: column; gap: 4px; border: 0; padding: 0; margin: 0; }
|
||||
.checkbox-row { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: var(--font-size-sm); padding: 4px 0; }
|
||||
.checkbox-row input { margin: 0; }
|
||||
.required-mark { color: var(--color-severity-critical); margin-left: 2px; }
|
||||
|
||||
/* Form-patterns (.field-row, .field-label, .field-help, .multi-select,
|
||||
.checkbox-row, .required-mark) hentet fra vendored DS v0.3 (tier3-supplement section 21) */
|
||||
|
||||
.onboarding-actions { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) 0; flex-wrap: wrap; }
|
||||
.onboarding-help { font-size: var(--font-size-sm); color: var(--color-text-tertiary); }
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 714 KiB After Width: | Height: | Size: 718 KiB |
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 244 KiB |
|
Before Width: | Height: | Size: 3.7 MiB After Width: | Height: | Size: 3.7 MiB |
|
Before Width: | Height: | Size: 3.7 MiB After Width: | Height: | Size: 3.7 MiB |
|
Before Width: | Height: | Size: 4 MiB After Width: | Height: | Size: 3.9 MiB |
|
Before Width: | Height: | Size: 3.9 MiB After Width: | Height: | Size: 3.9 MiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB |
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB |
|
Before Width: | Height: | Size: 828 KiB After Width: | Height: | Size: 825 KiB |
|
Before Width: | Height: | Size: 827 KiB After Width: | Height: | Size: 824 KiB |
|
Before Width: | Height: | Size: 223 KiB After Width: | Height: | Size: 218 KiB |
|
Before Width: | Height: | Size: 221 KiB After Width: | Height: | Size: 216 KiB |
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 214 KiB |
|
Before Width: | Height: | Size: 218 KiB After Width: | Height: | Size: 213 KiB |
|
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 189 KiB |
|
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 218 KiB After Width: | Height: | Size: 218 KiB |
|
Before Width: | Height: | Size: 215 KiB After Width: | Height: | Size: 215 KiB |
|
Before Width: | Height: | Size: 382 KiB After Width: | Height: | Size: 380 KiB |
|
Before Width: | Height: | Size: 379 KiB After Width: | Height: | Size: 377 KiB |
|
Before Width: | Height: | Size: 249 KiB After Width: | Height: | Size: 246 KiB |
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 244 KiB |
|
|
@ -1,5 +1,36 @@
|
|||
# playground-design-system — CHANGELOG
|
||||
|
||||
## 0.3.0 — 2026-05-04
|
||||
|
||||
### Added — Playground/report-page foundation primitives (sections 13-25 in tier3-supplement)
|
||||
|
||||
Generiske mønstre som tidligere ble definert inline i plugin-playgrounds (først i ms-ai-architect v1.10) er hoisted hit slik at alle 5 plugin-konsumenter (`ms-ai-architect`, `okr`, `llm-security`, `ultraplan-local`, `config-audit`) kan dele samme vokabular og visuelle profil.
|
||||
|
||||
- **`.eyebrow` utility** — uppercase 11px monospace label med 0.08em letter-spacing. Bruk over seksjons-titler.
|
||||
- **`.page__*` page-shell** (`.page__header`, `.page__header-main`, `.page__header-aside`, `.page__eyebrow`, `.page__title`, `.page__lede`, `.page__meta`) — standard rapport-side-header med eyebrow → h1 → lede → meta + verdict-slot side-by-side. Responsiv: kollapser til én kolonne under 720px.
|
||||
- **`.key-stats` / `.key-stat`** — 2-5-kolonne responsivt grid av store tall-metrikker. `font-variant-numeric: tabular-nums`, `font-size-2xl` bold. Severity-modifiers (`.key-stat--critical/high/medium/low/positive/info`) tinter value-fargen.
|
||||
- **`.verdict-pill-lg` 5-band utvidelse** — eksisterende `.verdict-pill-lg` aksepterer nå alle 5 severity-bånd: `critical/extreme/high/medium/low/positive` + neutral `n-a/info/neutral`. Bakoverkompatibel med eksisterende `block/warning/allow`.
|
||||
- **`.tab-list` / `.tab` / `.tab-panel`** — generisk faneflate-komponent. ARIA-paritet: `role="tablist"`, `role="tab"`, `aria-current="true"`. `.tab__count` for badge-tall, `.tab-panel[hidden]` for skjuling.
|
||||
- **`.top-risks` / `.top-risk[data-severity]`** — severity-ordnet liste over topp-risikoer med rank/desc/score-kolonner. Severity-attribut driver venstre-border + score-pill-bakgrunn.
|
||||
- **`.recommendation-card[data-severity]`** — emphasized advisory-callout med label + body. 6 severity-modifiers.
|
||||
- **`.card__*` subkomponenter** — komponerbare tillegg til eksisterende `.card` (base.css): `.card__head`, `.card__title`, `.card__desc`, `.card__id`, `.card__meta`, `.card__hint`, `.card__actions`, `.card__pill`. Pluss `.card--severity-{level}` for 4px venstre-border-modifier.
|
||||
- **Form patterns** — `.field-row` (vertikal flex), `.field-label` (medium weight), `.field-help` (xs tertiary), `.required-mark` (severity-critical asterisk), `.multi-select` (fieldset reset), `.checkbox-row` (inline-flex med hover). Mirrors Aksel/Digdir form-konvensjoner.
|
||||
- **Section-spacing utilities** — `.stack-lg` (margin-block: var(--space-8)), `.stack-md` (var(--space-5)), `.stack-sm` (var(--space-3)). Anvendes på parent for å gi konsistent vertikal rytme mellom barn-elementer.
|
||||
- **`.pyramide-tier-detail`** — utvidbar `<details>`-blokk under `.pyramide`-visualisering. Custom chevron, ingen native marker. Brukes av AI Act-klassifiserings-renderer.
|
||||
- **`.scenario-card-grid` / `.scenario-card[data-status="winner"]`** — auto-fit grid (minmax 240px) av scenario/alternativ-cards. Vinnerstatus får success-tinted bakgrunn + grønn count-pill.
|
||||
- **`.app-shell` / `.app-shell--wide` / `.app-shell--narrow`** — sentralisert max-width page-wrapper. 1200/1400/880px varianter.
|
||||
|
||||
### Notes for vendor consumers
|
||||
|
||||
Versjon 0.3.0 er **rent additiv** — ingen eksisterende selector er endret eller fjernet. Alle eksisterende klasser (`.btn`, `.card`, `.expansion`, `.kanban-*`, `.mat-ladder`, `.read-more`, `.suppressed`, `.pair-before-after`, `.verdict-pill-lg` osv.) fungerer uendret.
|
||||
|
||||
For å adoptere v0.3:
|
||||
1. Re-sync via `node scripts/sync-design-system.mjs <plugin-name>` (kreves `--force` hvis eksisterende drift)
|
||||
2. Oppdater plugin HTML til å bruke nye klasser i stedet for inline CSS
|
||||
3. Andre plugins kan vente med adopsjon — eksisterende DS-bruk fortsetter å fungere
|
||||
|
||||
Førsteadopter: `ms-ai-architect` v1.11.0 (planlagt 2026-05-04).
|
||||
|
||||
## 0.2.0 — 2026-05-04
|
||||
|
||||
### Added
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@
|
|||
"generated_by": "scripts/sync-design-system.mjs",
|
||||
"do_not_edit": true,
|
||||
"source": "shared/playground-design-system/",
|
||||
"source_commit": "a5c12b68d9f1eba093c876f5bd33394f99d422ef",
|
||||
"sync_date": "2026-05-04T01:03:31.587Z",
|
||||
"source_commit": "e3378e9b9c8df259ba12f8146c44e5c18b40ff31",
|
||||
"sync_date": "2026-05-04T07:56:18.490Z",
|
||||
"file_count": 26,
|
||||
"files": {
|
||||
"CHANGELOG.md": "7e559e64a5e854c250b697696ca8d50bc81c7a683d1e5d77ce722d0f47329a32",
|
||||
"CHANGELOG.md": "e293a911701e0ae8e95f8d30e2b583d1c578d0c2af4fd2abfbee3a7d65d5f7ba",
|
||||
"README.md": "83de0e29b207c979b7b2a3327b7a4ec0c2e1b4d3705ee2677f26c28c3a3ee643",
|
||||
"base.css": "604fe6839e2ed304bc0ba112a4e045f208b4b3f084f449a1abdb94ce0a1e5263",
|
||||
"components-tier2.css": "c2cb7e9d76d6af28d50db654030413777feb2f2f2b93213e598de8b686b14523",
|
||||
"components-tier3-supplement.css": "5b70503ce81a4aefc269e894ab0ae0921ab48370a00de19c737354274f520387",
|
||||
"components-tier3-supplement.css": "b78664275948f05b9cb4e577921695bd39d15b34c671809d8c8465cac4e1739b",
|
||||
"components-tier3.css": "c391ea387298ce864bc35078e7e044b2cdd4187e3130456347d91876599ff4b1",
|
||||
"components.css": "f76b22ba9fd64c2e806b4467536174347105f3e5ccca8a6349a919287d864b86",
|
||||
"fonts.css": "e3c3df581c6e4d66e25c555f125c745f6512a33038401089d2519a94ea63ee3d",
|
||||
|
|
|
|||
|
|
@ -885,3 +885,571 @@
|
|||
.okr-mode__row { display: flex; gap: var(--space-4); align-items: center; }
|
||||
.okr-mode__objective { font-size: var(--font-size-md); color: var(--color-text-primary); flex: 1; }
|
||||
.okr-mode__hint { font-size: 12px; color: var(--color-text-tertiary); margin-top: 4px; }
|
||||
|
||||
/* =============================================================================
|
||||
v0.3 ADDITIONS — playground/report-page foundation primitives.
|
||||
Originally defined inline in plugin playgrounds (ms-ai-architect v1.10).
|
||||
Hoisted here so all 5 plugin consumers share the same vocabulary.
|
||||
============================================================================= */
|
||||
|
||||
/* =========================================================================
|
||||
13. Eyebrow utility (.eyebrow)
|
||||
Uppercase mini-label above section titles. Mono, generous tracking.
|
||||
========================================================================= */
|
||||
.eyebrow {
|
||||
display: inline-block;
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: 11px;
|
||||
font-weight: var(--font-weight-semibold);
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-scope-architect, var(--color-text-link));
|
||||
margin: 0 0 var(--space-2);
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
14. Page-shell (.page__*)
|
||||
Standard report-page header used by renderPageShell() in playgrounds.
|
||||
eyebrow → h1 → optional lede → optional meta + verdict slot side-by-side.
|
||||
========================================================================= */
|
||||
.page__header {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
gap: var(--space-5);
|
||||
align-items: start;
|
||||
padding-block: var(--space-3) var(--space-4);
|
||||
margin-bottom: var(--space-5);
|
||||
border-bottom: 1px solid var(--color-border-subtle);
|
||||
}
|
||||
.page__header-main { min-width: 0; }
|
||||
.page__header-aside {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
.page__eyebrow {
|
||||
display: inline-block;
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: 11px;
|
||||
font-weight: var(--font-weight-semibold);
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-scope-architect, var(--color-text-link));
|
||||
margin: 0 0 var(--space-2);
|
||||
}
|
||||
.page__title {
|
||||
font-family: var(--font-family-sans);
|
||||
font-size: var(--font-size-3xl);
|
||||
font-weight: var(--font-weight-bold);
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 1.15;
|
||||
color: var(--color-text-primary);
|
||||
margin: 0 0 var(--space-2);
|
||||
}
|
||||
.page__lede {
|
||||
font-size: var(--font-size-md);
|
||||
line-height: 1.55;
|
||||
color: var(--color-text-secondary);
|
||||
max-width: 70ch;
|
||||
margin: 0 0 var(--space-2);
|
||||
}
|
||||
.page__meta {
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: 12px;
|
||||
color: var(--color-text-tertiary);
|
||||
display: flex;
|
||||
gap: var(--space-3);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
@media (max-width: 720px) {
|
||||
.page__header { grid-template-columns: 1fr; }
|
||||
.page__header-aside { align-items: flex-start; }
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
15. Key-stats grid (.key-stats / .key-stat)
|
||||
2-5 column responsive grid of large-number metrics. Uses tabular-nums for
|
||||
visual alignment. Severity modifiers tint the value color.
|
||||
========================================================================= */
|
||||
.key-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: var(--space-4);
|
||||
padding: var(--space-4) var(--space-5);
|
||||
background: var(--color-bg-soft);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: var(--radius-lg);
|
||||
margin-block: var(--space-4);
|
||||
}
|
||||
.key-stat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
}
|
||||
.key-stat__label {
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: 11px;
|
||||
font-weight: var(--font-weight-semibold);
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-text-tertiary);
|
||||
}
|
||||
.key-stat__value {
|
||||
font-family: var(--font-family-sans);
|
||||
font-size: var(--font-size-2xl);
|
||||
font-weight: var(--font-weight-bold);
|
||||
letter-spacing: -0.02em;
|
||||
font-variant-numeric: tabular-nums;
|
||||
color: var(--color-text-primary);
|
||||
line-height: 1.1;
|
||||
word-break: break-word;
|
||||
}
|
||||
.key-stat__hint {
|
||||
font-size: 12px;
|
||||
color: var(--color-text-tertiary);
|
||||
margin-top: 2px;
|
||||
}
|
||||
.key-stat--critical .key-stat__value { color: var(--color-severity-critical); }
|
||||
.key-stat--high .key-stat__value { color: var(--color-severity-high); }
|
||||
.key-stat--medium .key-stat__value { color: var(--color-severity-medium); }
|
||||
.key-stat--low .key-stat__value { color: var(--color-severity-low); }
|
||||
.key-stat--positive .key-stat__value { color: var(--color-state-success); }
|
||||
.key-stat--info .key-stat__value { color: var(--color-state-info); }
|
||||
|
||||
/* =========================================================================
|
||||
16. Verdict-pill 5-band extension
|
||||
Extends existing .verdict-pill-lg (Tier 2) to all 5 severity bands +
|
||||
neutral n-a. Backward compatible — existing block/warning/allow keys
|
||||
remain unchanged.
|
||||
========================================================================= */
|
||||
.verdict-pill-lg[data-verdict="critical"],
|
||||
.verdict-pill-lg[data-verdict="extreme"] { background: var(--color-severity-critical); color: #fff; }
|
||||
.verdict-pill-lg[data-verdict="high"] { background: var(--color-severity-high); color: #fff; }
|
||||
.verdict-pill-lg[data-verdict="medium"] { background: var(--color-severity-medium); color: var(--color-severity-medium-on); }
|
||||
.verdict-pill-lg[data-verdict="low"] { background: var(--color-severity-low); color: #fff; }
|
||||
.verdict-pill-lg[data-verdict="positive"] { background: var(--color-state-success); color: #fff; }
|
||||
.verdict-pill-lg[data-verdict="n-a"],
|
||||
.verdict-pill-lg[data-verdict="info"],
|
||||
.verdict-pill-lg[data-verdict="neutral"] {
|
||||
background: var(--color-surface-sunken);
|
||||
color: var(--color-text-secondary);
|
||||
border: 1px solid var(--color-border-moderate);
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
17. Tab-component (.tab-list / .tab / .tab-panel)
|
||||
Generic tabbed interface. ARIA-paritet: role="tablist", role="tab",
|
||||
aria-current="true" for active. tab-panel is hidden via [hidden] attr.
|
||||
========================================================================= */
|
||||
.tab-list {
|
||||
display: flex;
|
||||
gap: var(--space-1);
|
||||
flex-wrap: wrap;
|
||||
padding: 4px;
|
||||
background: var(--color-bg-soft);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: var(--radius-md);
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
.tab {
|
||||
appearance: none;
|
||||
border: 1px solid transparent;
|
||||
background: transparent;
|
||||
color: var(--color-text-secondary);
|
||||
font-family: var(--font-family-sans);
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: var(--font-weight-medium);
|
||||
padding: 6px var(--space-3);
|
||||
border-radius: var(--radius-sm);
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
transition: background var(--duration-fast), color var(--duration-fast);
|
||||
}
|
||||
.tab:hover { background: var(--color-surface-sunken); color: var(--color-text-primary); }
|
||||
.tab[aria-current="true"] {
|
||||
background: var(--color-surface);
|
||||
color: var(--color-text-primary);
|
||||
border-color: var(--color-border-subtle);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
.tab:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
|
||||
.tab__count {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 22px;
|
||||
padding: 0 6px;
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: 11px;
|
||||
background: var(--color-surface-sunken);
|
||||
color: var(--color-text-tertiary);
|
||||
border-radius: 999px;
|
||||
}
|
||||
.tab[aria-current="true"] .tab__count {
|
||||
background: var(--color-bg-soft);
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
.tab-panel { padding-block: var(--space-3); }
|
||||
.tab-panel[hidden] { display: none; }
|
||||
|
||||
/* =========================================================================
|
||||
18. Top-risks (.top-risks / .top-risk)
|
||||
Severity-ordered list of top risk items used by ROS/security renderers.
|
||||
Each row: rank dot - description - score column. Severity drives left-border.
|
||||
========================================================================= */
|
||||
.top-risks {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-2);
|
||||
margin-block: var(--space-4);
|
||||
}
|
||||
.top-risks__heading {
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: 11px;
|
||||
font-weight: var(--font-weight-semibold);
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-text-tertiary);
|
||||
margin: 0 0 var(--space-1);
|
||||
}
|
||||
.top-risk {
|
||||
display: grid;
|
||||
grid-template-columns: 32px 1fr auto;
|
||||
gap: var(--space-3);
|
||||
align-items: center;
|
||||
padding: var(--space-3) var(--space-4);
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-left: 4px solid var(--color-border-moderate);
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
.top-risk[data-severity="critical"] { border-left-color: var(--color-severity-critical); }
|
||||
.top-risk[data-severity="high"] { border-left-color: var(--color-severity-high); }
|
||||
.top-risk[data-severity="medium"] { border-left-color: var(--color-severity-medium); }
|
||||
.top-risk[data-severity="low"] { border-left-color: var(--color-severity-low); }
|
||||
.top-risk__rank {
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: var(--font-size-md);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--color-text-tertiary);
|
||||
text-align: center;
|
||||
}
|
||||
.top-risk__desc {
|
||||
font-size: var(--font-size-md);
|
||||
line-height: 1.4;
|
||||
color: var(--color-text-primary);
|
||||
min-width: 0;
|
||||
}
|
||||
.top-risk__score {
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: var(--font-weight-bold);
|
||||
font-variant-numeric: tabular-nums;
|
||||
padding: 4px 10px;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--color-bg-soft);
|
||||
color: var(--color-text-primary);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.top-risk[data-severity="critical"] .top-risk__score { background: var(--color-severity-critical-soft); color: var(--color-severity-critical-on); }
|
||||
.top-risk[data-severity="high"] .top-risk__score { background: var(--color-severity-high-soft); color: var(--color-severity-high-on); }
|
||||
.top-risk[data-severity="medium"] .top-risk__score { background: var(--color-severity-medium-soft); color: var(--color-severity-medium-on); }
|
||||
.top-risk[data-severity="low"] .top-risk__score { background: var(--color-severity-low-soft); color: var(--color-severity-low-on); }
|
||||
|
||||
/* =========================================================================
|
||||
19. Recommendation-card (.recommendation-card)
|
||||
Emphasized advisory callout. Severity-tinted background + bold label.
|
||||
Used by security/ROS recommendations and architecture-review next-actions.
|
||||
========================================================================= */
|
||||
.recommendation-card {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: var(--space-3);
|
||||
align-items: start;
|
||||
padding: var(--space-4) var(--space-5);
|
||||
background: var(--color-bg-soft);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-left: 4px solid var(--color-state-info);
|
||||
border-radius: var(--radius-md);
|
||||
margin-block: var(--space-3);
|
||||
}
|
||||
.recommendation-card__label {
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: 11px;
|
||||
font-weight: var(--font-weight-bold);
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
padding: 4px 10px;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--color-state-info);
|
||||
color: #fff;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.recommendation-card__body {
|
||||
font-size: var(--font-size-md);
|
||||
line-height: 1.55;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
.recommendation-card[data-severity="critical"] { border-left-color: var(--color-severity-critical); }
|
||||
.recommendation-card[data-severity="critical"] .recommendation-card__label { background: var(--color-severity-critical); }
|
||||
.recommendation-card[data-severity="high"] { border-left-color: var(--color-severity-high); }
|
||||
.recommendation-card[data-severity="high"] .recommendation-card__label { background: var(--color-severity-high); }
|
||||
.recommendation-card[data-severity="medium"] { border-left-color: var(--color-severity-medium); }
|
||||
.recommendation-card[data-severity="medium"] .recommendation-card__label { background: var(--color-severity-medium); color: var(--color-severity-medium-on); }
|
||||
.recommendation-card[data-severity="low"] { border-left-color: var(--color-severity-low); }
|
||||
.recommendation-card[data-severity="low"] .recommendation-card__label { background: var(--color-severity-low); }
|
||||
.recommendation-card[data-severity="positive"] { border-left-color: var(--color-state-success); }
|
||||
.recommendation-card[data-severity="positive"] .recommendation-card__label { background: var(--color-state-success); }
|
||||
|
||||
/* =========================================================================
|
||||
20. Card subcomponents (.card__*)
|
||||
Composable subcomponents extending the existing .card primitive (base.css).
|
||||
Use as: <article class="card"><div class="card__head">...</div>...</article>
|
||||
========================================================================= */
|
||||
.card__head {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-3);
|
||||
margin-bottom: var(--space-2);
|
||||
}
|
||||
.card__title {
|
||||
font-family: var(--font-family-sans);
|
||||
font-size: var(--font-size-lg);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
letter-spacing: -0.01em;
|
||||
color: var(--color-text-primary);
|
||||
margin: 0;
|
||||
line-height: 1.3;
|
||||
}
|
||||
.card__desc {
|
||||
font-size: var(--font-size-sm);
|
||||
line-height: 1.5;
|
||||
color: var(--color-text-secondary);
|
||||
margin: 0 0 var(--space-2);
|
||||
}
|
||||
.card__id {
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: 12px;
|
||||
color: var(--color-text-tertiary);
|
||||
background: var(--color-surface-sunken);
|
||||
padding: 2px 8px;
|
||||
border-radius: var(--radius-sm);
|
||||
display: inline-block;
|
||||
}
|
||||
.card__meta {
|
||||
display: flex;
|
||||
gap: var(--space-2);
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
font-size: 12px;
|
||||
color: var(--color-text-tertiary);
|
||||
margin-top: var(--space-2);
|
||||
}
|
||||
.card__hint {
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: 12px;
|
||||
color: var(--color-text-tertiary);
|
||||
margin-top: var(--space-1);
|
||||
}
|
||||
.card__actions {
|
||||
display: flex;
|
||||
gap: var(--space-2);
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
margin-top: var(--space-3);
|
||||
}
|
||||
.card__pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 2px 8px;
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: 11px;
|
||||
font-weight: var(--font-weight-semibold);
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
background: var(--color-surface-sunken);
|
||||
color: var(--color-text-secondary);
|
||||
border-radius: 999px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Severity left-border modifier on cards */
|
||||
.card--severity-critical { border-left: 4px solid var(--color-severity-critical); }
|
||||
.card--severity-high { border-left: 4px solid var(--color-severity-high); }
|
||||
.card--severity-medium { border-left: 4px solid var(--color-severity-medium); }
|
||||
.card--severity-low { border-left: 4px solid var(--color-severity-low); }
|
||||
.card--severity-positive { border-left: 4px solid var(--color-state-success); }
|
||||
.card--severity-info { border-left: 4px solid var(--color-state-info); }
|
||||
|
||||
/* =========================================================================
|
||||
21. Form patterns (.field-row / .field-label / .field-help / etc)
|
||||
Standard form-field building blocks. Mirrors Aksel/Digdir conventions.
|
||||
========================================================================= */
|
||||
.field-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
.field-row + .field-row { margin-top: var(--space-3); }
|
||||
.field-label {
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
.field-help {
|
||||
font-size: var(--font-size-xs);
|
||||
color: var(--color-text-tertiary);
|
||||
}
|
||||
.required-mark {
|
||||
color: var(--color-severity-critical);
|
||||
margin-left: 2px;
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
.multi-select {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.checkbox-row {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
cursor: pointer;
|
||||
font-size: var(--font-size-sm);
|
||||
padding: 4px 0;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
.checkbox-row input { margin: 0; }
|
||||
.checkbox-row:hover { color: var(--color-text-link); }
|
||||
|
||||
/* =========================================================================
|
||||
22. Section-spacing utility (.stack-lg / .stack-md / .stack-sm)
|
||||
Consistent vertical rhythm between major sections.
|
||||
========================================================================= */
|
||||
.stack-lg > * + * { margin-top: var(--space-8); }
|
||||
.stack-md > * + * { margin-top: var(--space-5); }
|
||||
.stack-sm > * + * { margin-top: var(--space-3); }
|
||||
|
||||
/* =========================================================================
|
||||
23. Pyramide-tier-detail (.pyramide-tier-detail)
|
||||
Expandable details below a .pyramide visualization. Used by AI Act
|
||||
classification renderer to describe each tier's obligations.
|
||||
========================================================================= */
|
||||
.pyramide-tier-detail {
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: var(--radius-md);
|
||||
padding: var(--space-3) var(--space-4);
|
||||
margin-top: var(--space-2);
|
||||
}
|
||||
.pyramide-tier-detail summary {
|
||||
cursor: pointer;
|
||||
font-family: var(--font-family-sans);
|
||||
font-size: var(--font-size-md);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
color: var(--color-text-primary);
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
.pyramide-tier-detail summary::-webkit-details-marker { display: none; }
|
||||
.pyramide-tier-detail summary::before {
|
||||
content: "\25B8";
|
||||
font-size: 11px;
|
||||
color: var(--color-text-tertiary);
|
||||
transition: transform var(--duration-fast);
|
||||
display: inline-block;
|
||||
}
|
||||
.pyramide-tier-detail[open] summary::before { transform: rotate(90deg); }
|
||||
.pyramide-tier-detail__body {
|
||||
font-size: var(--font-size-sm);
|
||||
line-height: 1.55;
|
||||
color: var(--color-text-secondary);
|
||||
margin-top: var(--space-2);
|
||||
padding-left: var(--space-3);
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
24. Scenario-card-grid (.scenario-card-grid / .scenario-card)
|
||||
Grid of scenario/option cards used by license, compare renderers.
|
||||
Each card: header (title + count) -> optional source line -> optional body.
|
||||
========================================================================= */
|
||||
.scenario-card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
gap: var(--space-3);
|
||||
margin-block: var(--space-3);
|
||||
}
|
||||
.scenario-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-2);
|
||||
padding: var(--space-4);
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: var(--radius-md);
|
||||
transition: border-color var(--duration-fast), box-shadow var(--duration-fast);
|
||||
}
|
||||
.scenario-card:hover { border-color: var(--color-border-moderate); box-shadow: var(--shadow-sm); }
|
||||
.scenario-card__head {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
.scenario-card__title {
|
||||
font-family: var(--font-family-sans);
|
||||
font-size: var(--font-size-md);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
color: var(--color-text-primary);
|
||||
margin: 0;
|
||||
line-height: 1.3;
|
||||
}
|
||||
.scenario-card__count {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 24px;
|
||||
padding: 2px 8px;
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: 11px;
|
||||
font-weight: var(--font-weight-bold);
|
||||
background: var(--color-bg-soft);
|
||||
color: var(--color-text-secondary);
|
||||
border-radius: 999px;
|
||||
}
|
||||
.scenario-card__source {
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: 12px;
|
||||
color: var(--color-text-tertiary);
|
||||
}
|
||||
.scenario-card[data-status="winner"] {
|
||||
border-color: var(--color-state-success);
|
||||
background: var(--color-severity-low-soft);
|
||||
}
|
||||
.scenario-card[data-status="winner"] .scenario-card__count {
|
||||
background: var(--color-state-success);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
25. App-shell utility (.app-shell)
|
||||
Centered max-width page wrapper. Hoisted from playgrounds - every plugin
|
||||
playground uses the same shell pattern.
|
||||
========================================================================= */
|
||||
.app-shell {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: var(--space-6) var(--space-5);
|
||||
}
|
||||
.app-shell--wide { max-width: 1400px; }
|
||||
.app-shell--narrow { max-width: 880px; }
|
||||
|
|
|
|||