/* Design tokens.
   One scale per dimension. The previous sheet mixed seven font weights and
   four radii picked ad hoc per component, which is what made every page look
   subtly like a different product.

   Values now come from the marketing site's Figma library, so signing in does
   not feel like arriving at a different company: the greys are its slate ramp,
   the accent is its brand green, and the radii and type match. Only the values
   changed — every variable kept its name, so the rest of this sheet is
   untouched by the rebrand. */
:root {
    /* Typography. The site pairs Outfit for headings with Inter for text and
       Geist Mono for small uppercase labels and any figure meant to be compared
       column to column. */
    --font-display: "Outfit", "Inter", system-ui, sans-serif;
    --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
    --font-mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;

    --bg: #f8fafc;
    --surface: #ffffff;
    --sunken: #f1f5f9;
    --line: #e2e8f0;
    --line-strong: #cbd5e1;

    --text: #0f172a;
    --text-soft: #475569;
    --text-faint: #64748b;

    --accent: #0f5135;
    --accent-hover: #0b3d28;
    --accent-tint: #ecfdf5;
    --ring: rgba(15, 81, 53, 0.24);

    /* The emerald half of the logo. Decorative only — at 3.2:1 on white it is
       not safe for text, so it stays on fills and marks. */
    --accent-bright: #10b981;

    /* The five risk bands, worst first. Each carries a text colour for the
       label and a tint plus edge for the pill it sits in, so a band reads the
       same everywhere it appears.

       Deliberately not rebranded: these encode meaning, and every one clears
       4.5:1 on its own tint. `--ok` is nudged to the site's green so "nothing
       wrong" and the brand read as the same colour. */
    --high: #b42318;
    --high-tint: #fef3f2;
    --high-line: #fecdc9;
    --mid: #c2410c;
    --mid-tint: #fff7ed;
    --mid-line: #fed7aa;
    --low: #b54708;
    --low-tint: #fffaeb;
    --low-line: #fedf89;
    --ok: #047857;
    --ok-tint: #ecfdf5;
    --ok-line: #a7f3d0;
    /* Not slate-500 (#64748b): on the tint below that is 4.34:1, just under AA.
       This sits between slate-500 and 600 so it clears 4.9:1 and still reads as
       a neutral, distinct from --text-soft. */
    --off: #5d6b7f;
    --off-tint: #f1f5f9;
    --off-line: #e2e8f0;

    --danger: #b42318;

    --r-sm: 6px;
    --r-md: 8px;
    --r-lg: 12px;
    /* The site's panel radius, for the one-per-page hero surfaces. */
    --r-xl: 24px;

    --gap: 16px;
    --pad: 20px;

    --shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
    --shadow-lift: 0 4px 16px rgba(15, 23, 42, 0.08);
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    /* 1.6 rather than 1.55 to clear the 1.5 minimum in WCAG 2.2 SC 1.4.12 with
       room to spare, and to match the site's body leading. */
    font: 15px/1.6 var(--font-sans);
    -webkit-font-smoothing: antialiased;
}

