feat(ms-ai-architect): renderer A.1 classify adopt page-header + tier-desc

- renderAiActPyramid wrapped med renderPageShell (eyebrow KLASSIFISERING, verdict via aiact-archetype, keyStats via inferKeyStats)
- 4 details/summary-blokker under pyramide for klikk-pa-tier kort beskrivelse (active tier open by default)
- Inline CSS for pyramide-desc + scenario-card-grid + residual-pair + read-more-block (klargjor renderers A.2-A.6)
This commit is contained in:
Kjell Tore Guttormsen 2026-05-04 06:03:35 +02:00
commit 2e8cb9ed93

View file

@ -177,6 +177,39 @@
.key-stat[data-modifier="medium"] .key-stat__value { color: var(--color-severity-medium); }
.key-stat[data-modifier="low"] .key-stat__value { color: var(--color-severity-low); }
/* Renderer-batch A inlines (v1.10.0 Sesjon 3). Klasser ikke i vendor —
inline her per scope-regel (plugin standalone). Kandidat for hoisting
til shared/playground-design-system/ i Sesjon 6 visual QA. */
.pyramide-desc { margin: var(--space-4) 0 0 0; display: flex; flex-direction: column; gap: var(--space-2); }
.pyramide-desc__item { background: var(--color-bg-soft); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); }
.pyramide-desc__item summary { cursor: pointer; font-weight: var(--font-weight-semibold); color: var(--color-text-primary); }
.pyramide-desc__item[open] summary { margin-bottom: var(--space-2); }
.pyramide-desc__item p { margin: 0; font-size: var(--font-size-sm); color: var(--color-text-secondary); }
.scenario-card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--space-3); margin: 0 0 var(--space-4) 0; }
.scenario-card { background: var(--color-surface); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-md); padding: var(--space-3) var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); }
.scenario-card[data-status="met"] { border-left: 4px solid var(--color-state-success); }
.scenario-card[data-status="partial"] { border-left: 4px solid var(--color-severity-medium); }
.scenario-card[data-status="missing"] { border-left: 4px solid var(--color-severity-critical); }
.scenario-card__head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-2); }
.scenario-card__source { font-family: var(--font-family-mono); font-size: var(--font-size-xs); color: var(--color-text-tertiary); }
.scenario-card__count { font-family: var(--font-family-mono); font-size: 11px; padding: 2px 8px; background: var(--color-bg-soft); border-radius: var(--radius-pill); color: var(--color-text-secondary); border: 1px solid var(--color-border-subtle); }
.scenario-card__title { font-size: var(--font-size-md); font-weight: var(--font-weight-semibold); color: var(--color-text-primary); margin: 0; }
.residual-pair { display: grid; grid-template-columns: 1fr auto 1fr; gap: var(--space-4); align-items: center; margin: var(--space-4) 0; padding: var(--space-3); background: var(--color-bg-soft); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-md); }
.residual-pair__cell { background: var(--color-surface); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-sm); padding: var(--space-3); display: flex; flex-direction: column; gap: 4px; }
.residual-pair__cell-label { font-size: var(--font-size-xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-tertiary); font-weight: var(--font-weight-semibold); }
.residual-pair__cell-value { font-size: var(--font-size-2xl); font-weight: var(--font-weight-bold); font-variant-numeric: tabular-nums; line-height: 1; color: var(--color-text-primary); }
.residual-pair__cell-meta { font-size: var(--font-size-xs); color: var(--color-text-secondary); }
.residual-pair__arrow { font-size: var(--font-size-xl); color: var(--color-text-tertiary); justify-self: center; }
.residual-pair__cell[data-severity="low"] { border-left: 4px solid var(--color-severity-low); }
.residual-pair__cell[data-severity="medium"] { border-left: 4px solid var(--color-severity-medium); }
.residual-pair__cell[data-severity="high"] { border-left: 4px solid var(--color-severity-high); }
.residual-pair__cell[data-severity="critical"] { border-left: 4px solid var(--color-severity-critical); }
.read-more-block { margin: var(--space-2) 0; }
.read-more-block summary { cursor: pointer; color: var(--color-text-link); font-weight: var(--font-weight-medium); }
/* Tier 3 A4 — Screen-tabs (segmented). Inline her per scope-regel
(plugin standalone). Kandidat for hoisting til shared/ i Sesjon 6. */
.screen-tabs { display: flex; gap: var(--space-1); padding: 4px; background: var(--color-bg-soft); border-radius: var(--radius-md); width: fit-content; margin: 0 0 var(--space-4) 0; }
@ -2964,10 +2997,10 @@
else if (/minimal|low/.test(norm)) activeTier = 'minimal';
const tiers = [
{ id: 'forbidden', label: 'Uakseptabel risiko (Art. 5)' },
{ id: 'high', label: 'Høyrisiko (Art. 6 + Annex III)' },
{ id: 'limited', label: 'Begrenset risiko (Art. 50)' },
{ id: 'minimal', label: 'Minimal risiko' }
{ id: 'forbidden', label: 'Uakseptabel risiko (Art. 5)', desc: 'Forbudte AI-praksiser: subliminal manipulasjon, sosial scoring, manipulering av sårbare grupper, biometrisk fjernidentifisering i sanntid (med unntak).' },
{ id: 'high', label: 'Høyrisiko (Art. 6 + Annex III)', desc: 'Krever full compliance: risikostyringssystem, datakvalitet, teknisk dokumentasjon, transparens, menneskelig oversikt, robusthet og — for offentlig sektor — FRIA før idriftsettelse.' },
{ id: 'limited', label: 'Begrenset risiko (Art. 50)', desc: 'Transparenskrav: brukere skal informeres om at de samhandler med AI. Gjelder bl.a. chatboter, deepfakes og emosjonell gjenkjenning.' },
{ id: 'minimal', label: 'Minimal risiko', desc: 'Ingen særskilte krav under AI Act. Frivillige Codes of Conduct anbefales og dokumenteres som god praksis.' }
];
const tiersHtml = tiers.map(function (t) {
const active = (t.id === activeTier);
@ -2979,6 +3012,14 @@
'</div>';
}).join('');
const tierDescsHtml = '<div class="pyramide-desc">' + tiers.map(function (t) {
const open = (t.id === activeTier) ? ' open' : '';
return '<details class="pyramide-desc__item" data-tier="' + escapeAttr(t.id) + '"' + open + '>' +
'<summary>' + escapeHtml(t.label) + '</summary>' +
'<p>' + escapeHtml(t.desc) + '</p>' +
'</details>';
}).join('') + '</div>';
const obligationsHtml = (data.obligations || []).length
? '<section class="report-meta"><h4>Forpliktelser</h4><ul>' +
data.obligations.map(function (o) { return '<li>' + escapeHtml(o) + '</li>'; }).join('') +
@ -2988,7 +3029,14 @@
'<dt>Rolle</dt><dd>' + escapeHtml(data.role || '—') + '</dd>' +
(data.reasoning ? '<dt>Begrunnelse</dt><dd>' + escapeHtml(data.reasoning).slice(0, 800) + '</dd>' : '') +
'</dl></section>';
slot.innerHTML = '<div class="pyramide">' + tiersHtml + '</div>' + meta + obligationsHtml;
const body = '<div class="pyramide">' + tiersHtml + '</div>' + tierDescsHtml + meta + obligationsHtml;
slot.innerHTML = renderPageShell({
eyebrow: 'KLASSIFISERING',
title: data.title || 'EU AI Act-klassifisering',
lede: data.lede || 'Risikonivå, rolle og forpliktelser etter AI Act.',
verdict: data.verdict || inferVerdict(data, 'aiact'),
keyStats: data.keyStats || inferKeyStats(data, 'aiact')
}, body);
}
function renderRequirements(data, slot) {