ktg-plugin-marketplace/shared/playground-examples/tier3-preview.html
Kjell Tore Guttormsen f1fecf39b8 feat(shared): Tier 3 wave 2 (12 components) + self-hosted fonts
Two changes in one commit because they were prepared together and the
component demos depend on the new self-hosted fonts.css.

Tier 3 wave 2 — 12 new components
---------------------------------
Adds components-tier3-supplement.css (886 lines) and 12 isolated demo
HTML pages under shared/playground-examples/components/:
toxic-flow chain, fleet-overview, kanban Keep/Review/Remove,
maturity-ladder, classify-and-transform, cycle-ribbon,
persistent-antipattern, suppressed-signals, ExpansionCard, ReadMore,
FormProgress, Aspirational-vs-Committed.

Reuses existing tokens — no new CSS custom properties. Honors the
Phase 1 feedback rules: no large pink areas for body text, severity-red
distinct from failure-red, dark mode via existing [data-theme="dark"].

Provenance: components-tier3-supplement.css and the 12 demo bodies were
authored by claude.ai/design (separate Anthropic instance) on 2026-05-03.
This commit only integrates them — path rewrites, font swap, generic
name substitution in fleet-overview demo data, README updates.
base.css from the export was deliberately NOT taken in because it
reverted the inline-message contrast fix from v0.1.

Self-hosted fonts (Inter, JetBrains Mono, Source Serif 4)
---------------------------------------------------------
Replaces all fonts.googleapis.com / fonts.gstatic.com requests with
.woff2 files bundled at shared/playground-design-system/fonts/.

Why:
- No data leaked to Google about end-user IPs and User-Agents.
- GDPR-safe for Norwegian public-sector deployments.
- Works offline / behind air-gapped firewalls.
- Forkers downloading the marketplace get a complete bundle.

All three families are SIL Open Font License 1.1 — license texts
included alongside the woff2 files. Source Serif 4 woff2 generated
locally from the upstream OTF release using
fonttools ttLib.woff2 compress; Inter and JetBrains Mono are
unmodified upstream webfont releases.

Total bundle: 9 woff2 files, ~940 KB. New fonts.css declares all
@font-face rules with font-display: swap. All 6 example HTMLs and 12
new component demos load it via a single relative path.