a {
    color: var(--accent-hover);
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

/* One visible focus treatment for every interactive element. There was none
   before, so keyboard users had to guess where they were. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--r-sm);
}

@media (prefers-reduced-motion: reduce) {
    * {
        transition: none !important;
    }
}

/* ---------------------------------------------------------------- app shell */

.app-header {
    display: flex;
    align-items: center;
    gap: 24px;
    min-height: 60px;
    padding: 0 24px;
    background: var(--surface);
    border-bottom: 1px solid var(--line);
}

.brand {
    display: inline-flex;
    align-items: center;
    flex: none;
}

.brand:hover {
    text-decoration: none;
}

/* The lockup carries its own wordmark, so height is fixed and width follows the
   asset's 623x151 to keep it from stretching. */
.brand-logo {
    display: block;
    height: 30px;
    width: auto;
}

nav {
    display: flex;
    align-items: center;
    gap: 4px;
}

.nav-main {
    flex: 1;
}

/* The active page is marked, so the header answers "where am I" without the
   user re-reading the heading. */
.nav-link {
    padding: 7px 12px;
    border-radius: var(--r-sm);
    color: var(--text-soft);
    font-weight: 500;
}

.nav-link:hover {
    background: var(--sunken);
    color: var(--text);
    text-decoration: none;
}

.nav-link.is-active {
    background: var(--accent-tint);
    color: var(--accent-hover);
    font-weight: 600;
}

/* Billing, members, and settings are occasional errands, so they live behind
   one menu rather than competing with the daily work in the main nav. */
.account-menu {
    position: relative;
}

.account-menu > summary {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px 6px 6px;
    border: 1px solid var(--line);
    border-radius: 999px;
    color: var(--text-soft);
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    list-style: none;
}

.account-menu > summary::-webkit-details-marker {
    display: none;
}

.account-menu > summary:hover {
    background: var(--sunken);
}

.account-menu[open] > summary {
    background: var(--sunken);
    border-color: var(--line-strong);
}

.avatar {
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--accent-tint);
    color: var(--accent-hover);
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
}

.caret {
    color: var(--text-faint);
    font-size: 10px;
}

.menu-panel {
    position: absolute;
    right: 0;
    z-index: 20;
    width: 260px;
    margin-top: 8px;
    padding: 8px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-lift);
}

.menu-head {
    padding: 8px 10px 10px;
    border-bottom: 1px solid var(--line);
    margin-bottom: 6px;
}

.menu-head strong {
    display: block;
    font-size: 14px;
    font-weight: 600;
    overflow-wrap: anywhere;
}

.menu-head small {
    color: var(--text-faint);
    overflow-wrap: anywhere;
}

.menu-panel a,
.menu-panel button {
    display: block;
    width: 100%;
    min-height: 0;
    padding: 8px 10px;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    color: var(--text-soft);
    font: inherit;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
}

.menu-panel a:hover,
.menu-panel button:hover {
    background: var(--sunken);
    color: var(--text);
    text-decoration: none;
}

.menu-section {
    margin: 6px 0 2px;
    padding: 0 10px;
    color: var(--text-faint);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.menu-panel form {
    margin: 6px 0 0;
    padding-top: 6px;
    border-top: 1px solid var(--line);
}

.org-switcher {
    margin: 0;
    padding: 0 10px 8px;
}

.org-switcher select {
    width: 100%;
    font: inherit;
    font-size: 14px;
}

.shell {
    width: min(1140px, calc(100% - 40px));
    margin: 28px auto 72px;
}

/* --------------------------------------------------------------- typography */

h1,
h2,
h3,
p {
    margin-top: 0;
}

/* Outfit at 700, matching the site's section headings. The app's scale stays
   far smaller than the marketing page's 40-56px — a work surface is read, not
   pitched — so only the family, weight, and tracking are shared. */
h1,
h2,
h3 {
    font-family: var(--font-display);
}

h1 {
    margin-bottom: 4px;
    font-size: 26px;
    font-weight: 700;
    letter-spacing: -0.02em;
}

h2 {
    margin-bottom: 10px;
    font-size: 17px;
    font-weight: 700;
    letter-spacing: -0.01em;
}

h3 {
    margin-bottom: 6px;
    font-size: 14px;
    font-weight: 600;
}

small {
    font-size: 13px;
}

.muted,
.lead,
.help-text,
.page-title p,
.metric span,
.section-heading span {
    color: var(--text-soft);
}

.lead {
    max-width: 68ch;
}

.help-text {
    font-size: 13px;
    margin-bottom: 8px;
}

.help-text code,
code {
    padding: 2px 6px;
    border-radius: 4px;
    background: var(--sunken);
    font-size: 12px;
}

.page-title {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 24px;
    margin-bottom: 22px;
}

.page-title p {
    margin-bottom: 0;
    max-width: 68ch;
}

.section-heading {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 12px;
}

.section-heading h2 {
    margin-bottom: 0;
}

.section-heading span {
    font-size: 13px;
}

/* ------------------------------------------------------------------ buttons */

.actions,
.form-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

/* Geometry follows the site's buttons: 8px radius, 600 weight at 14px, and a
   1px border in the plain slate line colour rather than the heavier one. Kept at
   36px high — denser than the site's 48px, because a table row may hold three of
   these and a marketing hero holds one. */
.button,
button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 36px;
    padding: 0 16px;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    transition: background 120ms ease, border-color 120ms ease;
}

