Assessor_2.0/.claude/skills/assessor-ui/assets/components.css

722 lines
25 KiB
CSS

/* ==========================================================================
ASSESSOR Komponenten-Referenz
--------------------------------------------------------------------------
Verbindliche Implementierung. Diese Datei wird erweitert, nicht ueberschrieben.
Keine Regel ausserhalb der Layer. Kein !important. Keine Seitenselektoren
(kein `.page-datahub .btn { ... }`).
Layer-Reihenfolge zwingend:
@layer tokens, base, shell, components, utilities;
========================================================================== */
@layer components {
/* ==========================================================================
1. BUTTONS
Hierarchie: pro Ansicht genau EIN Primary. Alles andere Secondary/Ghost.
Destructive nur fuer irreversible Datenaktionen.
========================================================================== */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--space-2);
height: var(--control-h);
padding: 0 var(--space-3);
border: var(--bw-hairline) solid transparent;
border-radius: var(--radius-sm);
font: var(--fw-medium) var(--fs-base) / 1 var(--font-ui);
white-space: nowrap;
cursor: pointer;
transition: background-color var(--dur-fast) var(--ease),
border-color var(--dur-fast) var(--ease);
}
.btn:focus-visible {
outline: var(--bw-emphasis) solid var(--focus-ring);
outline-offset: 1px;
}
.btn[disabled] {
color: var(--text-disabled);
background: var(--surface-panel);
border-color: var(--border-subtle);
cursor: not-allowed;
}
.btn--primary {
background: var(--accent);
color: var(--accent-on);
border-color: var(--accent);
}
.btn--primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn--primary:active { background: var(--accent-active); border-color: var(--accent-active); }
.btn--secondary {
background: var(--surface-panel-raised);
color: var(--text-primary);
border-color: var(--border-default);
}
.btn--secondary:hover { background: var(--surface-hover); border-color: var(--border-strong); }
.btn--secondary:active { background: var(--surface-active); }
.btn--ghost {
background: transparent;
color: var(--text-secondary);
border-color: transparent;
}
.btn--ghost:hover { background: var(--surface-hover); color: var(--text-primary); }
.btn--destructive {
background: transparent;
color: var(--sev-critical);
border-color: var(--sev-critical);
}
.btn--destructive:hover { background: var(--sev-critical); color: var(--sev-on); }
.btn--sm { height: var(--control-h-sm); padding: 0 var(--space-2); font-size: var(--fs-sm); }
/* Icon-Button: quadratisch, nur Icon, immer mit aria-label */
.icon-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: var(--icon-btn);
height: var(--icon-btn);
padding: 0;
background: transparent;
color: var(--text-secondary);
border: var(--bw-hairline) solid transparent;
border-radius: var(--radius-sm);
cursor: pointer;
}
.icon-btn:hover { background: var(--surface-hover); color: var(--text-primary); border-color: var(--border-default); }
.icon-btn:focus-visible { outline: var(--bw-emphasis) solid var(--focus-ring); outline-offset: 1px; }
.icon-btn[aria-pressed="true"] { background: var(--surface-selected); color: var(--text-primary); border-color: var(--accent); }
/* ==========================================================================
2. EINGABEN
========================================================================== */
.field {
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.field__label {
font: var(--fw-medium) var(--fs-micro) / 1.2 var(--font-ui);
letter-spacing: var(--ls-caps);
text-transform: uppercase;
color: var(--text-muted);
}
.input,
.select,
.textarea {
width: 100%;
height: var(--control-h);
padding: 0 var(--space-2);
background: var(--surface-input);
color: var(--text-primary);
border: var(--bw-hairline) solid var(--border-default);
border-radius: var(--radius-sm);
font: var(--fw-regular) var(--fs-base) / 1 var(--font-ui);
}
.textarea {
height: auto;
min-height: calc(var(--control-h) * 2);
max-height: calc(var(--control-h) * 4);
padding: var(--space-2);
line-height: var(--lh-ui);
resize: vertical;
}
.input::placeholder,
.textarea::placeholder { color: var(--text-muted); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--border-strong); }
.input:focus-visible,
.select:focus-visible,
.textarea:focus-visible {
border-color: var(--accent);
outline: var(--bw-emphasis) solid var(--focus-ring);
outline-offset: -1px;
}
.input[aria-invalid="true"] { border-color: var(--sev-critical); }
/* Technische Werte: DN, Timestamps, Hashes, IDs, Scores */
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
/* Segmented Control: 2 bis 5 sich ausschliessende Optionen */
.segmented {
display: inline-flex;
padding: 2px;
background: var(--surface-input);
border: var(--bw-hairline) solid var(--border-default);
border-radius: var(--radius-sm);
}
.segmented__item {
height: calc(var(--control-h) - 6px);
padding: 0 var(--space-3);
background: transparent;
color: var(--text-secondary);
border: 0;
border-radius: var(--radius-xs);
font: var(--fw-medium) var(--fs-sm) / 1 var(--font-ui);
cursor: pointer;
}
.segmented__item[aria-selected="true"] {
background: var(--accent);
color: var(--accent-on);
}
.segmented__item:focus-visible { outline: var(--bw-emphasis) solid var(--focus-ring); outline-offset: 1px; }
/* ==========================================================================
3. COMMAND BAND
Signaturelement. Enthaelt Filter- und Scope-Controls.
Regel: ALLE Controls im Band tragen die Band-Optik. Kein Mischbetrieb.
========================================================================== */
.band {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--space-2);
min-height: var(--band-row-h);
padding: var(--space-1) var(--space-3);
background: var(--surface-app);
border-bottom: var(--bw-hairline) solid var(--border-subtle);
}
.band__control {
height: calc(var(--band-row-h) - 8px);
padding: 0 var(--space-2);
background: var(--band-surface);
color: var(--band-text);
border: var(--bw-hairline) solid var(--band-border);
border-radius: var(--radius-sm);
font: var(--fw-medium) var(--fs-sm) / 1 var(--font-ui);
cursor: pointer;
}
.band__control:hover { background: var(--band-surface-hover); }
.band__control:focus-visible { outline: var(--bw-emphasis) solid var(--focus-ring); outline-offset: 1px; }
/* Freitextfilter: neutral, damit die Bandfarbe nicht als Eingabeaufforderung wirkt */
.band__search {
flex: 1 1 240px;
height: calc(var(--band-row-h) - 8px);
padding: 0 var(--space-2);
background: var(--surface-input);
color: var(--text-primary);
border: var(--bw-hairline) solid var(--border-default);
border-radius: var(--radius-sm);
font: var(--fw-regular) var(--fs-sm) / 1 var(--font-ui);
}
/* Aktiver Filter mit Treffermenge */
.band__control[data-active="true"]::after {
content: " \00B7 " attr(data-count);
font-variant-numeric: tabular-nums;
}
/* ==========================================================================
4. ZUSTANDSDARSTELLUNG
Drei formal unterscheidbare Familien. Form traegt Bedeutung, nicht nur Farbe.
========================================================================== */
/* 4.1 Severity: gefuellt, rechteckig, Versalien. Nur hier gefuellte Farbe. */
.sev {
display: inline-flex;
align-items: center;
height: 18px;
padding: 0 6px;
background: var(--sev-unknown);
color: var(--sev-on);
border-radius: var(--radius-xs);
font: var(--fw-semibold) var(--fs-micro) / 1 var(--font-ui);
letter-spacing: var(--ls-caps);
text-transform: uppercase;
}
.sev[data-sev="critical"] { background: var(--sev-critical); }
.sev[data-sev="high"] { background: var(--sev-high); }
.sev[data-sev="medium"] { background: var(--sev-medium); }
.sev[data-sev="low"] { background: var(--sev-low); }
.sev[data-sev="info"] { background: var(--sev-info); }
/* Severity-Kante: zweites, nicht farbabhaengiges Signal an Zeile/Tile/Card */
.sev-edge { box-shadow: inset 3px 0 0 0 var(--sev-unknown); }
.sev-edge[data-sev="critical"] { box-shadow: inset 3px 0 0 0 var(--sev-critical); }
.sev-edge[data-sev="high"] { box-shadow: inset 3px 0 0 0 var(--sev-high); }
.sev-edge[data-sev="medium"] { box-shadow: inset 3px 0 0 0 var(--sev-medium); }
.sev-edge[data-sev="low"] { box-shadow: inset 3px 0 0 0 var(--sev-low); }
.sev-edge[data-sev="info"] { box-shadow: inset 3px 0 0 0 var(--sev-info); }
/* 4.2 Meta-Badge: neutral gefuellt. Kategorie, Tool, IOE, Weight, Score, MITRE. */
.badge {
display: inline-flex;
align-items: center;
height: 18px;
padding: 0 6px;
background: var(--surface-panel-raised);
color: var(--text-secondary);
border: var(--bw-hairline) solid var(--border-default);
border-radius: var(--radius-xs);
font: var(--fw-medium) var(--fs-micro) / 1 var(--font-ui);
letter-spacing: var(--ls-caps);
text-transform: uppercase;
white-space: nowrap;
}
.badge--numeric { font-family: var(--font-mono); letter-spacing: 0; text-transform: none; }
/* 4.3 Workflow-Chip: Outline plus Punkt. Nie gefuellt. */
.chip {
display: inline-flex;
align-items: center;
gap: 6px;
height: 20px;
padding: 0 var(--space-2);
background: transparent;
color: var(--text-secondary);
border: var(--bw-hairline) solid var(--border-default);
border-radius: var(--radius-xs);
font: var(--fw-medium) var(--fs-micro) / 1 var(--font-ui);
}
.chip::before {
content: "";
width: 6px; height: 6px;
border-radius: 50%;
background: var(--state-open);
}
.chip[data-state="progress"]::before { background: var(--state-progress); }
.chip[data-state="done"]::before { background: var(--state-done); }
.chip[data-state="blocked"]::before { background: var(--state-blocked); }
.chip[data-state="accepted"] { border-style: dashed; }
.chip[data-state="accepted"]::before { background: var(--state-accepted); }
/* 4.4 Outcome: Text plus Glyph. Niemals gefuellt, niemals gruen. */
.outcome {
display: inline-flex;
align-items: center;
gap: 6px;
color: var(--outcome-idle);
font: var(--fw-medium) var(--fs-sm) / 1 var(--font-ui);
}
.outcome::before { content: "\2013"; }
.outcome[data-outcome="fail"] { color: var(--outcome-fail); }
.outcome[data-outcome="fail"]::before { content: "\25CF"; }
.outcome[data-outcome="pass"] { color: var(--outcome-pass); }
.outcome[data-outcome="pass"]::before { content: "\25CB"; }
.outcome[data-outcome="warning"] { color: var(--outcome-warning); }
.outcome[data-outcome="warning"]::before { content: "\25D0"; }
.outcome[data-outcome="execution_error"] { color: var(--outcome-error); }
.outcome[data-outcome="execution_error"]::before { content: "\2715"; }
/* 4.5 Bookmark: Iconfuellung plus rechte Kante. Getrennt von Severity. */
.is-bookmarked { box-shadow: inset -3px 0 0 0 var(--state-bookmark); }
.is-bookmarked.sev-edge[data-sev="critical"] { box-shadow: inset 3px 0 0 0 var(--sev-critical), inset -3px 0 0 0 var(--state-bookmark); }
.is-bookmarked.sev-edge[data-sev="high"] { box-shadow: inset 3px 0 0 0 var(--sev-high), inset -3px 0 0 0 var(--state-bookmark); }
.is-bookmarked.sev-edge[data-sev="medium"] { box-shadow: inset 3px 0 0 0 var(--sev-medium), inset -3px 0 0 0 var(--state-bookmark); }
.is-bookmarked.sev-edge[data-sev="low"] { box-shadow: inset 3px 0 0 0 var(--sev-low), inset -3px 0 0 0 var(--state-bookmark); }
.is-bookmarked.sev-edge[data-sev="info"] { box-shadow: inset 3px 0 0 0 var(--sev-info), inset -3px 0 0 0 var(--state-bookmark); }
/* 4.6 Datenvollstaendigkeit */
.is-incomplete { border-style: dashed; }
/* ==========================================================================
5. LISTENZEILE (Master-Liste)
========================================================================== */
.row {
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: var(--space-2);
min-height: calc(var(--row-h) * 2);
padding: var(--space-2) var(--space-3);
background: var(--surface-panel);
border: var(--bw-hairline) solid var(--border-subtle);
border-radius: var(--radius-sm);
cursor: pointer;
}
.row + .row { margin-top: var(--space-1); }
.row:hover { background: var(--surface-hover); border-color: var(--border-default); }
.row[aria-selected="true"] {
background: var(--surface-selected);
border-color: var(--selection-border);
border-width: var(--bw-emphasis);
padding: calc(var(--space-2) - 1px) calc(var(--space-3) - 1px);
}
.row:focus-visible { outline: var(--bw-emphasis) solid var(--focus-ring); outline-offset: -1px; }
.row__title {
font: var(--fw-semibold) var(--fs-md) / var(--lh-ui) var(--font-ui);
color: var(--text-primary);
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
overflow: hidden;
}
.row__meta {
margin-top: 2px;
font: var(--fw-regular) var(--fs-sm) / 1.3 var(--font-ui);
color: var(--text-secondary);
}
/* ==========================================================================
6. TILE (Kachelansicht)
Feste Hoehe. Kein ragged bottom. Aktionen ausschliesslich in der Fusszeile.
========================================================================== */
.tile-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(var(--tile-min-w), 1fr));
gap: var(--space-2);
padding: var(--space-3);
}
.tile {
display: grid;
grid-template-rows: auto 1fr auto;
height: var(--tile-h);
padding: var(--space-2) var(--space-3);
background: var(--surface-panel);
border: var(--bw-hairline) solid var(--border-subtle);
border-radius: var(--radius-sm);
cursor: pointer;
overflow: hidden;
}
.tile:hover { background: var(--surface-hover); border-color: var(--border-strong); }
.tile[aria-selected="true"] {
background: var(--surface-selected);
border-color: var(--selection-border);
border-width: var(--bw-emphasis);
padding: calc(var(--space-2) - 1px) calc(var(--space-3) - 1px);
}
.tile:focus-visible { outline: var(--bw-emphasis) solid var(--focus-ring); outline-offset: -1px; }
.tile__title {
font: var(--fw-semibold) var(--fs-md) / var(--lh-ui) var(--font-ui);
color: var(--text-primary);
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
overflow: hidden;
}
.tile__badges {
display: flex; flex-wrap: nowrap; gap: var(--space-1);
align-items: center; align-self: center;
overflow: hidden;
}
.tile__footer {
display: flex; align-items: center; justify-content: space-between;
gap: var(--space-2);
padding-top: var(--space-1);
border-top: var(--bw-hairline) solid var(--border-subtle);
}
/* ==========================================================================
7. TABELLE
Kopf und Koerper teilen dieselbe Groessenklasse. Keine verschachtelten
Tabellen. Keine Tabelle in einer Karte.
========================================================================== */
.table { width: 100%; border-collapse: collapse; }
.table thead th {
position: sticky; top: 0; z-index: 1;
height: var(--row-h);
padding: 0 var(--space-2);
background: var(--surface-panel-raised);
color: var(--text-muted);
border-bottom: var(--bw-hairline) solid var(--border-default);
font: var(--fw-medium) var(--fs-micro) / 1 var(--font-ui);
letter-spacing: var(--ls-caps);
text-transform: uppercase;
text-align: left;
white-space: nowrap;
}
.table tbody td {
height: var(--row-h);
padding: 0 var(--space-2);
background: var(--surface-panel);
color: var(--text-primary);
border-bottom: var(--bw-hairline) solid var(--border-subtle);
font: var(--fw-regular) var(--fs-sm) / var(--lh-ui) var(--font-ui);
text-align: left; /* Text linksbuendig, immer */
}
.table td.is-numeric,
.table th.is-numeric { text-align: right; font-variant-numeric: tabular-nums; }
.table tbody tr:hover td { background: var(--surface-hover); }
.table tbody tr[aria-selected="true"] td {
background: var(--surface-selected);
box-shadow: inset 0 0 0 1px var(--selection-border);
}
.table tbody tr:focus-visible { outline: var(--bw-emphasis) solid var(--focus-ring); outline-offset: -2px; }
/* ==========================================================================
8. FACET RAIL (nur Archetyp Datentabelle)
========================================================================== */
.facets {
width: var(--facetrail-w);
flex: 0 0 var(--facetrail-w);
overflow-y: auto;
background: var(--surface-panel-raised);
border-right: var(--bw-hairline) solid var(--border-subtle);
padding: var(--space-2);
}
.facets__group + .facets__group { margin-top: var(--space-3); }
.facets__legend {
font: var(--fw-medium) var(--fs-micro) / 1 var(--font-ui);
letter-spacing: var(--ls-caps);
text-transform: uppercase;
color: var(--text-muted);
padding: 0 var(--space-1) var(--space-1);
}
.facets__item {
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: var(--space-2);
height: var(--control-h-sm);
padding: 0 var(--space-1);
border-radius: var(--radius-xs);
font: var(--fw-regular) var(--fs-sm) / 1 var(--font-ui);
color: var(--text-secondary);
cursor: pointer;
}
.facets__item:hover { background: var(--surface-hover); color: var(--text-primary); }
.facets__count { font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--text-muted); }
/* ==========================================================================
9. INSPECTOR (persistentes Detailpanel)
========================================================================== */
.inspector {
width: var(--inspector-w);
flex: 0 0 var(--inspector-w);
display: flex; flex-direction: column;
background: var(--surface-panel-raised);
border-left: var(--bw-hairline) solid var(--border-subtle);
overflow-y: auto;
}
.inspector__header {
position: sticky; top: 0; z-index: 1;
padding: var(--space-3);
background: var(--surface-panel-raised);
border-bottom: var(--bw-hairline) solid var(--border-subtle);
}
.inspector__title { font: var(--fw-semibold) var(--fs-lg) / var(--lh-ui) var(--font-ui); color: var(--text-primary); }
.inspector__section { padding: var(--space-3); border-bottom: var(--bw-hairline) solid var(--border-subtle); }
.inspector__legend {
font: var(--fw-medium) var(--fs-micro) / 1 var(--font-ui);
letter-spacing: var(--ls-caps); text-transform: uppercase;
color: var(--text-muted); margin-bottom: var(--space-2);
}
.inspector__prose { font: var(--fw-regular) var(--fs-base) / var(--lh-prose) var(--font-ui); color: var(--text-secondary); }
.inspector__prose strong { color: var(--text-primary); font-weight: var(--fw-semibold); }
/* Key-Value-Liste */
.kv { display: grid; grid-template-columns: 128px 1fr; gap: var(--space-1) var(--space-3); }
.kv dt { font: var(--fw-medium) var(--fs-micro) / var(--lh-ui) var(--font-ui);
letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--text-muted); }
.kv dd { font: var(--fw-regular) var(--fs-sm) / var(--lh-ui) var(--font-ui); color: var(--text-primary); margin: 0; }
/* ==========================================================================
10. OVERLAYS
Titelleisten sind IMMER neutral. Keine akzentfarbene Titelleiste.
========================================================================== */
.overlay-titlebar {
display: flex; align-items: center; justify-content: space-between;
gap: var(--space-2);
height: var(--topbar-h);
padding: 0 var(--space-2) 0 var(--space-3);
background: var(--surface-shell);
border-bottom: var(--bw-hairline) solid var(--border-default);
cursor: move;
}
.overlay-titlebar__title {
font: var(--fw-semibold) var(--fs-sm) / 1 var(--font-ui);
letter-spacing: var(--ls-caps); text-transform: uppercase;
color: var(--text-primary);
}
/* Floating Window: nicht modal, verschiebbar, groessenveraenderlich */
.floatwin {
position: fixed;
display: flex; flex-direction: column;
min-width: 480px; min-height: 320px;
max-width: 90vw; max-height: 80vh;
background: var(--surface-overlay);
border: var(--bw-hairline) solid var(--border-strong);
border-radius: var(--radius-md);
box-shadow: var(--shadow-overlay);
resize: both; overflow: hidden;
}
.floatwin__body { flex: 1; overflow: auto; }
/* Dialog: blockierend, nur fuer Entscheidungen */
.dialog {
width: min(560px, 92vw);
background: var(--surface-overlay);
border: var(--bw-hairline) solid var(--border-strong);
border-radius: var(--radius-md);
box-shadow: var(--shadow-overlay);
padding: 0;
}
.dialog::backdrop { background: var(--surface-scrim); }
.dialog__body { padding: var(--space-4); font: var(--fw-regular) var(--fs-base) / var(--lh-prose) var(--font-ui); color: var(--text-secondary); }
.dialog__footer {
display: flex; justify-content: flex-end; gap: var(--space-2);
padding: var(--space-3) var(--space-4);
border-top: var(--bw-hairline) solid var(--border-subtle);
}
/* Drawer: zusaetzlicher Kontext bei begrenzter Breite */
.drawer {
position: fixed; inset: var(--topbar-h) 0 var(--statusbar-h) auto;
width: min(var(--inspector-w), 92vw);
background: var(--surface-overlay);
border-left: var(--bw-hairline) solid var(--border-strong);
box-shadow: var(--shadow-overlay);
}
/* Popover: kurze lokale Auswahl */
.popover {
background: var(--surface-overlay);
border: var(--bw-hairline) solid var(--border-strong);
border-radius: var(--radius-md);
box-shadow: var(--shadow-popover);
padding: var(--space-1);
min-width: 180px;
}
/* ==========================================================================
11. EMPTY STATE
Kompakt, linksbuendig, mit genau einer Aktion. Keine Illustration,
keine zentrierte Hero-Flaeche.
========================================================================== */
.empty {
display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-2);
max-width: 480px;
padding: var(--space-4);
border: var(--bw-hairline) dashed var(--border-default);
border-radius: var(--radius-sm);
}
.empty__title { font: var(--fw-semibold) var(--fs-md) / var(--lh-ui) var(--font-ui); color: var(--text-primary); }
.empty__text { font: var(--fw-regular) var(--fs-sm) / var(--lh-prose) var(--font-ui); color: var(--text-secondary); }
}
/* Verbindlicher Donut-Standard: Referenz vom 2026-08-05. */
.donut-metric-rack {
display: grid;
grid-template-columns: repeat(6, minmax(0, 1fr));
gap: var(--space-2);
padding: var(--space-3);
border: var(--border-hair) solid var(--donut-border);
border-radius: var(--donut-rack-radius);
background: var(--donut-rack-surface);
box-shadow: var(--donut-rack-shadow);
}
.donut-metric-card {
position: relative;
display: grid;
grid-template-rows: auto minmax(0, 1fr);
min-width: 0;
min-height: var(--donut-card-min-h);
padding: var(--space-5) var(--space-3) var(--space-2);
overflow: hidden;
border: var(--border-hair) solid var(--donut-border);
border-radius: var(--donut-card-radius);
color: var(--donut-all);
background: linear-gradient(145deg, var(--donut-card-surface), var(--donut-card-surface-end));
box-shadow: var(--donut-card-shadow);
}
.donut-metric-card::before {
position: absolute;
top: var(--space-1);
left: var(--space-3);
width: 48%;
height: var(--bw-emphasis);
background: linear-gradient(90deg, currentColor 0 72%, transparent 100%);
content: "";
}
.donut-metric-card__title {
min-width: 0;
margin: 0;
overflow: hidden;
color: var(--donut-label);
font: var(--fw-regular) var(--donut-title-size) / 1.15 var(--font-donut-display);
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
}
.donut-metric-card__plot {
position: relative;
align-self: end;
justify-self: center;
width: min(100%, var(--donut-ring-size));
aspect-ratio: 1;
}
.donut-metric-card__plot svg {
display: block;
width: 100%;
height: 100%;
overflow: visible;
transform: rotate(135deg);
}
.donut-metric-card__plot circle {
fill: none;
stroke-width: var(--donut-ring-stroke);
}
.donut-metric-card__track { stroke: var(--donut-track); }
.donut-metric-card__progress {
stroke: currentColor;
stroke-linecap: round;
}
.donut-metric-card__values {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding-top: var(--space-4);
font-family: var(--font-donut-display);
font-variant-numeric: tabular-nums;
line-height: 1;
}
.donut-metric-card__values strong {
color: var(--donut-value);
font-size: var(--donut-value-size);
font-weight: var(--fw-semibold);
}
.donut-metric-card__values span {
margin-top: var(--space-2);
color: currentColor;
font-size: var(--donut-percent-size);
font-weight: var(--fw-regular);
}
.donut-metric-card--all { color: var(--donut-all); }
.donut-metric-card--deviation { color: var(--donut-deviation); }
.donut-metric-card--passed { color: var(--donut-passed); }
.donut-metric-card--not-applicable { color: var(--donut-not-applicable); }
.donut-metric-card--not-run { color: var(--donut-not-run); }
.donut-metric-card--error { color: var(--donut-error); }
@media (prefers-reduced-motion: reduce) {
.donut-metric-card__progress animate { display: none; }
}
@media (max-width: 1100px) {
.donut-metric-rack { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
.donut-metric-rack { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}