Assessor_2.0/src/compliance/ui/compliance.css

211 lines
22 KiB
CSS

/* Compliance Engine UI. Shared tokens only; no status or severity colour. */
/* `Map ISO controls` window, sized like the Accepted Risk window. */
.dialog-window.regulatory-mapping-dialog { width: min(1040px, 100%); }
.regulatory-mapping-panel.is-embedded { margin-top: 0; padding: 0; border: 0; background: transparent; }
/* Finding Reader section, read like `Description`. */
.finding-iso-controls ul { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.finding-iso-controls li { display: flex; flex-wrap: wrap; gap: var(--space-2); font-size: var(--type-body-size); line-height: 1.5; }
.finding-iso-controls li strong { font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; }
/* BSI requirements derived through the BSI mapping. Client Info Results: the ISO route and source stay readable. */
.bsi-requirements__via, .bsi-requirements__source { font-size: var(--type-table-body-size); color: var(--text-secondary); overflow-wrap: break-word; }
.bsi-requirements__source { margin: var(--space-3) 0 0; }
/* Finding Reader: collapsed like Context, one group per ISO control, one line per requirement; a statement opens on demand. */
.finding-bsi-requirements__group { display: grid; gap: var(--space-1); min-width: 0; }
.finding-bsi-requirements__route, .finding-bsi-requirements__source { margin: 0; font-size: var(--type-table-body-size); color: var(--text-secondary); font-variant-numeric: tabular-nums; overflow-wrap: break-word; }
.finding-bsi-requirements__group ul { display: grid; gap: var(--space-1); margin: 0; padding: 0; list-style: none; }
.finding-bsi-requirements__item > summary { display: flex; align-items: baseline; gap: var(--space-2); cursor: pointer; list-style: none; font-size: var(--type-body-size); line-height: 1.5; }
.finding-bsi-requirements__item > summary::-webkit-details-marker { display: none; }
.finding-bsi-requirements__item > summary:focus-visible { outline: var(--bw-emphasis) solid var(--focus-ring); outline-offset: var(--bw-emphasis); }
.finding-bsi-requirements__item > summary strong { font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; white-space: nowrap; }
.finding-bsi-requirements__statement { margin: var(--space-1) 0 var(--space-2) var(--space-5); font-size: var(--type-body-size); line-height: 1.5; }
/* Direct BSI mapping (stage 2): its own group below the derived ones, with the window action beside the heading. */
.finding-bsi-requirements__direct-header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2); }
div.finding-bsi-requirements__item { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); font-size: var(--type-body-size); line-height: 1.5; }
div.finding-bsi-requirements__item strong { font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Client Info `Compliance` tab; its tiles use the environment tile geometry. */
.client-compliance-page { align-content: start; }
.client-compliance { margin-block: 0 var(--space-8); color: var(--text-primary); min-width: 0; }
.client-compliance-header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); }
.client-compliance-heading { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); }
.client-compliance-heading > h2 { margin: 0; font-size: var(--type-h3-size); font-weight: var(--fw-semibold); }
.iso-controls__error { margin: var(--space-2) 0 0; font-size: var(--type-table-body-size); }
/* The theme facts are this tile's purpose, so they stay visible where narrow environment tiles show two facts. */
.client-compliance-grid .client-env-facts > div:nth-child(n + 3) { display: grid; }
/* The BSI tile always shows its totals and four practices, and one more row of two practices for each further
fact row its square fits. A fact row is about 50px; the thresholds measure the inner width (tile minus padding)
with room to spare, so a wrapped practice name scrolls inside the tile instead of being cut off. */
.client-compliance-grid [data-framework="bsi-grundschutz-plus-plus"] .client-env-facts > div:nth-child(n + 7) { display: none; }
@container environment-tile (min-width: 17rem) {
.client-compliance-grid [data-framework="bsi-grundschutz-plus-plus"] .client-env-facts > div:nth-child(-n + 8) { display: grid; }
}
@container environment-tile (min-width: 20.5rem) {
.client-compliance-grid [data-framework="bsi-grundschutz-plus-plus"] .client-env-facts > div:nth-child(-n + 10) { display: grid; }
}
@container environment-tile (min-width: 23.5rem) {
.client-compliance-grid [data-framework="bsi-grundschutz-plus-plus"] .client-env-facts > div:nth-child(-n + 12) { display: grid; }
}
/* A theme fact with hits is one click target over its whole cell; hover changes the surface only. */
.client-compliance-grid .iso-tile-theme.is-actionable { position: relative; cursor: pointer; }
.client-compliance-grid .iso-tile-theme.is-actionable:hover { background: var(--tile-surface-hover); }
.client-compliance-grid .iso-tile-theme.is-actionable:has(button:focus-visible) { outline: var(--bw-emphasis) solid var(--focus-ring); outline-offset: calc(var(--bw-emphasis) * -1); }
.iso-tile-theme button {
padding: 0; border: 0; background: transparent; color: inherit; font: inherit; font-variant-numeric: tabular-nums; text-align: left; cursor: pointer;
}
.iso-tile-theme button::after { content: ''; position: absolute; inset: 0; }
.iso-tile-theme button:focus-visible { outline: none; }
/* ISO Results window: accepted controls grouped by ISO 27002 theme as ranked rows. */
.iso-controls { color: var(--text-primary); min-width: 0; }
.iso-controls__total { margin: 0; font-size: var(--type-body-size); font-weight: var(--fw-regular); color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.iso-controls__empty { margin: 0; font-size: var(--type-body-size); color: var(--text-secondary); }
.iso-controls__themes { display: grid; gap: var(--space-3); margin-top: var(--space-3); }
.iso-controls__group { display: grid; gap: var(--space-1); min-width: 0; }
/* Rows fill columns of twice the compact tile width; a partial last row keeps its track width. */
.iso-controls__rows { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, calc(var(--tile-compact-width) * 2)), 1fr)); gap: var(--space-1) var(--space-3); }
.iso-controls__theme {
display: flex; align-items: baseline; justify-content: flex-start; gap: var(--space-4); flex-wrap: wrap;
padding: var(--space-2) var(--space-1); border: 0; border-bottom: var(--bw-hairline) solid var(--tile-divider);
background: transparent; color: var(--text-primary); font-family: inherit; text-align: left;
}
button.iso-controls__theme { cursor: pointer; }
button.iso-controls__theme:hover .iso-controls__theme-name { text-decoration: underline; }
.iso-controls__theme-name { font-size: var(--type-body-size); font-weight: var(--fw-semibold); }
.iso-controls__theme-count { font-size: var(--type-table-body-size); color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.iso-controls__row {
display: grid; grid-template-columns: max-content minmax(0, 1fr) max-content; align-items: center; gap: var(--space-3);
padding: var(--space-2) var(--space-3); border: var(--bw-hairline) solid var(--tile-border); border-radius: var(--radius-sm);
background: var(--tile-surface); color: var(--text-primary); font-family: inherit; text-align: left; cursor: pointer;
}
.iso-controls__row:hover { background: var(--tile-surface-hover); }
.iso-controls__row:focus-visible, button.iso-controls__theme:focus-visible { outline: var(--bw-emphasis) solid var(--focus-ring); outline-offset: var(--bw-emphasis); }
.iso-controls__id { font-size: var(--type-table-body-size); color: var(--text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.iso-controls__title { font-size: var(--type-body-size); line-height: var(--lh-ui); overflow-wrap: break-word; }
.iso-controls__amount { font-size: var(--type-body-size); font-weight: var(--fw-semibold); text-align: right; font-variant-numeric: tabular-nums; }
.regulatory-earlier-controls { margin-top: 16px; }
.regulatory-earlier-controls > h4 { margin-bottom: 4px; }
.regulatory-earlier-controls > p { color: var(--text-muted); }
/* Data Hub ISO tile: switch for automatic mapping of newly uploaded scans. */
.iso-auto-mapping-toggle { display: flex; align-items: center; gap: var(--space-2); color: var(--text-primary); font-size: var(--type-table-body-size); }
/* `Last mapping` button and its empty state beside the tab heading. */
.client-compliance-last-mapping { font-variant-numeric: tabular-nums; }
.client-compliance-last-mapping.is-empty { color: var(--text-secondary); font-size: var(--type-table-body-size); }
/* Mapping history is a data table, not field/value pairs: every cell keeps the 14px table role. */
.client-information-table.client-compliance-history td:nth-child(2) { font-size: var(--type-table-body-size); }
/* Client Info `Compliance` overview row: same six tracks as the framework row below, so column starts align.
Mapping coverage takes two tracks and the footprint the other four; the row is as tall as the taller content
needs, and both tiles stretch to that same height. */
.compliance-overview { display: grid; grid-template-columns: repeat(6, minmax(var(--tile-environment-min-width), 1fr)); gap: var(--segment-gap); min-width: 0; margin-top: var(--segment-gap); overflow-x: auto; }
.compliance-overview > .client-env-group { display: flex; flex-direction: column; min-width: 0; padding: var(--tile-inset); border: var(--border-hair) solid var(--tile-border); border-radius: var(--tile-radius); background: var(--tile-surface); box-shadow: var(--tile-card-shadow); }
.compliance-overview .client-env-group-title { font-size: var(--type-h4-size); font-weight: var(--fw-semibold); }
.compliance-coverage { grid-column: span 2; }
.compliance-footprint { grid-column: span 4; }
/* Coverage: the shared Client Info donut; accepted, mapped-only and failed are arcs, not mapped is the track. */
.compliance-coverage__body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; gap: var(--space-5); flex: 1; min-height: 0; margin-top: var(--space-4); }
.compliance-coverage__ring { display: grid; justify-items: center; gap: var(--space-2); min-width: 0; }
.compliance-coverage .client-info-donut { width: min(196px, 100%); }
.compliance-coverage__caption { color: var(--donut-label); font-size: var(--donut-title-size); text-align: center; }
.compliance-coverage [data-state="accepted"], .compliance-coverage [data-state="bsi"] { --chart-color: var(--chart-tone-emphasis); }
.compliance-coverage [data-state="isoOnly"] { --chart-color: color-mix(in srgb, var(--chart-tone-emphasis) 45%, var(--tile-surface)); }
.compliance-coverage [data-state="mappedNoneAccepted"] { --chart-color: var(--donut-not-run); }
.compliance-coverage [data-state="failed"] { --chart-color: var(--donut-error); }
.compliance-coverage [data-state="notMapped"] { --chart-color: var(--donut-track); }
.compliance-coverage__legend { display: grid; min-width: 0; margin: 0; border-top: var(--bw-hairline) solid var(--tile-divider); }
.compliance-coverage__legend > div { display: grid; grid-template-columns: var(--space-3) minmax(0, 1fr) max-content; align-items: baseline; gap: var(--space-2); padding: var(--space-2); border-bottom: var(--bw-hairline) solid var(--tile-divider); }
.compliance-coverage__legend i { width: var(--space-3); height: var(--space-3); align-self: center; background: var(--chart-color, transparent); }
.compliance-coverage__legend dt { min-width: 0; color: var(--text-secondary); font-size: var(--type-table-body-size); overflow-wrap: break-word; }
.compliance-coverage__legend dd { margin: 0; font-size: var(--type-body-size); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; text-align: right; }
.compliance-coverage__legend .is-total dt { color: var(--text-primary); }
.compliance-coverage__note { margin: var(--space-3) 0 0; color: var(--text-secondary); font-size: var(--type-table-body-size); }
/* Footprint: all 93 Annex A controls; one neutral chart tone in four steps, never a status colour. */
/* Footprint cells grow with the tile up to a cap, so a wide tile is filled without oversized squares;
each Annex A theme column is only as wide as its six cells, the columns spread across the tile and wrap below
six minimum cells. */
.compliance-footprint {
--footprint-cell-min: calc(var(--space-8) + var(--space-1) + var(--bw-emphasis));
--footprint-cell-max: calc(var(--space-8) * 2);
--footprint-cell-gap: calc(var(--space-1) - var(--bw-hairline));
}
.compliance-footprint__themes { display: grid; grid-template-columns: repeat(auto-fit, minmax(calc(var(--footprint-cell-min) * 6 + var(--footprint-cell-gap) * 5), calc(var(--footprint-cell-max) * 6 + var(--footprint-cell-gap) * 5))); justify-content: space-between; align-items: start; gap: var(--space-6); margin-block: var(--space-4); }
.compliance-footprint__column { display: grid; gap: var(--space-4); }
.compliance-footprint__theme { display: grid; align-content: start; gap: var(--space-2); }
.compliance-footprint__theme-head { display: grid; justify-items: start; padding: 0 0 var(--space-1); border: 0; border-bottom: var(--bw-hairline) solid var(--tile-divider); background: transparent; color: var(--text-primary); font-family: inherit; text-align: left; }
button.compliance-footprint__theme-head { cursor: pointer; }
button.compliance-footprint__theme-head:hover .compliance-footprint__theme-name { text-decoration: underline; }
button.compliance-footprint__theme-head:focus-visible { outline: var(--bw-emphasis) solid var(--focus-ring); outline-offset: var(--bw-emphasis); }
.compliance-footprint__theme-name { font-size: var(--type-body-size); font-weight: var(--fw-semibold); }
.compliance-footprint__theme-meta { color: var(--text-secondary); font-size: var(--type-table-body-size); font-variant-numeric: tabular-nums; }
.compliance-footprint__cells { display: grid; grid-template-columns: repeat(6, minmax(var(--footprint-cell-min), var(--footprint-cell-max))); gap: var(--footprint-cell-gap); }
.compliance-footprint__cells > .compliance-footprint__cell, .compliance-footprint__requirements > .compliance-footprint__cell { height: auto; min-height: calc(var(--space-6) + var(--space-1) + var(--bw-emphasis)); aspect-ratio: 5 / 3; font-size: var(--type-table-body-size); }
.compliance-footprint__cell { display: grid; place-items: center; height: calc(var(--space-6) + var(--space-1) + var(--bw-emphasis)); padding: 0; border: var(--bw-hairline) solid var(--tile-divider); background: transparent; color: var(--text-secondary); font-family: inherit; font-size: var(--type-meta-size); font-variant-numeric: tabular-nums; }
.compliance-footprint__cell[data-step] { border-color: transparent; color: var(--text-primary); }
button.compliance-footprint__cell { cursor: pointer; }
.compliance-footprint__cell[data-step="1"] { background: color-mix(in srgb, var(--chart-tone-emphasis) 22%, var(--tile-surface)); }
.compliance-footprint__cell[data-step="2"] { background: color-mix(in srgb, var(--chart-tone-emphasis) 45%, var(--tile-surface)); }
.compliance-footprint__cell[data-step="3"] { background: color-mix(in srgb, var(--chart-tone-emphasis) 72%, var(--tile-surface)); color: var(--sev-ink); }
.compliance-footprint__cell[data-step="4"] { background: var(--chart-tone-emphasis); color: var(--sev-ink); font-weight: var(--fw-semibold); }
button.compliance-footprint__cell:hover, .compliance-footprint__cell.is-current { outline: var(--bw-hairline) solid var(--text-primary); outline-offset: calc(var(--bw-hairline) * -1); }
button.compliance-footprint__cell:focus-visible { outline: var(--bw-emphasis) solid var(--focus-ring); outline-offset: 0; }
.compliance-footprint__detail { display: grid; grid-template-columns: minmax(0, 1fr) max-content; align-items: center; gap: var(--space-3); min-height: calc(var(--space-8) * 1.75); margin-top: auto; padding: var(--space-2) var(--space-3); border-block: var(--bw-hairline) solid var(--tile-divider); }
.compliance-footprint__detail-id, .compliance-footprint__detail-hint { color: var(--text-secondary); font-size: var(--type-table-body-size); }
.compliance-footprint__detail-title { font-size: var(--type-body-size); overflow-wrap: break-word; }
.compliance-footprint__detail-count { font-size: var(--type-body-size); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; }
.compliance-footprint__legend { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); margin-top: var(--space-3); color: var(--text-secondary); font-size: var(--type-table-body-size); }
.compliance-footprint__legend > span { display: inline-flex; align-items: center; gap: var(--space-2); }
.compliance-footprint__legend .compliance-footprint__cell { width: calc(var(--space-5) + var(--bw-emphasis)); height: var(--space-4); }
/* BSI Kernel footprint: every requirement of a shown practice is a square with its number, like an Annex A cell;
the practices stack at full width so their squares wrap across the tile. A requirement the ISO mapping cannot
reach has a dashed outline, a reachable one without findings the solid outline of an empty Annex A cell. */
.compliance-footprint__practices { display: grid; gap: var(--space-4); margin-block: var(--space-4); }
/* As many capped columns as fit, so the squares fill each row at the size of the Annex A cells. */
.compliance-footprint__requirements { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--footprint-cell-min), var(--footprint-cell-max))); gap: var(--footprint-cell-gap); }
.compliance-footprint__requirements > .compliance-footprint__cell { padding: 0 var(--space-1); white-space: nowrap; }
.compliance-footprint__cell.is-unreachable { border-style: dashed; }
.compliance-footprint__pending { margin: var(--space-4) 0; color: var(--text-secondary); font-size: var(--type-body-size); }
/* Show all window: every practice, with larger squares and the 14px data role for the numbers. */
.compliance-footprint--window { min-width: 0; }
.compliance-footprint__practices.is-window { --footprint-cell-min: calc(var(--space-8) + var(--space-4)); --footprint-cell-gap: var(--space-1); }
.compliance-footprint__practices.is-window .compliance-footprint__requirements > .compliance-footprint__cell { min-height: calc(var(--space-8) + var(--space-1)); padding: 0 var(--space-2); }
.compliance-footprint__footer { margin-top: auto; }
/* Pinned to the bottom of the window body (its 20px inset included), on the window surface, while the grid scrolls. */
.compliance-footprint--window .compliance-footprint__footer { position: sticky; bottom: calc(var(--panel-inset) * -1); padding-bottom: var(--panel-inset); background: var(--bg); }
/* `Mapping failed` with findings opens Work: one click target over the whole legend row; hover changes the surface only. */
.compliance-coverage__legend > div.is-actionable { position: relative; cursor: pointer; }
.compliance-coverage__legend > div.is-actionable:hover { background: var(--tile-surface-hover); }
.compliance-coverage__legend > div.is-actionable:has(button:focus-visible) { outline: var(--bw-emphasis) solid var(--focus-ring); outline-offset: calc(var(--bw-emphasis) * -1); }
.compliance-coverage__legend dd button { padding: 0; border: 0; background: transparent; color: inherit; font: inherit; font-variant-numeric: tabular-nums; cursor: pointer; }
.compliance-coverage__legend dd button::after { content: ''; position: absolute; inset: 0; }
.compliance-coverage__legend dd button:focus-visible { outline: none; }
/* ISO <-> BSI review window (Phase 13F, BSI stage 2): rules as disclosure rows, no status colour. */
.mapping-review { display: grid; gap: var(--space-3); min-width: 0; }
.mapping-review__intro, .mapping-review__note { margin: 0; font-size: var(--type-body-size); line-height: 1.5; }
.mapping-review__note { color: var(--text-secondary); }
.mapping-review__items { display: grid; min-width: 0; border-top: var(--border-hair) solid var(--tile-divider); }
.mapping-review__item { min-width: 0; border-bottom: var(--border-hair) solid var(--tile-divider); }
.mapping-review__item > summary { display: grid; grid-template-columns: minmax(150px, auto) minmax(0, 1fr); gap: var(--space-1) var(--space-3); padding: var(--space-2) 0; cursor: pointer; list-style: none; }
.mapping-review__item > summary::-webkit-details-marker { display: none; }
.mapping-review__item > summary:hover { background: var(--tile-surface-hover); }
.mapping-review__item > summary:focus-visible { outline: var(--bw-emphasis) solid var(--focus-ring); outline-offset: calc(var(--bw-emphasis) * -1); }
.mapping-review__state { font-size: var(--type-table-body-size); font-weight: var(--fw-semibold); }
.mapping-review__title { font-size: var(--type-body-size); overflow-wrap: break-word; min-width: 0; }
.mapping-review__meta { font-size: var(--type-table-body-size); color: var(--text-secondary); overflow-wrap: anywhere; }
.mapping-review__item > summary .mapping-review__meta { grid-column: 2; }
.mapping-review__detail { display: grid; gap: var(--space-3); padding: 0 0 var(--space-3); }
.mapping-review__side h4 { margin: 0 0 var(--space-1); font-size: var(--type-table-body-size); font-weight: var(--fw-semibold); }
.mapping-review__side p { margin: 0; font-size: var(--type-table-body-size); color: var(--text-secondary); }
.mapping-review__side ul { display: grid; gap: var(--space-1); margin: 0; padding: 0; list-style: none; }
.mapping-review__side li { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); font-size: var(--type-table-body-size); }
.mapping-review__side li strong { font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; white-space: nowrap; }
.mapping-review__side li > span:not(.mapping-review__meta) { flex: 1 1 200px; min-width: 0; overflow-wrap: break-word; }
.mapping-review__actions { display: flex; flex-wrap: wrap; align-items: end; gap: var(--space-2); }
.mapping-review__actions label { display: grid; flex: 1 1 260px; gap: var(--space-1); font-size: var(--type-table-body-size); }