.button:hover,
button:hover {
    background: var(--sunken);
    text-decoration: none;
}

.button.primary,
button.primary {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
    font-weight: 600;
}

.button.primary:hover,
button.primary:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
}

/* Borderless, for repeated row actions. A table of ten Edit buttons drawn as
   ten bordered boxes is louder than the data it acts on. */
.button.quiet,
button.quiet {
    border-color: transparent;
    background: none;
    color: var(--text-soft);
}

.button.quiet:hover,
button.quiet:hover {
    background: var(--sunken);
    color: var(--text);
}

/* Solid red is reserved for what cannot be undone. It used to sit on Archive
   and even on Restore, so the one colour that should stop someone had stopped
   meaning anything. */
.button.destructive,
button.destructive {
    border-color: transparent;
    background: none;
    color: var(--danger);
}

.button.destructive:hover,
button.destructive:hover {
    background: var(--high-tint);
}

.button.destructive-solid,
button.destructive-solid {
    background: var(--danger);
    border-color: var(--danger);
    color: #fff;
    font-weight: 600;
}

.button.destructive-solid:hover,
button.destructive-solid:hover {
    background: #912018;
    border-color: #912018;
}

.button.block,
button.block {
    width: 100%;
}

.button[disabled],
button[disabled] {
    opacity: 0.55;
    cursor: not-allowed;
}

.link-button {
    min-height: 0;
    padding: 0;
    border: 0;
    background: none;
    color: var(--accent-hover);
    font-size: 13px;
    font-weight: 500;
}

.link-button:hover {
    background: none;
    text-decoration: underline;
}

.link-button.danger-text {
    color: var(--danger);
}

.inline-form {
    display: inline-flex;
    margin: 0;
}

.danger-text {
    color: var(--danger);
}

/* ----------------------------------------------------------------- surfaces */

.panel {
    padding: var(--pad);
    margin-bottom: var(--gap);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
}

.panel > :last-child {
    margin-bottom: 0;
}

.panel.flush {
    padding: 0;
    overflow: hidden;
}

.panel.flush .section-heading {
    padding: var(--pad) var(--pad) 0;
    margin-bottom: 12px;
}

.panel.flush > p {
    padding: 0 var(--pad) var(--pad);
}

.metric-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 12px;
    margin-bottom: var(--gap);
}

.metric {
    padding: 16px 18px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
}

/* Direct children only. Matching any descendant `span` turned a status pill
   inside the value into a full-width block, and shrank an inline "/ 10" to
   label size on its own line. */
/* The label above a figure, as an uppercase mono caption like the site's
   eyebrows. Keeps the number below it the loudest thing in the tile. */