Verified
--------
- Privacy grep returns empty across plugins/ and shared/
- Google Fonts grep returns empty across shared/*.html
- Smoke test via python -m http.server: HTML + 7 stylesheets +
  Inter-Regular.woff2 all return 200

Doc updates
-----------
- shared/playground-design-system/README.md: file tree updated,
  Quick start snippet shows fonts.css link, "Self-hosted fonts"
  section added
- shared/playground-design-system/fonts/LICENSES.md: combined attribution
- README.md (root): Tier 3 wave 1+2 component list, Privacy-first bullet
- CLAUDE.md (root): tree entry expanded for new components + fonts

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 05:08:07 +02:00

500 lines
29 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="nb" data-theme="light">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tier 3 preview — Playground Design System</title>
<link rel="stylesheet" href="../playground-design-system/tokens.css">
<link rel="stylesheet" href="../playground-design-system/base.css">
<link rel="stylesheet" href="../playground-design-system/components.css">
<link rel="stylesheet" href="../playground-design-system/components-tier2.css">
<link rel="stylesheet" href="../playground-design-system/components-tier3.css">
<link rel="stylesheet" href="../playground-design-system/fonts.css">
<style>
.preview-section {
padding: var(--space-10) 0;
border-bottom: 1px solid var(--color-border-subtle);
}
.preview-section:last-child { border-bottom: none; }
.preview-section__heading {
display: flex;
align-items: baseline;
gap: var(--space-3);
margin-bottom: var(--space-2);
}
.preview-section__num {
font-family: var(--font-family-mono);
font-size: var(--font-size-sm);
color: var(--color-text-tertiary);
font-weight: var(--font-weight-semibold);
min-width: 32px;
}
.preview-section__intro {
max-width: 60ch;
color: var(--color-text-secondary);
margin-bottom: var(--space-6);
}
.preview-section__demo {
padding: var(--space-6);
background: var(--color-surface);
border: 1px solid var(--color-border-subtle);
border-radius: var(--radius-lg);
}
</style>
</head>
<body>
<header class="app-header">
<a class="app-header__brand" href="index.html">
<span class="app-header__brand-mark">PG</span>
Playground Design System
</a>
<span class="app-header__breadcrumb">/ Tier 3 preview</span>
<div class="app-header__spacer"></div>
<button class="theme-toggle" id="themeToggle" type="button">Mørk modus</button>
<a href="index.html" class="btn btn--ghost btn--sm">← Til oversikt</a>
</header>
<main class="container container--wide">
<div style="padding: var(--space-8) 0 var(--space-4);">
<h1>Tier 3 — Critical components</h1>
<p class="text-secondary" style="max-width: 65ch; margin-top: var(--space-3);">
8 komponenter bygd direkte for ms-ai-architect Playground v3. Hvis disse ser ut som de hører hjemme i samme familie som Tier 1 + 2, beholder vi dem og lar claude.ai/design lage de resterende 12 (sankey/toxic-flow, fleet-overview, kanban Keep/Review/Remove, maturity-ladder, classify-and-transform, cycle-ribbon, persistent-antipattern badge, suppressed-signals panel, ExpansionCard, ReadMore, FormProgress, Aspirational vs Committed visual).
</p>
</div>
<!-- 19. Pair before/after -->
<section class="preview-section">
<div class="preview-section__heading">
<span class="preview-section__num">19</span>
<h2>Inherent + residual pair</h2>
</div>
<p class="preview-section__intro">Brukes i ROS før/etter mitigering, DPIA inherent → residual, OKR check-in score over tid.</p>
<div class="preview-section__demo">
<h4 style="margin-bottom: var(--space-2);">T-001: Eksponering av personopplysninger via Copilot Chat</h4>
<div class="pair-before-after">
<div class="pair-before-after__cell pair-before-after__cell--severity-critical">
<span class="pair-before-after__cell-label">Inherent risiko</span>
<span class="pair-before-after__cell-value">20</span>
<span class="pair-before-after__cell-meta">S4 × K5 — Kritisk sone</span>
</div>
<div class="pair-before-after__arrow" aria-label="reduseres til"></div>
<div class="pair-before-after__cell pair-before-after__cell--severity-medium">
<span class="pair-before-after__cell-label">Etter M-001 + M-002</span>
<span class="pair-before-after__cell-value">8</span>
<span class="pair-before-after__cell-meta">S2 × K4 — Gul sone</span>
<span class="pair-before-after__delta pair-before-after__delta--improved">12 (60 % reduksjon)</span>
</div>
</div>
</div>
</section>
<!-- 20. AI Act timeline -->
<section class="preview-section">
<div class="preview-section__heading">
<span class="preview-section__num">20</span>
<h2>AI Act compliance-tidslinje</h2>
</div>
<p class="preview-section__intro">4 milepeler i EU AI Act med per-system countdown. Brukes i ms-ai-architect classify-flow og dashboard.</p>
<div class="preview-section__demo">
<div class="aiact-timeline">
<div class="aiact-timeline__track">
<div class="aiact-timeline__progress" style="width: 41%;"></div>
<div class="aiact-timeline__milestone" style="left: 0%;" data-state="passed">
<div class="aiact-timeline__dot"></div>
<div class="aiact-timeline__label">
<span class="aiact-timeline__label-date">2025-02-02</span>
<span class="aiact-timeline__label-name">Forbudte praksiser (Art. 5)</span>
</div>
</div>
<div class="aiact-timeline__milestone" style="left: 22%;" data-state="passed">
<div class="aiact-timeline__dot"></div>
<div class="aiact-timeline__label">
<span class="aiact-timeline__label-date">2025-08-02</span>
<span class="aiact-timeline__label-name">Governance og sanksjoner (Art. 99)</span>
</div>
</div>
<div class="aiact-timeline__today" style="left: 41%;"></div>
<div class="aiact-timeline__milestone" style="left: 60%;" data-state="active">
<div class="aiact-timeline__dot"></div>
<div class="aiact-timeline__label">
<span class="aiact-timeline__label-date">2026-08-02</span>
<span class="aiact-timeline__label-name">GPAI + Annex III høyrisiko</span>
</div>
</div>
<div class="aiact-timeline__milestone" style="left: 100%;" data-state="upcoming">
<div class="aiact-timeline__dot"></div>
<div class="aiact-timeline__label">
<span class="aiact-timeline__label-date">2027-08-02</span>
<span class="aiact-timeline__label-name">Full compliance for all høyrisiko</span>
</div>
</div>
</div>
</div>
<div style="display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-12);">
<span class="aiact-countdown" data-urgency="urgent">
<span>Kommunal Copilot-utrulling:</span>
<span class="aiact-countdown__days">92 dager</span>
<span>til Annex III-frist</span>
</span>
<span class="aiact-countdown" data-urgency="soon">
<span>Saksbehandling AI:</span>
<span class="aiact-countdown__days">457 dager</span>
<span>til full compliance</span>
</span>
<span class="aiact-countdown" data-urgency="distant">
<span>Intern HR-bot:</span>
<span class="aiact-countdown__days">457 dager</span>
<span>(begrenset risiko)</span>
</span>
</div>
</div>
</section>
<!-- 21. 3-track entry -->
<section class="preview-section">
<div class="preview-section__heading">
<span class="preview-section__num">21</span>
<h2>3-track entry</h2>
</div>
<p class="preview-section__intro">Carry-forward fra Playground v2. Den første beslutningen — bruker velger sin ferdighetsnivå-vei inn i Playground.</p>
<div class="preview-section__demo">
<div class="tracks">
<a class="tracks__card tracks__card--guided" href="#">
<div class="tracks__card-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v8M12 22v-2M4.93 4.93l5.66 5.66M19.07 19.07l-1.41-1.41M2 12h8M22 12h-2M4.93 19.07l5.66-5.66M19.07 4.93l-1.41 1.41"/></svg>
</div>
<h3 class="tracks__card-title">Guide meg</h3>
<p class="tracks__card-desc">Strukturert wizard som leder deg gjennom intake, kapabilitetsvalg og eksport. Anbefalt for første gangs bruk eller når du er usikker.</p>
<div class="tracks__card-meta">
<span>56 klikk</span>
<span class="tracks__card-cta">Start →</span>
</div>
</a>
<a class="tracks__card tracks__card--explore" href="#">
<div class="tracks__card-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
</div>
<h3 class="tracks__card-title">La meg utforske</h3>
<p class="tracks__card-desc">Bla i kapabilitetskatalogen, filtrér på lisens og dataresidens, og bygg arkitekturen din ad-hoc.</p>
<div class="tracks__card-meta">
<span>810 klikk</span>
<span class="tracks__card-cta">Bla →</span>
</div>
</a>
<a class="tracks__card tracks__card--expert" href="#">
<div class="tracks__card-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
</div>
<h3 class="tracks__card-title">Jeg vet hva jeg vil</h3>
<p class="tracks__card-desc">Hopp direkte til konfigurasjon, hent fra forrige beslutningsrekord, eller skriv inn JSON og la oss generere kommando-pipelinen.</p>
<div class="tracks__card-meta">
<span>34 klikk</span>
<span class="tracks__card-cta">Hopp inn →</span>
</div>
</a>
</div>
</div>
</section>
<!-- 22. FRIA rights-matrix -->
<section class="preview-section">
<div class="preview-section__heading">
<span class="preview-section__num">22</span>
<h2>FRIA rights-matrix</h2>
</div>
<p class="preview-section__intro">12 EU Charter-rettigheter × konsekvensnivå (05). Brukes i FRIA-vurdering (Art. 27 EU AI Act) for offentlig sektor høyrisiko-systemer.</p>
<div class="preview-section__demo">
<div class="rights-matrix">
<div class="rights-matrix__head">
<div class="rights-matrix__head-cell rights-matrix__head-cell--name">Grunnleggende rettighet (EU Charter)</div>
<div class="rights-matrix__head-cell">N/A</div>
<div class="rights-matrix__head-cell">Lav</div>
<div class="rights-matrix__head-cell">Med</div>
<div class="rights-matrix__head-cell">Høy</div>
<div class="rights-matrix__head-cell">Kritisk</div>
</div>
<div class="rights-matrix__row">
<div class="rights-matrix__name">Art. 7 — Rett til privatliv<span class="rights-matrix__name-meta">Korrespondanse, hjem, familieliv</span></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="4"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
</div>
<div class="rights-matrix__row">
<div class="rights-matrix__name">Art. 8 — Personopplysninger<span class="rights-matrix__name-meta">GDPR-forankret</span></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="5"></div>
</div>
<div class="rights-matrix__row">
<div class="rights-matrix__name">Art. 11 — Ytringsfrihet<span class="rights-matrix__name-meta">Innhentings- og spredningsfrihet</span></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="1"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
</div>
<div class="rights-matrix__row">
<div class="rights-matrix__name">Art. 21 — Diskrimineringsforbud<span class="rights-matrix__name-meta">Kjønn, etnisitet, religion, alder</span></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="5"></div>
</div>
<div class="rights-matrix__row">
<div class="rights-matrix__name">Art. 41 — God forvaltning<span class="rights-matrix__name-meta">Habilitet, begrunnelse, klagerett</span></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="3"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
</div>
<div class="rights-matrix__row">
<div class="rights-matrix__name">Art. 47 — Effektivt rettsmiddel<span class="rights-matrix__name-meta">Rett til rettferdig rettergang</span></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="2"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
<div class="rights-matrix__cell" data-impact="0"></div>
</div>
</div>
<p class="text-xs text-tertiary" style="margin-top: var(--space-3);">Demo viser 6 av 12 rettigheter. Full FRIA dekker alle relevante artikler i EU-pakten.</p>
</div>
</section>
<!-- 23. Capability-matrix -->
<section class="preview-section">
<div class="preview-section__heading">
<span class="preview-section__num">23</span>
<h2>Capability-matrix</h2>
</div>
<p class="preview-section__intro">Brukes i ms-ai-architect for å mappe kapabilitet × lisens. Statuser: tilgjengelig, koster ekstra, betinget, mangler. Aldri kun farge — ikon + farge sammen.</p>
<div class="preview-section__demo">
<div class="capability-matrix" style="grid-template-columns: 1fr;">
<div class="capability-matrix__head" style="grid-template-columns: 2fr 1fr 1fr 1fr 1fr;">
<div class="capability-matrix__head-cell capability-matrix__head-cell--name">Kapabilitet</div>
<div class="capability-matrix__head-cell">M365 E3</div>
<div class="capability-matrix__head-cell">M365 E5</div>
<div class="capability-matrix__head-cell">Copilot</div>
<div class="capability-matrix__head-cell">Power Premium</div>
</div>
<div class="capability-matrix__row" style="grid-template-columns: 2fr 1fr 1fr 1fr 1fr;">
<div class="capability-matrix__name">Generer tekst i M365 Chat</div>
<div class="capability-matrix__cell" data-status="missing"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="missing"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="available"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="missing"><i class="capability-matrix__cell-icon"></i></div>
</div>
<div class="capability-matrix__row" style="grid-template-columns: 2fr 1fr 1fr 1fr 1fr;">
<div class="capability-matrix__name">Sensitivity Labels på dokumenter</div>
<div class="capability-matrix__cell" data-status="cost"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="available"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="available"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="missing"><i class="capability-matrix__cell-icon"></i></div>
</div>
<div class="capability-matrix__row" style="grid-template-columns: 2fr 1fr 1fr 1fr 1fr;">
<div class="capability-matrix__name">DLP for endpoints</div>
<div class="capability-matrix__cell" data-status="missing"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="available"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="conditional"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="missing"><i class="capability-matrix__cell-icon"></i></div>
</div>
<div class="capability-matrix__row" style="grid-template-columns: 2fr 1fr 1fr 1fr 1fr;">
<div class="capability-matrix__name">Power Automate AI Builder-flows</div>
<div class="capability-matrix__cell" data-status="cost"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="cost"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="conditional"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="available"><i class="capability-matrix__cell-icon"></i></div>
</div>
<div class="capability-matrix__row" style="grid-template-columns: 2fr 1fr 1fr 1fr 1fr;">
<div class="capability-matrix__name">Copilot Studio agent (custom)</div>
<div class="capability-matrix__cell" data-status="missing"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="missing"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="cost"><i class="capability-matrix__cell-icon"></i></div>
<div class="capability-matrix__cell" data-status="conditional"><i class="capability-matrix__cell-icon"></i></div>
</div>
</div>
<div class="capability-matrix__legend">
<span class="capability-matrix__legend-item"><i class="capability-matrix__cell-icon" style="background: var(--color-severity-low); color: #fff;"></i> Tilgjengelig</span>
<span class="capability-matrix__legend-item"><i class="capability-matrix__cell-icon" style="background: var(--color-severity-medium); color: #fff; font-size: 10px;">kr</i> Krever tilleggslisens</span>
<span class="capability-matrix__legend-item"><i class="capability-matrix__cell-icon" style="background: var(--color-severity-high); color: #fff;">!</i> Betinget (krever konfigurasjon)</span>
<span class="capability-matrix__legend-item"><i class="capability-matrix__cell-icon" style="background: var(--color-text-tertiary); color: #fff;">×</i> Ikke tilgjengelig</span>
</div>
</div>
</section>
<!-- 24. Parallel-agent-status -->
<section class="preview-section">
<div class="preview-section__heading">
<span class="preview-section__num">24</span>
<h2>Parallel-agent-status panel</h2>
</div>
<p class="preview-section__intro">Brukes i ms-ai-architect utredning (4 parallelle workers skriver til <code>.work/</code>) og ultraplan-local multi-wave execute. Per worker: tilstand, fremdrift og siste output-utdrag.</p>
<div class="preview-section__demo">
<div class="agent-grid">
<div class="agent-card">
<div class="agent-card__head">
<div>
<h4 class="agent-card__name">security-worker</h4>
<span class="agent-card__role">6×5 sikkerhetsmatrise</span>
</div>
<span class="agent-card__state" data-state="done"><span class="agent-card__state-dot"></span>Ferdig</span>
</div>
<div class="agent-card__progress"><div class="agent-card__progress-fill" style="width: 100%;"></div></div>
<div class="agent-card__metrics">
<span class="agent-card__metric"><span>Tid:</span><span class="agent-card__metric-value">2m 14s</span></span>
<span class="agent-card__metric"><span>Funn:</span><span class="agent-card__metric-value">12</span></span>
</div>
</div>
<div class="agent-card">
<div class="agent-card__head">
<div>
<h4 class="agent-card__name">cost-worker</h4>
<span class="agent-card__role">P10/P50/P90 NOK-estimat</span>
</div>
<span class="agent-card__state" data-state="running"><span class="agent-card__state-dot"></span>Kjører</span>
</div>
<div class="agent-card__progress"><div class="agent-card__progress-fill" style="width: 67%;"></div></div>
<div class="agent-card__metrics">
<span class="agent-card__metric"><span>Tid:</span><span class="agent-card__metric-value">1m 32s</span></span>
<span class="agent-card__metric"><span>SKU-er:</span><span class="agent-card__metric-value">8 / 12</span></span>
</div>
</div>
<div class="agent-card">
<div class="agent-card__head">
<div>
<h4 class="agent-card__name">dpia-worker</h4>
<span class="agent-card__role">GDPR Art. 35-vurdering</span>
</div>
<span class="agent-card__state" data-state="running"><span class="agent-card__state-dot"></span>Kjører</span>
</div>
<div class="agent-card__progress"><div class="agent-card__progress-fill" style="width: 23%;"></div></div>
<div class="agent-card__metrics">
<span class="agent-card__metric"><span>Tid:</span><span class="agent-card__metric-value">42s</span></span>
<span class="agent-card__metric"><span>Risiko:</span><span class="agent-card__metric-value">2 / 10</span></span>
</div>
</div>
<div class="agent-card">
<div class="agent-card__head">
<div>
<h4 class="agent-card__name">diagram-worker</h4>
<span class="agent-card__role">Imagen 3 / Mermaid fallback</span>
</div>
<span class="agent-card__state" data-state="failed"><span class="agent-card__state-dot"></span>Feilet</span>
</div>
<div class="agent-card__progress"><div class="agent-card__progress-fill" style="width: 100%; background: var(--color-state-failed);"></div></div>
<div class="agent-card__metrics">
<span class="agent-card__metric"><span>Feil:</span><span class="agent-card__metric-value" style="color: var(--color-state-failed);">MCP timeout</span></span>
</div>
</div>
</div>
</div>
</section>
<!-- 25. ErrorSummary -->
<section class="preview-section">
<div class="preview-section__heading">
<span class="preview-section__num">25</span>
<h2>ErrorSummary (Aksel/GOV.UK)</h2>
</div>
<p class="preview-section__intro">Konsentrert valideringsfeil-liste øverst i lange skjemaer. Hver feil har anker-link til feltet. Skjermlesere leser hele listen først — kritisk for tilgjengelig skjema-UX.</p>
<div class="preview-section__demo">
<div class="error-summary" role="alert" aria-labelledby="es-heading">
<h3 class="error-summary__heading" id="es-heading">Det er 4 feil i ROS-skjemaet</h3>
<p class="error-summary__body">Rett opp feilene før du fortsetter. Hver feil lenker til feltet.</p>
<ul class="error-summary__list">
<li class="error-summary__item"><a class="error-summary__link" href="#field-system">System-navn må fylles ut</a></li>
<li class="error-summary__item"><a class="error-summary__link" href="#field-residency">Dataresidens er påkrevd for offentlig sektor (velg EU eller Norway East)</a></li>
<li class="error-summary__item"><a class="error-summary__link" href="#field-threats">Minst 5 trusler må plasseres i matrisen før du kan generere rapport</a></li>
<li class="error-summary__item"><a class="error-summary__link" href="#field-owner">Behandlingsansvarlig må navngis (rolle eller person)</a></li>
</ul>
</div>
</div>
</section>
<!-- 26. GuidePanel -->
<section class="preview-section">
<div class="preview-section__heading">
<span class="preview-section__num">26</span>
<h2>GuidePanel (Aksel)</h2>
</div>
<p class="preview-section__intro">Vennlig inline-veiledning for første-gangs-brukere. Skala av hjelp uten å være skoleflink.</p>
<div class="preview-section__demo stack">
<div class="guide-panel guide-panel--info">
<div class="guide-panel__icon" aria-hidden="true">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/></svg>
</div>
<div class="guide-panel__body">
<h4 class="guide-panel__title">Første gang du gjør en ROS for AI?</h4>
<p class="guide-panel__text">Vi følger NS 5814:2021 og bruker "evalueringskriterier" (ikke "akseptkriterier"). De 49 forhåndsdefinerte truslene er hentet fra EU AI Act Annex III og NSM grunnprinsipper for IKT-sikkerhet.</p>
</div>
<a href="#" class="btn btn--secondary btn--sm guide-panel__action">Les metodikk</a>
</div>
<div class="guide-panel guide-panel--success">
<div class="guide-panel__icon" aria-hidden="true">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
</div>
<div class="guide-panel__body">
<h4 class="guide-panel__title">Onboarding fullført</h4>
<p class="guide-panel__text">Profilen din er lagret i <code>org/profile.md</code>. Alle agenter (security, cost, dpia, diagram) leser denne automatisk — du slipper å skrive om virksomheten på nytt.</p>
</div>
</div>
<div class="guide-panel guide-panel--warn">
<div class="guide-panel__icon" aria-hidden="true">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
</div>
<div class="guide-panel__body">
<h4 class="guide-panel__title">Schrems II-flagging</h4>
<p class="guide-panel__text">Du har valgt en region som ikke er EU/EØS. For offentlig sektor i Norge krever dette rettslig vurdering av overføringsmekanismen (SCCs + supplementary measures eller Microsoft EU Data Boundary).</p>
</div>
<a href="#" class="btn btn--secondary btn--sm guide-panel__action">Vis vurderingsmal</a>
</div>
</div>
</section>
<div style="padding: var(--space-12) 0; text-align: center; color: var(--color-text-tertiary); font-size: var(--font-size-sm);">
<p>Hvis disse 8 ser ut som de hører til familien: behold dem. Hvis ikke: scrap og kjør alle 20 i claude.ai/design.</p>
<p style="margin-top: var(--space-2);"><a href="index.html">← Til hovedoversikt</a></p>
</div>
</main>
<script>
const themeToggle = document.getElementById('themeToggle');
const root = document.documentElement;
const saved = localStorage.getItem('pgds-theme') || 'light';
root.dataset.theme = saved;
themeToggle.textContent = saved === 'dark' ? 'Lys modus' : 'Mørk modus';
themeToggle.addEventListener('click', () => {
const next = root.dataset.theme === 'dark' ? 'light' : 'dark';
root.dataset.theme = next;
localStorage.setItem('pgds-theme', next);
themeToggle.textContent = next === 'dark' ? 'Lys modus' : 'Mørk modus';
});
</script>
</body>
</html>