← Back to the screen

Design system portfolio

Perimeter — AWS Cloudscape — the record

The four direction lines behind this page, the generator command that produced its tokens, and the pairs it was measured against.

Cloud security posture across three AWS accounts, built as a wall display for a security operations room. It answers one question, from six metres: is anything wrong.

Direction

LeverDecision
ArchetypeConsole. Ten regions on a fixed grid, filling one viewport at 1400px and wider with nothing to scroll.
Data stanceChart-first. Six of the ten regions carry a drawn mark; every figure states its comparison.
DensityCloudscape compact. space-scaled-* at the compact column for gaps that should compress, space-static-* for gaps that must not.
The one bold thingThe legend prints the contrast ratio. A 2px line takes the -500 step, a filled bar takes -400, and the browser measures both at load and on every theme change — per series where the two lines differ, and as one range under the four fills.

The eleventh tile was drafted — a cost-anomaly panel — and cut. Ten is what a person reads in fifteen seconds; eleven makes it a report.

Generator

cloudscape_tokens.py --both > tokens.css      # the linked file, never hand-edited
cloudscape_tokens.py --charts                 # the 155 data-visualisation tokens
cloudscape_tokens.py --density                # comfortable vs compact, 24 of 140 differ

tokens.css is generated output. Every colour and every radius on the page is a var() from it.

Where the ratio is printed, and where it is not

The two trend series print their own measured ratio, because the two lines are a real choice: -500 for a 2px mark, and the number differs by theme. The four severity fills do not. Measured, they land inside 0.03 of each other in either theme, so four ratios in four legend slots discriminate nothing and cost the slot the count needs; the four slots carry 21, 47, 108 and 72, and the range the four fills actually hold is stated once under the chart. The measurement is still live in both places — read from the browser at load and on every theme change, never transcribed.

Ranking, and the verdict that has to be true

Six of the ten regions are a measure with a target. Each states in its own head whether it is inside that target, at two levels: error for what the verdict pages on, warning for what is tracked. One region reads 9 of 9 under a tick. That is what makes the bottom row rank from six metres rather than read left to right.

The verdict counts the same way. It names the two over threshold, then the four outside target and the account three of them sit in. It said "Everything else sits inside its threshold" under a green tick until the critique round, over four regions that each print a target they miss.

The two states

Reporting. Every feed is live, the trend line is solid to today, and the detector tile reads 9 of 9.

One feed stopped. Security Hub in eu-west-1 goes quiet at 13:41. The trend line stops at the last real reading and a faint dashed segment bridges the gap with no markers and no end label; the sandbox account's stacked bar disappears and its total becomes an em dash; the detector tile says Not reporting rather than 3 of 3; the verdict changes from "Two measures are over threshold" to "Two over threshold, one unknown". Zero and no data are two different marks, which is the whole point of the state — a stale value that looks live is worse than no value.

Measured contrast

Every pair sits on color-background-container-content (#ffffff light, #161d26 dark) and every number comes from web-design/scripts/contrast.py.

WhatTokenLightDarkFloor
A value read off a regioncolor-text-body-default18.50:19.98:14.5:1
Critical line, 2pxcolor-charts-red-5005.01:16.21:13:1
High line, 2pxcolor-charts-orange-5005.00:16.23:13:1
Critical bar, filledcolor-charts-red-4004.01:14.99:13:1
Low bar, filledcolor-charts-blue-1-4004.03:14.96:13:1
Primary button labelcolor-text-button-primary-default4.97:18.11:14.5:1

In the light theme the number in a chart token's name is its ratio to the second decimal. In the dark theme it is a floor: the -500 step measures 6.21:1 rather than 5:1, because that ramp is indexed against a lighter surface than this one. The legend prints what the browser measures, so a reader sees the difference rather than taking it on trust.

Measuring also found one thing reading the names could not. color-charts-red-300 is 2.998:1 on white — it rounds to 3.00:1 and misses WCAG 1.4.11's floor for a graphic by a thousandth, while orange, yellow and blue at the same step clear it. The four filled bars take the -400 step instead, which holds 4.00:1 or better in light and 4.96:1 or better in dark across all four hues. A palette indexed by ratio still has to be measured.

Deviations

Kept warnings

copy-lint.ignore keeps operator-copy, which fires on 0.0.0.0/0. On a cloud security console the CIDR block is the finding itself, in the vocabulary the reader uses to write the security-group rule that caused it.