.metric > span {
    display: block;
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

/* Outfit at 700, matching the figures in the site's scan-status panel. */
.metric > strong {
    display: block;
    margin-top: 4px;
    font-family: var(--font-display);
    font-size: 26px;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.15;
}

.metric > small {
    display: block;
    margin-top: 2px;
    color: var(--text-faint);
}

/* A pill is the value on the cards that carry a state rather than a number. */
.metric > strong > .status {
    font-size: 13px;
    vertical-align: 3px;
}

/* A metric whose number is the work waiting to be done. It reads as a link
   because acting on it is the point. */
.metric.is-attention {
    border-color: var(--high-line);
    background: var(--high-tint);
}

.metric.is-attention strong,
.metric.is-attention strong a {
    color: var(--high);
}

.metric.is-attention strong a:hover {
    text-decoration: underline;
}

.metric.is-clear {
    border-color: var(--ok-line);
    background: var(--ok-tint);
}

.metric.is-clear strong {
    color: var(--ok);
}

.muted-card {
    opacity: 0.7;
}

/* ------------------------------------------------------------------- tables */

/* Tables carry domains and URLs, so on a narrow screen they scroll inside
   their own box rather than squeezing the page sideways. */
.table-wrap {
    overflow-x: auto;
}

table {
    width: 100%;
    border-collapse: collapse;
}

th,
td {
    padding: 12px 14px;
    border-bottom: 1px solid var(--line);
    text-align: left;
    vertical-align: middle;
}

/* Uppercase mono, as on the site's audit-scope table. Tracking is wide because
   uppercase at 11px sets too tightly to scan otherwise. */
th {
    color: var(--text-soft);
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    white-space: nowrap;
}

thead th {
    border-bottom-color: var(--line-strong);
}

tbody tr:last-child > * {
    border-bottom: 0;
}

tbody tr:hover {
    background: #fafbfc;
}

td.num,
th.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

td .row-title {
    display: block;
    font-weight: 500;
}

td small {
    display: block;
    color: var(--text-faint);
}

/* A table cell has to stay a table cell. The shared `.actions` rule turns its
   element into a flex container, which takes the cell out of the row's layout
   and leaves the row's bottom border broken partway across. */
td.actions {
    display: table-cell;
    text-align: right;
    white-space: nowrap;
}

td.actions > * + * {
    margin-left: 6px;
}

.panel.flush table th:first-child,
.panel.flush table td:first-child {
    padding-left: var(--pad);
}

.panel.flush table th:last-child,
.panel.flush table td:last-child {
    padding-right: var(--pad);
}

/* ------------------------------------------------------------ marketing tag */

/* A recommendation, not a state. It borrows the brand accent rather than any
   band colour: the risk ramp says how much trouble an image is in, and spending
   one of those colours on "most people pick this" is how they stop meaning
   anything. No dot either — the pill next to it is a status, and two identical
   shapes on one row would read as two statuses. */
.badge {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 8px;
    border: 1px solid var(--accent-tint);
    border-radius: 999px;
    background: var(--accent-tint);
    color: var(--accent);
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
    vertical-align: middle;
}

/* -------------------------------------------------------------- status pill */

/* A dot carries the band as well as the colour does, so the label stays in
   sentence case instead of shouting an enum value at the reader. */
.status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px 3px 8px;
    border: 1px solid var(--off-line);
    border-radius: 999px;
    background: var(--off-tint);
    color: var(--off);
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
}

.status::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}

.status.hold {
    color: var(--high);
    background: var(--high-tint);
    border-color: var(--high-line);
}

.status.review {
    color: var(--mid);
    background: var(--mid-tint);
    border-color: var(--mid-line);
}

.status.warning,
.status.running,
.status.pending {
    color: var(--low);
    background: var(--low-tint);
    border-color: var(--low-line);
}

.status.pass,
.status.done {
    color: var(--ok);
    background: var(--ok-tint);
    border-color: var(--ok-line);
}

.status.failed,
.status.error {
    color: var(--high);
    background: var(--high-tint);
    border-color: var(--high-line);
}

.status.running::before {
    animation: pulse 1.6s ease-in-out infinite;
}

@keyframes pulse {
    50% {
        opacity: 0.25;
    }
}

.attention {
    color: var(--high);
    font-weight: 600;
}

/* ------------------------------------------------------------- empty states */

/* "No jobs yet." in a table cell told someone nothing about what to do next.
   Every empty list now says what would fill it and offers the one action. */
.empty {
    padding: 40px 24px;
    text-align: center;
}

.empty-icon {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    margin: 0 auto 14px;
    border-radius: 50%;
    background: var(--sunken);
    color: var(--text-faint);
    font-size: 20px;
}

.empty h2 {
    margin-bottom: 6px;
}

.empty p {
    max-width: 46ch;
    margin: 0 auto 16px;
    color: var(--text-soft);
}

.empty .actions {
    justify-content: center;
}

