/** * Agent Firewall admin styles. * * Compiled by wp-scripts to build/style-index.css via the import in index.js. */ .adaf-admin { &__panel { margin-top: 1em; } table { margin-bottom: 1.5em; } } .adaf-badge { display: inline-block; padding: 2px 8px; border-radius: 3px; font-size: 12px; font-weight: 600; line-height: 1.8; text-transform: uppercase; letter-spacing: 0.02em; border: 1px solid transparent; &--allowed { background: #edfaef; border-color: #68de7c; color: #00500c; } &--denied { background: #fcf0f1; border-color: #f86368; color: #8a2424; } &--pending { background: #fcf9e8; border-color: #dba617; color: #674600; } &--undone { background: #f0f0f1; border-color: #a7aaad; color: #3c434a; } // Policy decisions reuse the ledger palette: allow reads as allowed, // deny as denied, and anything held for a human as pending. &--allow, &--log_only { background: #edfaef; border-color: #68de7c; color: #00500c; } &--deny { background: #fcf0f1; border-color: #f86368; color: #8a2424; } &--require_approval, &--evaluate_ai { background: #fcf9e8; border-color: #dba617; color: #674600; } // Exposure findings reuse the same palette (AF-16.8): something // unaccounted for reads like an action held for a human, and an // inventory line reads like a decision already made. &--attention { background: #fcf9e8; border-color: #dba617; color: #674600; } &--review { background: #f0f0f1; border-color: #a7aaad; color: #3c434a; } } .adaf-defaults { margin-top: 1em; &__table { max-width: 48em; td { vertical-align: top; } .description { margin: 4px 0 0; } } } .adaf-rule { max-width: 48em; margin: 0 0 1em; padding: 8px 12px 4px; border: 1px solid #dcdcde; background: #fff; legend { padding: 0 4px; font-weight: 600; } &__matches { display: flex; flex-wrap: wrap; gap: 0 1.5em; } &__field { display: flex; align-items: center; gap: 0.5em; margin: 0 0 0.75em; label { font-weight: 600; white-space: nowrap; } input[type="number"] { width: 7em; } } &__actions { margin: 0 0 0.75em; .button + .button { margin-left: 4px; } } } .adaf-agents__token code { display: block; padding: 8px; margin: 4px 0; word-break: break-all; background: #fff; } .adaf-pending__payload, .adaf-policies__rules { max-width: 32em; max-height: 12em; margin: 0; overflow: auto; padding: 8px; background: #f6f7f7; border: 1px solid #dcdcde; font-size: 12px; } // What an agent asked to do is read, not skimmed: wrap long values rather // than hide their end behind a sideways scrollbar that only appears on hover. .adaf-pending__payload { white-space: pre-wrap; overflow-wrap: anywhere; } .adaf-scopes { color: #50575e; font-size: 12px; &--none { font-style: italic; } } // Only ever shown for an agent linked before AF-12.14 refused such links. // Warning colors rather than neutral: this one wants fixing, not noting. // The loading row. Core's .spinner floats right with a 10px top margin, // which is right beside a submit button and wrong inside a table cell, so // both are reset here rather than the spinner being reinvented. .adaf-loading td { color: #646970; padding: 12px 10px; } .adaf-loading .spinner { float: none; margin: 0 6px 0 0; vertical-align: text-bottom; } // Row actions sat flush against each other: a .button and a bare link with // nothing between them and no shared baseline. Flex gives both the gap and // the vertical centering, and wraps rather than overflowing a narrow column. .adaf-row-actions { align-items: center; display: flex; flex-wrap: wrap; gap: 4px 10px; } .adaf-row-actions__pending { color: #646970; font-style: italic; } // A linked user that no longer resolves. Muted rather than alarming - the // agent is broken, but the row is reporting a fact, not raising an alert. .adaf-user-missing { color: #646970; font-style: italic; margin-left: 4px; } .adaf-privileged { background: #fcf0f1; border: 1px solid #d63638; border-radius: 2px; color: #8a2424; display: inline-block; font-size: 11px; margin-left: 6px; padding: 0 5px; white-space: nowrap; } // An agent an administrator confirmed runs as one (AF-25.15): deliberate, // so a caution color rather than the error red of an unconfirmed one. .adaf-admin-agent { background: #fcf9e8; border: 1px solid #dba617; border-radius: 2px; color: #614a19; display: inline-block; font-size: 11px; margin-left: 6px; padding: 0 5px; white-space: nowrap; } .adaf-dryrun { max-width: 48em; margin: 1.5em 0; padding: 8px 12px; border: 1px solid #dcdcde; background: #fff; h2 { margin-top: 0.5em; } &__form { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5em; label { font-weight: 600; } } &__result { margin-top: 0.5em; padding: 8px 12px; background: #f6f7f7; border-left: 4px solid #2271b1; p { margin: 0.25em 0; } } &__explanation { font-weight: 600; } } .adaf-ledger__provenance { max-width: 22em; color: #50575e; font-size: 12px; } // Target cell: the name leads because it is what a reader scans for, and the // type/id reference stays under it because that is what survives a rename or // a deletion (AF-12.10). .adaf-target__name { font-weight: 600; max-width: 18em; overflow-wrap: anywhere; } .adaf-target__renamed, .adaf-target__ref { color: #50575e; font-size: 12px; max-width: 18em; overflow-wrap: anywhere; } // First-run guidance panel. // // Core caps .card at 520px (wp-admin/css/forms.css), which left this panel a // narrow box floating above a full-width screen - the tabs, filters and // ledger table below it all run the whole content width, and the mismatch is // what the eye catches first. The cap is dropped so the card's edges line up // with everything under it. // // Line length is left to the layout rather than capped: the three-column // grid below gives each step a readable measure on a wide screen, and on a // narrow one the text runs the panel width exactly as every other // description on this screen does. Capping the intro alone just made it // ragged against the steps beneath it. .card.adaf-getting-started { max-width: none; // Three steps across the card rather than down its left edge. A // full-width panel with a single narrow text column leaves most of // itself empty; in columns the space is used and each step keeps a // readable measure. // // Mobile-first, and the order matters: the stacked rules come first and // the column overrides last, so the breakpoint wins by source order // rather than by specificity. Written the other way round - the override // above a later same-specificity rule - the separator below quietly // undoes it, which is exactly how the actions came to be misaligned. ol { display: grid; gap: 1.5em 2.5em; margin: 1em 0 0; padding-left: 1.5em; } // Steps rarely run to the same number of lines, so an action placed // directly after its prose lands at a different height in each column // and the row of buttons reads as ragged rather than as three equal // choices. Each step is a full-height column with its action pushed to // the bottom, which holds the baseline whatever the copy does - the // point being translations, where the line counts shift again and any // fix depending on the English lengths would come undone. // // The flex column lives on an inner wrapper rather than on the
  • : // a list item given `display: flex` is no longer a list-item and // silently loses its number, and the numbering is the whole point of // an ordered list of steps. .adaf-getting-started__step { display: flex; flex-direction: column; height: 100%; } // Each step's action is its own block, left-aligned with the text it // belongs to. Inline, the button sat wherever the sentence happened to // stop and moved as the card resized. Not centered: the card grows with // the viewport, and a centered control drifts away from the step it acts // on - and away from the left-aligned column the numbered list sets up. // // `auto` top margin does the pinning; the padding carries the gap, // because in the tallest column there is no free space for the margin // to absorb and the button would otherwise touch the text. .adaf-getting-started__action { margin: auto 0 0; padding-top: 0.75em; } // Separates the steps while they are stacked. li { margin-bottom: 1.5em; &:last-child { margin-bottom: 0; } } // Three or one, never two: three items in two columns leaves a hole // under the second, which reads as a rendering fault rather than a // layout. The breakpoint is where three columns still hold a comfortable // line - below it they would be too narrow to be worth having. @media screen and (min-width: 1280px) { ol { grid-template-columns: repeat(3, 1fr); gap: 0 2.5em; } // The stacked separator must not survive into the columns. A // stretched grid item fills the row with its *margin box*, so a step // still carrying 1.5em beneath it ends its content that much higher // than the last step, which has none - putting two of the three // actions 19px above the baseline they are being aligned to. li { margin-bottom: 0; } } } // Explains a picker that is empty or has stopped short. Sits directly under // the control it is about, in the muted tone the scopes column already uses. .adaf-linkable-note { max-width: 48em; color: #50575e; font-size: 13px; margin: -0.5em 0 1em; } // Field-level help under a form control: what the field is for, in the muted // tone the other notes on this screen use. .adaf-field-note { max-width: 48em; color: #50575e; font-size: 13px; margin: -0.5em 0 1em; } .adaf-unused { max-width: 48em; margin: 1.5em 0; padding: 8px 12px; border: 1px solid #dcdcde; background: #fff; h2 { margin-top: 0.5em; } &__list { margin: 0.5em 0; list-style: none; li { padding: 6px 0; border-top: 1px solid #f0f0f1; } } &__rule { margin: 4px 0 0; padding: 6px 8px; overflow-x: auto; background: #f6f7f7; border: 1px solid #dcdcde; font-size: 12px; } } .adaf-retention { max-width: 48em; margin: 0 0 1em; .notice.inline { margin: 8px 0; } } .adaf-alerts { max-width: 48em; margin: 0 0 1em; label { font-weight: 600; } .description { display: block; margin-top: 4px; } &__notice { font-style: italic; } } /** * The application password an agent answers to (AF-13.2). * * A revoked binding is styled like the missing-user note rather than as an * error: the agent still works over its bearer token, so this is a fact to * report, not a failure to alarm about. */ .adaf-app-password { font-size: 12px; &__name { font-family: Consolas, Monaco, monospace; } &__revoked { color: #8a2424; font-style: italic; } &--picking select { max-width: 16em; } .description { display: block; margin-top: 4px; } } /** * The switch for automation that claims no agent. Shares the alert switch's * shape because it is the same kind of control: one checkbox, and a * description that carries the consequence rather than restating the label. */ .adaf-untracked-writes { max-width: 48em; margin: 0 0 1em; label { font-weight: 600; } .description { display: block; margin-top: 4px; } &__notice { font-style: italic; } } /** * Rows-per-page control, sat inside core's .tablenav-pages beside the count. */ .adaf-tablenav__per-page { margin: 0 12px; label { margin-right: 4px; } } /** * Core sizes its page field with size="1" on a text input; this one is a * number input (so it announces as a spinbutton), which needs a width. */ .adaf-ledger .tablenav .current-page { width: 4em; text-align: center; } // Exposure scan (AF-16.8). .adaf-scan { &__header { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin: 16px 0; } &__when { margin: 0; font-weight: 600; } &__summary { display: flex; flex-wrap: wrap; gap: 24px; margin: 16px 0 24px; padding: 16px; background: #fff; border: 1px solid #c3c4c7; } &__count { display: flex; align-items: baseline; gap: 8px; margin: 0; } &__number { font-size: 28px; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; } &__count--attention .adaf-scan__number { color: #674600; } &__count--review .adaf-scan__number { color: #3c434a; } &__label { color: #50575e; } &__check { margin: 0 0 24px; h3 { margin: 0 0 8px; padding-bottom: 8px; border-bottom: 1px solid #dcdcde; } } &__none { margin: 0; color: #50575e; font-style: italic; } // A check that could not run is not an all-clear, and must not be // mistaken for one at a glance. &__error { margin: 0; padding: 8px 12px; background: #fcf0f1; border-left: 4px solid #d63638; } &__findings { margin: 0; list-style: none; } } .adaf-finding { margin: 0 0 4px; padding: 12px 16px; background: #fff; border: 1px solid #dcdcde; border-left-width: 4px; &--attention { border-left-color: #dba617; } &--review { border-left-color: #a7aaad; } &__title { margin: 0; font-weight: 600; } .description { margin: 4px 0 0; } // One paragraph, then everything it applies to. Each row keeps its own // action, because binding a password is per password even when the // reason to bind it is shared. &__subjects { margin: 8px 0 0; list-style: none; } &__item { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; margin: 0; padding: 4px 0; & + & { border-top: 1px solid #f0f0f1; } } &__subject { font-family: Consolas, Monaco, monospace; font-size: 13px; } }