# Playground Design System

A shared design system for plugin Playgrounds — visual self-service UIs that complement terminal slash-commands. Built for Norwegian public sector with WCAG 2.1 AA compliance, Aksel/Digdir-aligned aesthetics, and self-contained HTML deployment.

**Version:** 0.1 (Phase 1 — 2026-05-02)

## Provenance

This design system was generated by **[claude.ai/design](https://claude.ai/design)** (Anthropic) in a dialog-based design session driven by a comprehensive brief covering five plugins (`ms-ai-architect`, `okr`, `llm-security`, `ultraplan-local`, `config-audit`), Norwegian public-sector design conventions (Aksel/Digdir), and domain-specific visual standards (NS 5814 risk matrices, EU AI Act 4-tier pyramide, Doerr OKR scoring, NIST CSF, OWASP threat modeling).

Integration into the marketplace (file organization, path normalization, README authoring, root-doc cross-references) was performed in a separate Claude Code session. Per Anthropic Consumer Terms §4, ownership of outputs is assigned to the user; this design system is licensed MIT alongside the rest of the marketplace.

## Directory layout

```
shared/
├── playground-design-system/        # The design system (this directory)
│   ├── README.md                    # This file
│   ├── tokens.css                   # CSS custom properties (Aksel/Digdir-aligned)
│   ├── base.css                     # Reset, typography, primitives, focus, print
│   ├── components.css               # Tier 1: radar, matrix, findings-browser, critique-card, wizard, live-meter
│   ├── components-tier2.css         # Tier 2: decision-tree, traffic-lights, diff-review, treemap, distribution, command-pipeline, pyramide, pipeline-cockpit, verdict-pill+risk-meter, codepoint-reveal, small-multiples, OWASP badges
│   ├── components-tier3.css         # Tier 3 wave 1: pair-before-after, AI Act timeline, 3-track entry, FRIA rights-matrix, capability-matrix, parallel-agent-status, ErrorSummary, GuidePanel
│   ├── components-tier3-supplement.css # Tier 3 wave 2 (12): toxic-flow, fleet-overview, kanban Keep/Review/Remove, maturity-ladder, classify-and-transform, cycle-ribbon, persistent-antipattern, suppressed-signals, ExpansionCard, ReadMore, FormProgress, Aspirational-vs-Committed
│   ├── fonts.css                    # @font-face declarations for self-hosted fonts
│   ├── fonts/                       # Self-hosted woff2 + license attribution
│   │   ├── Inter-{Regular,Medium,SemiBold,Bold}.woff2
│   │   ├── JetBrainsMono-{Regular,Medium,SemiBold}.woff2
│   │   ├── SourceSerif4-{Regular,Semibold}.woff2
│   │   └── LICENSES.md              # All three are SIL OFL 1.1
│   ├── print.css                    # A4 print stylesheet with B/W severity patterns
│   └── schemas/                     # Cross-plugin JSON schemas
│       ├── finding.schema.json      # Used by llm-security, config-audit, ultraplan-review, ms-ai-review
│       ├── okr-set.schema.json      # Used by OKR plugin
│       └── ros-threat.schema.json   # Used by ms-ai-architect ROS workflow
│
└── playground-examples/             # Showcase + reference scenarios
    ├── index.html                   # System showcase (browse all components)
    ├── ros-lier-kommune.html        # Scenario A — ms-ai-architect ROS report
    ├── okr-baerum.html              # Scenario B — OKR live writer
    ├── security-direktorat.html     # Scenario C — llm-security findings review
    ├── templates.html               # Skeleton + print-template demos
    ├── tier3-preview.html           # Tier 3 wave 1 visual preview
    ├── components/                  # Tier 3 wave 2 — 12 isolated demo pages
    │   ├── sankey-toxic-flow.html
    │   ├── fleet-overview.html
    │   ├── kanban.html
    │   ├── maturity-ladder.html
    │   ├── classify-transform.html
    │   ├── cycle-ribbon.html
    │   ├── persistent-antipattern.html
    │   ├── suppressed-signals.html
    │   ├── expansion-card.html
    │   ├── read-more.html
    │   ├── form-progress.html
    │   └── aspirational-committed.html
    ├── ros-app.js                   # Scenario A interactivity
    └── ros-data.js                  # Scenario A mock data
```

## Quick start

To use the design system from a plugin's Playground:

```html
<!doctype html>
<html lang="nb" data-theme="light">
<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="../../shared/playground-design-system/tokens.css">
  <link rel="stylesheet" href="../../shared/playground-design-system/base.css">
  <link rel="stylesheet" href="../../shared/playground-design-system/components.css">
  <link rel="stylesheet" href="../../shared/playground-design-system/components-tier2.css">
  <!-- Optional: include components-tier3.css for Tier 3 wave 1 components -->
  <!-- Optional: include components-tier3-supplement.css for Tier 3 wave 2 (12 additional components) -->
  <!-- Optional: only include print.css if scenario produces a printable A4 report -->
  <link rel="stylesheet" href="../../shared/playground-design-system/print.css">
  <!-- Self-hosted fonts (no external requests) -->
  <link rel="stylesheet" href="../../shared/playground-design-system/fonts.css">
</head>
<body>
  <header class="app-header">
    <a class="app-header__brand" href="...">
      <span class="app-header__brand-mark">MS</span>
      ms-ai-architect
    </a>
    <span class="app-header__breadcrumb">/ Playground</span>
    <div class="app-header__spacer"></div>
    <button class="theme-toggle" data-theme-toggle>Mørk modus</button>
  </header>
  <!-- Your Playground content using design-system classes -->
</body>
</html>
```

The relative path `../../shared/playground-design-system/` assumes the plugin's Playground lives at `plugins/{plugin-name}/playground/index.html`. Adjust the prefix to match your plugin's structure.

## Design principles

1. **Aksel/Digdir-aligned.** Inter font, body 17px, Digdir blue `#0062BA`, semantic CSS tokens. Norwegian public sector users recognize this DNA.
2. **WCAG 2.1 AA non-negotiable.** Required by `Forskrift om universell utforming av IKT` for Norwegian public sector. Every component ships with proper focus rings, ARIA attributes, keyboard navigation, and contrast that passes deuteranopia simulators.
3. **Vanilla HTML/CSS/JS.** No React, no Tailwind, no build step. A plugin can copy a Playground HTML file to disk and it will render correctly.
4. **Self-contained per Playground.** Each plugin's `playground/*.html` should be openable offline with only the design-system CSS files alongside.
5. **Print-aware.** The `print.css` stylesheet ensures matrix cells use B/W-safe hatching patterns when printed, severity badges become outlined boxes with patterns, and interactive chrome disappears. Designed for A4 reports going to Datatilsynet, kommunestyre, statsråd.
6. **Severity is universal.** All severity-coded UI uses the same five-level ramp (low/medium/high/critical/extreme) with deuteranopia-safe hex values defined in `tokens.css`. Distinct from "state" tokens (failed/blocked/queued/running) used in pipeline contexts — never mix severity-red with failure-red.
7. **Two-spor strategy.** The system supports both non-technical decision makers (Spor 1: ms-ai-architect, OKR, llm-security) and developer power-users (Spor 2: ultraplan-local, config-audit) — same component library, different information densities.

## Token system

See `tokens.css` for full reference. Highlights:

- **Typography:** `--font-family-sans` (Inter), `--font-size-md` (17px body), `--measure` (65ch line length)
- **Primary:** `--color-primary-500` = `#0062BA` (Digdir blue), with 50/100/300/500/700/900 ramp
- **Severity:** `--color-severity-{low,medium,high,critical,extreme}` + `-soft` (background) + `-on` (foreground) variants. Deuteranopia-safe.
- **State:** `--color-state-{success,warning,failed,blocked,info,running,queued,pending,done}` — distinct from severity
- **Surface:** Warm off-white `#FBFAF7` (light), graphite `#0F1419` (dark). Theme via `[data-theme="dark"]` on `<html>` or `<body>`
- **Plugin scope:** `--color-scope-{architect,okr,security,ultraplan,config}` for visual differentiation between plugins
- **Spacing:** 4px grid, scale 1-20 (4px to 80px)
- **Radius:** `--radius-sm` (3px) / `-md` (5px) / `-lg` (8px) / `-pill` (999px) — max 8px (no consumer-app rounded corners)
- **Motion:** Respects `prefers-reduced-motion`

## Component reference

### Tier 1 (`components.css`)

| Component | Class prefix | Used by |
|---|---|---|
| Radar / Spider chart | `.radar` | OKR maturity (7-axis), ms-ai security (6), ms-ai ROS dimensions (7), ultraplan plan-critic (7) |
| Matrix / 5×5 heatmap | `.matrix` | ms-ai ROS, DPIA, OKR coverage, security scanner, license map |
| Findings-browser | `.findings` | llm-security, ultraplan-review, config-audit, ms-ai-review |
| Critique-card | `.critique-card` | llm-security findings, ultraplan, config-audit feature-gap, OKR antipatterns |
| Wizard / Stepper | `.stepper`, `.wizard__panel` | ms-ai 5-step intake, security clean, config-audit audit, ultraplan, OKR onboarding |
| Live-meter | `.live-meter`, `.lint-annotation` | OKR writer, ultraplan brief-reviewer, cost, config-audit |

Plus app-shell primitives: `.app-header`, `.sidepanel`, `.scrim`, `.theme-toggle`.

### Tier 3 (`components-tier3.css`)

Critical components for ms-ai-architect Playground v3 plus universal Aksel patterns. Authored 2026-05-02 in Claude Code (not via claude.ai/design — visual coherence verified against Tier 1+2 in `playground-examples/tier3-preview.html`).

| Component | Class prefix | Used by |
|---|---|---|
| Inherent + residual pair | `.pair-before-after` | ms-ai ROS before/after, DPIA, AI Act mitigations, OKR check-ins |
| AI Act compliance-tidslinje | `.aiact-timeline`, `.aiact-countdown` | ms-ai-architect classify flow + dashboard |
| 3-track entry | `.tracks` | All plugins — entry-level UX choice (Guide/Explore/Expert) |
| FRIA rights-matrix | `.rights-matrix` | ms-ai-architect FRIA (Art. 27, 12 EU Charter rights × impact) |
| Capability-matrix | `.capability-matrix` | ms-ai-architect license × kapabilitet mapping |
| Parallel-agent-status | `.agent-grid`, `.agent-card` | ms-ai utredning multi-worker, ultraplan multi-wave execute |
| ErrorSummary | `.error-summary` | All plugins — Aksel/GOV.UK form-validation pattern |
| GuidePanel | `.guide-panel` | All plugins — Aksel friendly inline guidance with optional CTA |

### Tier 2 (`components-tier2.css`)

| Component | Class prefix | Used by |
|---|---|---|
| Decision-tree | `.decision-tree`, `.dt-node`, `.dt-edge` | ms-ai AI Act 4-step classifier, security MAESTRO drill |
| Traffic-lights | `.traffic-light` | ms-ai compliance, OKR KR-status, security pre-deploy, config-audit risk |
| Diff-review | `.diff` | security diff, config-audit drift, ultraplan triage |
| Treemap | `.treemap` | config-audit token-hotspots |
| Distribution / range-viz | `.distribution` | ms-ai cost P10/P50/P90, security risk-score, OKR progress |
| Command-pipeline | `.cmd-pipeline`, `.cmd-step` | All plugins — final export of slash-command sequence |
| Pyramide (4-tier) | `.pyramide` | ms-ai AI Act risk classification |
| Pipeline-cockpit | `.pipeline-cockpit`, `.pc-stage` | ultraplan 6-stage flow, ms-ai utredning, config-audit audit |
| Verdict-pill + risk-meter | `.verdict-pill-lg`, `.risk-meter` | llm-security BLOCK/WARNING/ALLOW + 0-100 risk-score |
| Codepoint-reveal | `.codepoint-reveal` | llm-security Unicode steganography demo |
| Small-multiples grid | `.small-multiples`, `.sm-card` | llm-security 16-category posture (alternative to overcrowded radar) |
| OWASP badges | `.badge--owasp-{llm,asi,ast,mcp}` | llm-security finding cross-mapping (4 frameworks) |

## Schemas

`schemas/` contains JSON schemas for cross-plugin data interchange:

- **`finding.schema.json`** — universal "finding" shape (id, title, severity, source, evidence, rationale, recommendation, status). Consumed by llm-security, config-audit, ultraplan-review, ms-ai-review. Maps directly to the `.critique-card` component.
- **`okr-set.schema.json`** — OKR shape (objectives + key results, scoring, antipattern annotations). Consumed by OKR plugin.
- **`ros-threat.schema.json`** — ROS threat shape (likelihood × consequence, mitigation references, residual risk). Consumed by ms-ai-architect.

A plugin command can output JSON conforming to these schemas, and a Playground can render the result without further translation.

## Theming

Default is light. Toggle dark via `data-theme="dark"` attribute on `<html>` or `<body>`. The system also respects `prefers-color-scheme: dark` when no explicit theme is set:

```js
// Toggle dark/light
document.documentElement.dataset.theme =
  document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark';
localStorage.setItem('theme', document.documentElement.dataset.theme);
```

## Print mode

Include `print.css` if your scenario produces an A4 report. Then add `class="no-print"` to interactive chrome (header, buttons, theme toggle), and use `class="page-break"` to force page breaks. Severity-coded matrix cells will automatically render as B/W-safe hatching patterns when printed. The `.print-header` and `.print-footer` blocks support kommune-logo slots and signature lines for offentlige dokumenter.

## Known limitations

1. **No JavaScript framework.** Components are CSS-first. Interactivity (e.g. `aria-selected` toggling, sidepanel open/close, live-meter updates) must be wired by each Playground using vanilla JS. See `playground-examples/ros-app.js` for a reference implementation pattern.
2. **No icon set bundled.** The system assumes Lucide or Phosphor SVG sprites are inlined per Playground. Iconography is intentionally out-of-system to keep the shared system small.
3. **Mobile responsiveness is partial.** The 5×5 matrix, findings-browser, codepoint-reveal split-pane, and small-multiples grid have explicit `@media (max-width: ...)` rules. Other components may need polish for narrow viewports.

## Self-hosted fonts

All three font families (Inter, JetBrains Mono, Source Serif 4) are bundled as woff2 in `fonts/` and loaded via `fonts.css`. No external requests to Google Fonts or any CDN. All three are SIL OFL 1.1 — see `fonts/LICENSES.md` for full attribution.

## Versioning

This system follows semver:

- **Major:** Breaking token rename, component class rename, schema field removal/rename
- **Minor:** New tokens, new components, new schema fields, new variants
- **Patch:** Bugfixes, accessibility improvements, visual polish without contract changes

Every plugin Playground that consumes the design system should declare the version in a comment at the top of its HTML:

```html
<!-- playground-design-system v0.1 -->
```

## License

MIT, same as the parent ktg-plugin-marketplace. Reuse freely; attribution appreciated.

## Contributing

This is a solo project. PRs are not accepted, but issues and suggestions are welcome at the marketplace repo (Forgejo: `git.fromaitochitta.com/open/ktg-plugin-marketplace`).

When adding a new component:

1. Add CSS to `components.css` (Tier 1) or `components-tier2.css` (Tier 2)
2. Use BEM naming convention: `.component-name__element--modifier`
3. Reference only `tokens.css` custom properties — never hard-code colors, spacing, or fonts
4. Test in light + dark themes, with deuteranopia simulator (Stark, Sim Daltonism)
5. Test keyboard navigation and screen reader (NVDA on Windows, VoiceOver on Mac)
6. Add a print rule if the component appears in printable reports
7. Document in this README under the appropriate Tier table