/* ------------------------------------------------------------------- steps */

/* The scan's stages. Previously five flat boxes, all identical once green,
   with nothing marking where the scan had actually got to. */
.steps {
    display: grid;
    grid-template-columns: repeat(var(--step-count, 5), minmax(0, 1fr));
    gap: 8px;
    margin-bottom: var(--gap);
    padding: 0;
    list-style: none;
    counter-reset: step;
}

.step {
    padding: 12px 14px 12px 0;
    border-top: 2px solid var(--line);
    color: var(--text-faint);
    font-size: 13px;
    font-weight: 500;
}

.step::before {
    counter-increment: step;
    content: counter(step);
    display: inline-grid;
    place-items: center;
    width: 18px;
    height: 18px;
    margin-right: 8px;
    border-radius: 50%;
    background: var(--sunken);
    color: var(--text-faint);
    font-size: 11px;
    font-weight: 600;
    vertical-align: 1px;
}

.step.done {
    border-top-color: var(--ok);
    color: var(--text-soft);
}

.step.done::before {
    content: "✓";
    background: var(--ok-tint);
    color: var(--ok);
}

.step.current {
    border-top-color: var(--accent);
    color: var(--text);
    font-weight: 600;
}

.step.current::before {
    background: var(--accent);
    color: #fff;
}

/* Where the scan stopped. A failure belongs on the stage someone is looking
   for, not only in the pill at the top of the page. */
.step.failed {
    border-top-color: var(--high);
    color: var(--high);
    font-weight: 600;
}

.step.failed::before {
    content: "!";
    background: var(--high-tint);
    color: var(--high);
}

.step-hint {
    display: block;
    margin-top: 2px;
    color: var(--text-faint);
    font-size: 12px;
    font-weight: 400;
}

/* ------------------------------------------------------- progressive detail */

/* Manifest paths, hashes, and raw logs are real debugging material and stay
   available, but they are not what a client's project manager came to read. */
.disclosure {
    margin-top: var(--gap);
    border-top: 1px solid var(--line);
    padding-top: 12px;
}

.disclosure > summary {
    color: var(--text-soft);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
}

.disclosure > summary:hover {
    color: var(--text);
}

.disclosure[open] > summary {
    margin-bottom: 14px;
}

.disclosure.boxed {
    margin: 0 0 var(--gap);
    padding: 14px 18px;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--surface);
}

/* ------------------------------------------------------------------- fields */

.form-panel {
    max-width: 640px;
}

.field {
    display: grid;
    gap: 6px;
    margin-bottom: 16px;
}

.field > span:first-child {
    font-size: 14px;
    font-weight: 500;
}

.field small {
    color: var(--text-soft);
    font-weight: 400;
}

/* A checkbox belongs beside its label, not centred underneath it, which is
   what the grid above did to every "Remember me". */
.field.field-check {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    column-gap: 10px;
    row-gap: 2px;
}

/* Placed explicitly rather than by source order, so the input may be rendered
   before or after its label without the layout changing. */
.field.field-check input[type="checkbox"] {
    grid-column: 1;
    grid-row: 1;
    margin: 0;
}

.field.field-check > span {
    grid-column: 2;
    grid-row: 1;
}

.field.field-check small {
    grid-column: 2;
}

input[type="text"],
input[type="email"],
input[type="url"],
input[type="number"],
input[type="password"],
input[type="search"],
select,
textarea,
input[type="file"] {
    width: 100%;
    min-height: 38px;
    padding: 8px 11px;
    border: 1px solid var(--line-strong);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-size: 14px;
}

input:focus,
select:focus,
textarea:focus {
    border-color: var(--accent);
    outline: none;
    box-shadow: 0 0 0 3px var(--ring);
}

input::placeholder,
textarea::placeholder {
    color: var(--text-faint);
}

input[type="checkbox"] {
    width: 17px;
    height: 17px;
    min-height: 0;
    accent-color: var(--accent);
}

textarea {
    min-height: 64px;
    resize: vertical;
}

.checkbox-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 8px;
}

.checkbox-grid label {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 12px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    font-size: 14px;
    cursor: pointer;
}

.checkbox-grid label:hover {
    border-color: var(--line-strong);
    background: var(--sunken);
}

fieldset.bare {
    margin: 0 0 16px;
    padding: 0;
    border: 0;
}

fieldset.bare > legend {
    padding: 0;
    margin-bottom: 8px;
    font-size: 14px;
    font-weight: 500;
}

.error,
.error-block {
    color: var(--danger);
}

.field .error {
    font-size: 13px;
}

/* ----------------------------------------------------------------- messages */

.messages {
    margin-bottom: var(--gap);
}

.message {
    display: flex;
    gap: 10px;
    padding: 12px 14px;
    margin-bottom: 8px;
    border: 1px solid var(--ok-line);
    border-radius: var(--r-md);
    background: var(--ok-tint);
    color: #05603a;
    font-size: 14px;
}

.message.error {
    border-color: var(--high-line);
    background: var(--high-tint);
    color: #912018;
}

.message.warning {
    border-color: var(--low-line);
    background: var(--low-tint);
    color: #93370d;
}

.message.info {
    border-color: #b9e6fe;
    background: #f0f9ff;
    color: #026aa2;
}

/* A callout inside the page, for a plan limit or a state that needs
   explaining rather than a transient success notice. */
.notice {
    padding: 14px 16px;
    margin-bottom: var(--gap);
    border: 1px solid var(--low-line);
    border-left-width: 3px;
    border-radius: var(--r-md);
    background: var(--low-tint);
    font-size: 14px;
}

.notice > :last-child {
    margin-bottom: 0;
}

.notice.neutral {
    border-color: var(--line);
    border-left-color: var(--line-strong);
    background: var(--sunken);
}

/* ------------------------------------------------------------ definition list */

dl.facts {
    display: grid;
    grid-template-columns: minmax(120px, auto) minmax(0, 1fr);
    gap: 10px 20px;
    margin: 0;
    font-size: 14px;
}

dl.facts dt {
    color: var(--text-soft);
}

dl.facts dd {
    margin: 0;
    overflow-wrap: anywhere;
}

/* A note under a fact, not a continuation of it — inline it ran straight on
   into the value, so "21 times" read as "21 times the strongest sign…". */
dl.facts dd small {
    display: block;
    color: var(--text-faint);
}

/* ------------------------------------------------------------------- images */

.asset-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 14px;
}

/* Thumbnail above the facts rather than beside them: the picture is how
   someone recognises which image this is, and the canonical hash never was. */
.asset-card {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    overflow: hidden;
    background: var(--surface);
    min-width: 0;
}

.asset-card > img,
.asset-card > .thumb-placeholder {
    width: 100%;
    height: 128px;
    object-fit: cover;
    background: var(--sunken);
    border-bottom: 1px solid var(--line);
}

.thumb-placeholder {
    display: grid;
    place-items: center;
    color: var(--text-faint);
    font-size: 12px;
}

.asset-body {
    padding: 10px 12px 12px;
    min-width: 0;
}

.asset-body strong {
    display: block;
    font-size: 14px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.asset-body small,
.asset-body span {
    display: block;
    color: var(--text-soft);
    font-size: 12px;
    overflow-wrap: anywhere;
}

.asset-body .status {
    display: inline-flex;
    margin-top: 6px;
}

.asset-body form {
    margin: 8px 0 0;
}

.table-thumb {
    display: block;
    width: 48px;
    height: 48px;
    object-fit: cover;
    border-radius: var(--r-sm);
    background: var(--sunken);
}

.thumb-placeholder.table-thumb {
    font-size: 11px;
}

.result-layout {
    display: grid;
    grid-template-columns: minmax(260px, 0.85fr) minmax(0, 1.15fr);
    gap: var(--gap);
    align-items: start;
}

.detail-image,
.detail-placeholder {
    display: block;
    width: 100%;
    max-height: 380px;
    object-fit: contain;
    margin-bottom: 14px;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--sunken);
}

.detail-placeholder {
    min-height: 240px;
    display: grid;
    place-items: center;
    color: var(--text-faint);
}

.link-list {
    margin: 0;
    padding-left: 20px;
    font-size: 14px;
}

.link-list li {
    margin-bottom: 8px;
    overflow-wrap: anywhere;
}

.url-list {
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: 14px;
}

.url-list li {
    padding: 7px 0;
    border-bottom: 1px solid var(--line);
    overflow-wrap: anywhere;
}

.url-list li:last-child {
    border-bottom: 0;
}

/* ------------------------------------------------------------------- charts */

.chart-panel {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
    gap: 28px;
    align-items: center;
}

.chart-panel > div:first-child p {
    margin-bottom: 0;
}

.pie-layout {
    display: grid;
    grid-template-columns: 168px minmax(0, 1fr);
    gap: 24px;
    align-items: center;
}

.pie-wrap {
    display: grid;
    place-items: center;
}

.pie-chart {
    width: 168px;
    height: 168px;
}

.pie-bg {
    fill: none;
    stroke: var(--sunken);
    stroke-width: 6;
}

.pie-segment {
    fill: none;
    stroke: var(--segment-color);
    stroke-width: 6;
    stroke-dasharray: var(--dasharray);
    stroke-dashoffset: var(--dashoffset);
    transform: rotate(-90deg);
    transform-origin: 50% 50%;
    transition: stroke-width 140ms ease;
    cursor: default;
}

.pie-segment:hover,
.pie-segment:focus {
    stroke-width: 8;
    outline: none;
}

.pie-total {
    fill: var(--text);
    font-size: 7px;
    font-weight: 700;
}

.pie-caption {
    fill: var(--text-faint);
    font-size: 3px;
    font-weight: 500;
}

.pie-legend {
    display: grid;
    gap: 2px;
}

.legend-item {
    display: grid;
    grid-template-columns: 10px minmax(0, 1fr) auto 48px;
    gap: 10px;
    align-items: center;
    width: 100%;
    min-height: 34px;
    padding: 0 8px;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    background: none;
    color: var(--text-soft);
    font-size: 14px;
    text-align: left;
}

.legend-item:hover {
    background: var(--sunken);
    color: var(--text);
}

.legend-swatch {
    width: 10px;
    height: 10px;
    border-radius: 3px;
    background: var(--legend-color);
}

.legend-item strong {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.legend-item small {
    color: var(--text-faint);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.empty-chart {
    display: grid;
    place-items: center;
    width: 168px;
    height: 168px;
    padding: 20px;
    border-radius: 50%;
    background: var(--sunken);
    color: var(--text-faint);
    font-size: 13px;
    text-align: center;
}

/* A used-quota bar. Replaces an inline-styled div in the billing template. */
.meter {
    height: 8px;
    margin: 12px 0;
    border-radius: 999px;
    background: var(--sunken);
    overflow: hidden;
}

.meter > span {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--ok);
}

.meter.is-over > span {
    background: var(--low);
}

/* -------------------------------------------------------------- pagination */

.pagination {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    margin-top: var(--gap);
    color: var(--text-soft);
    font-size: 13px;
}

/* --------------------------------------------------------- cost of a scan */

/* The one screen where money is committed. It is bordered and tinted so it
   cannot be skimmed past on the way to the approve button. */
.estimate-panel {
    border-color: var(--low-line);
    background: var(--low-tint);
}

.estimate-panel .metric {
    background: var(--surface);
    border-color: var(--low-line);
}

.price-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 14px 0 0;
    margin-top: 14px;
    border-top: 1px solid var(--low-line);
}

.price-row .price {
    font-size: 24px;
    font-weight: 600;
    letter-spacing: -0.02em;
}

/* --------------------------------------------------------- a refused scan */

/* The site said no. Not styled as a crash, because nothing of ours broke and
   the fix is a conversation with whoever runs the site — so it reads as an
   explanation with an action, not as an error to retry into. */
.panel.blocked {
    border-color: var(--low-line);
    border-left: 3px solid var(--low);
    background: var(--low-tint);
}

.panel.blocked h3 {
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid var(--low-line);
}

.panel.blocked dl.facts {
    margin: 12px 0;
}

.panel.blocked code {
    background: var(--surface);
    border: 1px solid var(--low-line);
    font-size: 13px;
    overflow-wrap: anywhere;
}

/* ----------------------------------------------------------------- clients */

.client-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.client-list a {
    display: inline-block;
    padding: 5px 11px;
    border: 1px solid var(--line);
    border-radius: 999px;
    color: var(--text-soft);
    font-size: 13px;
}

.client-list a:hover {
    border-color: var(--line-strong);
    background: var(--sunken);
    color: var(--text);
    text-decoration: none;
}

/* --------------------------------------------------------- recommendations */

.recommendations-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
    gap: 14px;
    margin-top: 14px;
}

.recommendation-card {
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    overflow: hidden;
    background: var(--surface);
    transition: box-shadow 140ms ease, border-color 140ms ease;
}

.recommendation-card:hover {
    border-color: var(--line-strong);
    box-shadow: var(--shadow-lift);
}

.recommendation-card img {
    display: block;
    width: 100%;
    height: 112px;
    object-fit: cover;
    background: var(--sunken);
}

.recommendation-info {
    padding: 10px 12px 12px;
}

.recommendation-info strong {
    display: block;
    margin-bottom: 3px;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.35;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.recommendation-info small {
    display: block;
    margin-bottom: 6px;
    color: var(--text-faint);
    font-size: 12px;
}

/* ----------------------------------------------------------------- pre/logs */

pre {
    overflow: auto;
    max-height: 320px;
    padding: 14px;
    border-radius: var(--r-md);
    background: #101828;
    color: #e4e7ec;
    font-size: 12.5px;
    line-height: 1.5;
}

/* ------------------------------------------------------------ sign-in pages */

.auth-shell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 24px;
    padding: 24px 0;
}

.auth-logo {
    height: 76px;
    width: auto;
}

.auth-panel {
    width: 100%;
    max-width: 400px;
}

.auth-lead {
    margin: 4px 0 20px;
    color: var(--text-soft);
    font-size: 14px;
}

.auth-google {
    width: 100%;
}

.auth-divider {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 18px 0;
    color: var(--text-faint);
    font-size: 13px;
}

.auth-divider::before,
.auth-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--line);
}

.auth-form .form-actions {
    margin-top: 18px;
}

.auth-form .button.primary {
    flex: 1;
}

.auth-alt {
    margin: 18px 0 0;
    color: var(--text-soft);
    font-size: 14px;
}

/* ------------------------------------------------------------- narrow screens */

@media (max-width: 900px) {
    .chart-panel,
    .pie-layout,
    .result-layout {
        grid-template-columns: 1fr;
    }

    .steps {
        grid-template-columns: 1fr;
        gap: 0;
    }

    .step {
        padding: 10px 0 10px 0;
        border-top-width: 1px;
    }
}

@media (max-width: 760px) {
    .app-header {
        flex-wrap: wrap;
        gap: 8px 16px;
        padding: 10px 16px;
    }

    /* Its own row under the brand. `flex: 1 0 100%` rather than `width: 100%`,
       because the base rule's `flex: 1` sets a zero basis that a width cannot
       override — so the nav stayed on the first line, pushed past the account
       menu by `order` alone. */
    .nav-main {
        order: 3;
        flex: 1 0 100%;
        overflow-x: auto;
    }

    .shell {
        width: calc(100% - 28px);
        margin-top: 20px;
    }

    .page-title {
        display: block;
    }

    .page-title .actions {
        margin-top: 14px;
    }

    /* Below this width a data table cannot fit legibly, so it scrolls rather
       than compressing every column into two words per line. */
    .table-wrap table {
        min-width: 560px;
    }

    h1 {
        font-size: 22px;
    }
}
