Files
DemonGatanjieu-Anomalous_Mo…/web/styles/18-scan-page.css
T
DemonGatanjieuandClaude Opus 5.5 4bc559eaa4 Scan page: quick with many models or a network drive; says it is counting
On a cloud server with 1041 models not scanned yet, on the platform's
network model disk, GET /anomalous/scan_summary took 79 s, each time the
page opened, and the page stayed blank meanwhile: it read each new
model's header (for "looks like no drawing model") one after another.

The headers are now read 16 at a time (HEAD_READERS) and through
get_metadata, whose cache keeps each answer until the file changes, so
the page opened again reads none of them and the picker after it finds
them there. Opened afresh, a count slower than 400 ms shows "Counting
your models…" instead of a blank page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:39:15 +08:00

1062 lines
25 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Scan page: the scan card (pictures, button, online or offline), the models' state, what needs a
look, the settings tiles, the last scan, and the list pages behind them. The settings page (ui_settings_page.js) is built from the
same page, card, row, choice and switch rules. */
#anomalous-scan-panel,
#anomalous-settings-panel {
flex: 1;
flex-direction: column;
overflow-y: auto;
background: var(--amb-bg-page, var(--amb-bg-page));
}
.anomalous-scan-page {
display: flex;
flex-direction: column;
gap: 14px;
width: min(760px, 100%);
margin: 0 auto;
padding: 32px 28px 40px;
box-sizing: border-box;
container: scanpage / inline-size;
}
.anomalous-scan-title {
margin: 0;
color: var(--amb-text-main);
font-size: 1.6em;
font-weight: 600;
}
.anomalous-scan-lead {
margin: 0;
color: var(--amb-text-muted);
line-height: 1.6;
}
.anomalous-scan-head {
display: flex;
flex-direction: column;
gap: 6px;
}
.anomalous-scan-about > summary {
align-self: flex-start;
width: fit-content;
color: var(--amb-link);
font-size: 12.5px;
list-style: none;
cursor: pointer;
}
.anomalous-scan-about > summary::-webkit-details-marker {
display: none;
}
.anomalous-scan-about > .anomalous-scan-lead {
margin-top: 8px;
font-size: 13px;
}
.anomalous-scan-icon {
display: inline-flex;
flex-shrink: 0;
width: 18px;
height: 18px;
}
.anomalous-scan-icon > svg {
width: 100%;
height: 100%;
}
/* A section's small heading (the models' state, what needs a look, the settings). */
.anomalous-scan-section-title {
margin: 10px 0 0;
color: var(--amb-text-muted);
font-size: 12.5px;
font-weight: 600;
}
/* The scan card: a band of pictures on top; what is left, the buttons and what the scan does. */
.anomalous-scan-card.anomalous-scan-hero {
gap: 18px;
padding: 20px 24px 22px;
overflow: hidden;
border-color: color-mix(in srgb, var(--amb-link) 28%, var(--amb-border));
background: color-mix(in srgb, var(--amb-link) 5%, transparent);
}
/* Two rows of tiles running to the card's right edge, fading out there. */
.anomalous-scan-band {
--amb-band-tile: 52px;
display: grid;
grid-auto-columns: var(--amb-band-tile);
grid-auto-flow: column;
grid-template-rows: repeat(2, var(--amb-band-tile));
gap: 6px;
margin-right: -24px;
overflow: hidden;
-webkit-mask-image: linear-gradient(to right, #000 62%, transparent);
mask-image: linear-gradient(to right, #000 62%, transparent);
}
.anomalous-scan-band-tile {
display: block;
width: 100%;
height: 100%;
box-sizing: border-box;
border-radius: 10px;
background: rgba(var(--amb-ink-rgb), 0.06);
object-fit: cover;
}
/* A model not scanned yet: an empty frame waiting for its cover. */
.anomalous-scan-band-tile.is-empty {
border: 1.5px dashed color-mix(in srgb, var(--amb-link) 55%, transparent);
background: color-mix(in srgb, var(--amb-link) 7%, transparent);
}
.anomalous-scan-band.is-busy .anomalous-scan-band-tile.is-empty {
animation: anomalous-scan-band-wait 1.4s ease-in-out infinite;
}
@keyframes anomalous-scan-band-wait {
50% { background: color-mix(in srgb, var(--amb-link) 22%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
.anomalous-scan-band.is-busy .anomalous-scan-band-tile.is-empty { animation: none; }
}
/* The counts on their way (many models, or a network drive). */
.anomalous-scan-counting {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: 72px 24px;
text-align: center;
color: var(--amb-text-main);
}
.anomalous-scan-counting p {
margin: 0;
max-width: 420px;
color: var(--amb-text-soft);
line-height: 1.5;
}
.anomalous-scan-counting-icon {
width: 40px;
height: 40px;
color: var(--amb-link);
animation: anomalous-scan-counting 1.4s ease-in-out infinite;
}
@keyframes anomalous-scan-counting {
50% { opacity: 0.35; }
}
@media (prefers-reduced-motion: reduce) {
.anomalous-scan-counting-icon { animation: none; }
}
.anomalous-scan-hero-body {
display: flex;
flex: 1 1 auto;
flex-direction: column;
gap: 4px;
min-width: 0;
}
.anomalous-scan-hero-title {
color: var(--amb-text-main);
font-size: 19px;
font-weight: 600;
}
.anomalous-scan-hero-sub {
margin-bottom: 10px;
color: var(--amb-text-muted);
font-size: 13px;
}
.anomalous-scan-hero .anomalous-scan-actions {
align-items: center;
margin-top: 0;
}
.anomalous-scan-hero-sentence {
display: flex;
flex-wrap: wrap;
align-items: baseline;
gap: 4px 10px;
margin: 0;
color: var(--amb-text-soft);
font-size: 13px;
}
.anomalous-scan-hero-sentence .anomalous-pick-link {
margin-left: 0;
padding: 0;
}
.anomalous-scan-hero-warn {
margin: 6px 0 0;
padding: 6px 10px;
border-radius: 8px;
background: color-mix(in srgb, var(--amb-warn-text) 12%, transparent);
color: var(--amb-warn-text);
font-size: 12.5px;
}
/* Online or offline, at the end of the scan card's buttons. */
.anomalous-scan-mode {
display: inline-flex;
margin-left: auto;
padding: 3px;
border: 1px solid var(--amb-border);
border-radius: 10px;
background: rgba(var(--amb-ink-rgb), 0.03);
}
.anomalous-scan-mode-btn {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
border: none;
border-radius: 7px;
background: transparent;
color: var(--amb-text-muted);
font: inherit;
font-size: 13px;
cursor: pointer;
}
.anomalous-scan-mode-btn .anomalous-scan-icon { width: 16px; height: 16px; }
.anomalous-scan-mode-btn:hover { color: var(--amb-text-main); }
.anomalous-scan-mode-btn.is-on {
background: color-mix(in srgb, var(--amb-link) 18%, transparent);
color: var(--amb-text-main);
font-weight: 600;
}
/* The models' state: a bar of shares, then a chip per state. */
.anomalous-scan-state,
.anomalous-scan-attention,
.anomalous-scan-settings {
display: flex;
flex-direction: column;
gap: 10px;
}
.anomalous-scan-bar {
display: flex;
gap: 2px;
height: 8px;
border-radius: 999px;
background: rgba(var(--amb-ink-rgb), 0.08);
overflow: hidden;
}
.anomalous-scan-bar-part { flex-basis: 0; min-width: 4px; }
.anomalous-scan-bar-part.is-ok, .anomalous-scan-state-chip.is-ok .anomalous-scan-state-dot { background: var(--amb-ok-text); }
.anomalous-scan-bar-part.is-plain, .anomalous-scan-state-chip.is-plain .anomalous-scan-state-dot { background: var(--amb-text-dim); }
.anomalous-scan-bar-part.is-warn, .anomalous-scan-state-chip.is-warn .anomalous-scan-state-dot { background: var(--amb-warn-text); }
.anomalous-scan-bar-part.is-new, .anomalous-scan-state-chip.is-new .anomalous-scan-state-dot { background: var(--amb-link); }
.anomalous-scan-state-chips {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.anomalous-scan-state-chip {
display: inline-flex;
align-items: center;
gap: 7px;
padding: 6px 12px;
border: 1px solid var(--amb-border);
border-radius: 999px;
background: rgba(var(--amb-ink-rgb), 0.03);
color: var(--amb-text-soft);
font: inherit;
font-size: 13px;
}
.anomalous-scan-state-chip strong {
color: var(--amb-text-main);
font-variant-numeric: tabular-nums;
}
.anomalous-scan-state-chip .anomalous-scan-icon { width: 14px; height: 14px; color: var(--amb-text-muted); }
button.anomalous-scan-state-chip { cursor: pointer; }
button.anomalous-scan-state-chip:hover {
border-color: color-mix(in srgb, var(--amb-link) 40%, transparent);
background: rgba(var(--amb-ink-rgb), 0.06);
}
.anomalous-scan-state-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
/* Under the chips: the models left out, as quiet links. */
.anomalous-scan-state-notes {
display: flex;
flex-wrap: wrap;
gap: 4px 16px;
}
.anomalous-scan-quiet-link {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 0;
border: none;
background: none;
color: var(--amb-text-muted);
font: inherit;
font-size: 12.5px;
cursor: pointer;
}
.anomalous-scan-quiet-link .anomalous-scan-icon { width: 14px; height: 14px; }
.anomalous-scan-quiet-link:hover { color: var(--amb-text-main); text-decoration: underline dotted; text-underline-offset: 3px; }
/* The components: apart from the counts, dashed, at the end of the row. */
.anomalous-scan-state-chip.anomalous-scan-parts-chip {
margin-left: auto;
border-style: dashed;
}
/* What needs a look: one row each, a list in one card. */
.anomalous-scan-card.anomalous-scan-attn-list {
gap: 0;
padding: 0;
}
.anomalous-scan-attn {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 12px;
width: 100%;
padding: 11px 16px;
border: none;
border-top: 1px solid var(--amb-border);
background: transparent;
color: var(--amb-text-main);
font: inherit;
font-size: 13.5px;
text-align: left;
}
.anomalous-scan-attn:first-child { border-top: none; }
button.anomalous-scan-attn { cursor: pointer; }
button.anomalous-scan-attn:hover { background: rgba(var(--amb-ink-rgb), 0.04); }
.anomalous-scan-attn-text { flex: 1 1 220px; min-width: 0; line-height: 1.5; }
.anomalous-scan-attn > .anomalous-scan-icon:last-child { color: var(--amb-text-muted); }
.anomalous-scan-attn.is-danger { color: var(--amb-danger-text); }
/* The settings: a tile each, with its icon and switch; the rarer ones folded under them. */
.anomalous-scan-tiles {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 10px;
}
.anomalous-scan-tile {
display: flex;
flex-direction: column;
gap: 6px;
padding: 14px;
border: 1px solid var(--amb-border);
border-radius: 12px;
background: rgba(var(--amb-ink-rgb), 0.03);
}
label.anomalous-scan-tile { cursor: pointer; }
label.anomalous-scan-tile:hover { border-color: color-mix(in srgb, var(--amb-link) 35%, transparent); }
.anomalous-scan-tile.is-dim { opacity: 0.55; }
.anomalous-scan-tile-top {
display: flex;
align-items: center;
gap: 10px;
}
.anomalous-scan-tile-top > .anomalous-scan-icon {
width: 20px;
height: 20px;
color: var(--amb-link);
}
.anomalous-scan-tile-title {
flex: 1 1 auto;
min-width: 0;
color: var(--amb-text-main);
font-size: 14px;
font-weight: 600;
}
.anomalous-scan-more-settings {
padding: 0 16px;
border: 1px solid var(--amb-border);
border-radius: 12px;
}
.anomalous-scan-more-head {
display: flex;
align-items: center;
gap: 8px;
padding: 12px 0;
color: var(--amb-text-soft);
font-size: 13px;
list-style: none;
cursor: pointer;
}
.anomalous-scan-more-head::-webkit-details-marker { display: none; }
.anomalous-scan-more-head::before { content: '›'; display: inline-block; color: var(--amb-text-muted); transition: transform 0.15s ease; }
.anomalous-scan-more-settings[open] > .anomalous-scan-more-head::before { transform: rotate(90deg); }
.anomalous-scan-more-settings > .anomalous-scan-setting-help { display: block; padding-bottom: 12px; }
/* The last scan, at the foot of the page in one line. */
.anomalous-scan-last {
display: flex;
flex-direction: column;
gap: 6px;
margin-top: 6px;
padding-top: 14px;
border-top: 1px solid var(--amb-border);
}
.anomalous-scan-last-line {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 6px 10px;
color: var(--amb-text-muted);
font-size: 13px;
}
.anomalous-scan-last-text { flex: 1 1 260px; min-width: 0; }
.anomalous-scan-last-line .anomalous-pick-link { margin-left: 0; }
/* Narrow (a phone, or docked in the sidebar): smaller pictures, the switches under the buttons. */
@container scanpage (max-width: 560px) {
.anomalous-scan-card.anomalous-scan-hero { padding: 16px 18px 18px; }
.anomalous-scan-band { --amb-band-tile: 44px; gap: 5px; margin-right: -18px; }
.anomalous-scan-mode { margin-left: 0; }
.anomalous-scan-state-chip.anomalous-scan-parts-chip { margin-left: 0; }
}
.anomalous-scan-stats {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 10px;
}
.anomalous-scan-stat {
display: flex;
flex-direction: column;
gap: 4px;
padding: 14px;
border: 1px solid var(--amb-border);
border-radius: 12px;
background: rgba(var(--amb-ink-rgb), 0.03);
font: inherit;
text-align: left;
}
/* Unmatched and not scanned open their list. */
button.anomalous-scan-stat {
cursor: pointer;
}
button.anomalous-scan-stat .anomalous-scan-stat-label::after {
content: ' ›';
}
button.anomalous-scan-stat:hover {
border-color: color-mix(in srgb, var(--amb-link) 40%, transparent);
background: rgba(var(--amb-ink-rgb), 0.06);
}
.anomalous-scan-stat-value {
color: var(--amb-text-main);
font-size: 1.5em;
font-variant-numeric: tabular-nums;
}
.anomalous-scan-stat-label {
color: var(--amb-text-muted);
font-size: 12px;
}
.anomalous-scan-stat.is-ok .anomalous-scan-stat-value { color: var(--amb-ok-text); }
.anomalous-scan-stat.is-warn .anomalous-scan-stat-value { color: var(--amb-warn-text); }
.anomalous-scan-stat.is-new .anomalous-scan-stat-value { color: var(--amb-link); }
.anomalous-scan-actions {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 4px;
}
.anomalous-scan-primary,
.anomalous-scan-secondary {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 10px 18px;
border-radius: 10px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: background 0.15s ease, border-color 0.15s ease, opacity 0.15s ease;
}
.anomalous-scan-primary {
border: 1px solid transparent;
background: var(--amb-btn-primary-bg);
color: var(--amb-btn-primary-text);
}
.anomalous-scan-primary:hover:not(:disabled) {
background: #ffffff;
}
.anomalous-scan-secondary {
border: 1px solid var(--amb-border-strong);
background: rgba(var(--amb-ink-rgb), 0.04);
color: var(--amb-text-main);
}
.anomalous-scan-secondary:hover:not(:disabled) {
border-color: color-mix(in srgb, var(--amb-link) 40%, transparent);
background: rgba(var(--amb-ink-rgb), 0.08);
}
.anomalous-scan-primary:disabled,
.anomalous-scan-secondary:disabled {
opacity: 0.55;
cursor: default;
}
.anomalous-scan-muted {
margin: 0;
color: var(--amb-text-muted);
font-size: 12.5px;
line-height: 1.6;
}
.anomalous-scan-progress-host:empty {
display: none;
}
.anomalous-scan-progress.is-inline {
position: static;
width: auto;
z-index: auto;
box-shadow: none;
backdrop-filter: none;
background: rgba(var(--amb-ink-rgb), 0.03);
}
/* A folded list (Model Check's models that are fine). */
.anomalous-scan-advanced {
border: 1px solid var(--amb-border);
border-radius: 12px;
background: rgba(var(--amb-ink-rgb), 0.02);
}
.anomalous-scan-advanced > summary {
padding: 12px 16px;
color: var(--amb-text-soft);
font-weight: 600;
cursor: pointer;
}
.anomalous-scan-advanced[open] > summary {
border-bottom: 1px solid var(--amb-border);
}
/* The settings page: one card per question. */
.anomalous-scan-group-title {
margin: 0 0 2px;
color: var(--amb-text-muted);
font-size: 12px;
font-weight: 600;
letter-spacing: 0.02em;
}
/* Which models: two choices side by side. */
.anomalous-scan-segment {
display: inline-flex;
flex-wrap: wrap;
flex-shrink: 0;
align-self: flex-start;
gap: 2px;
padding: 3px;
border: 1px solid var(--amb-border);
border-radius: 10px;
background: rgba(var(--amb-ink-rgb), 0.03);
}
.anomalous-scan-segment-btn {
padding: 6px 16px;
border: none;
border-radius: 7px;
background: transparent;
color: var(--amb-text-muted);
font: inherit;
font-size: 13px;
white-space: nowrap;
cursor: pointer;
}
.anomalous-scan-segment-btn:hover {
color: var(--amb-text-main);
}
.anomalous-scan-segment-btn[aria-checked="true"] {
background: color-mix(in srgb, var(--amb-link) 18%, transparent);
color: var(--amb-text-main);
font-weight: 600;
}
/* In the scan card: what a scan of everything does, or the picks. */
.anomalous-scan-scope-facts,
.anomalous-scan-pick {
display: flex;
flex-direction: column;
gap: 8px;
margin-top: 12px;
}
.anomalous-scan-scope-list {
display: flex;
flex-direction: column;
gap: 4px;
margin: 0;
padding-left: 18px;
color: var(--amb-text-soft);
font-size: 13px;
line-height: 1.5;
}
.anomalous-scan-pick-count {
color: var(--amb-text-main);
font-size: 14px;
font-weight: 600;
}
.anomalous-scan-pick-names {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 6px;
}
.anomalous-scan-pick-name {
display: inline-flex;
align-items: center;
gap: 4px;
max-width: 260px;
padding: 3px 4px 3px 10px;
border: 1px solid var(--amb-border-strong);
border-radius: 999px;
background: rgba(var(--amb-ink-rgb), 0.04);
color: var(--amb-text-main);
font-size: 12px;
}
.anomalous-scan-pick-name > span {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.anomalous-scan-pick-remove {
flex-shrink: 0;
width: 20px;
height: 20px;
padding: 0;
border: none;
border-radius: 50%;
background: transparent;
color: var(--amb-text-muted);
font-size: 11px;
cursor: pointer;
}
.anomalous-scan-pick-remove:hover {
background: rgba(var(--amb-ink-rgb), 0.1);
color: var(--amb-text-main);
}
.anomalous-scan-pick-more {
color: var(--amb-text-muted);
font-size: 12px;
}
/* A setting: what it does on the left, its switch or button on the right. */
.anomalous-scan-setting {
display: flex;
align-items: center;
gap: 16px;
padding: 10px 0;
border-top: 1px solid var(--amb-border);
}
label.anomalous-scan-setting {
cursor: pointer;
}
.anomalous-scan-group-title + .anomalous-scan-setting {
padding-top: 4px;
border-top: none;
}
.anomalous-scan-setting-copy {
display: flex;
flex: 1;
flex-direction: column;
gap: 3px;
min-width: 0;
}
.anomalous-scan-setting-title {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
color: var(--amb-text-main);
font-size: 13.5px;
font-weight: 600;
}
.anomalous-scan-setting-help {
color: var(--amb-text-muted);
font-size: 12px;
line-height: 1.55;
}
/* A word beside a title: a warning, or whether the key is set. */
.anomalous-scan-tag {
padding: 1px 8px;
border-radius: 999px;
background: rgba(252, 211, 77, 0.12);
color: var(--amb-warn-text);
font-size: 11px;
font-weight: 600;
}
.anomalous-scan-tag.is-on {
background: rgba(134, 239, 172, 0.12);
color: var(--amb-ok-text);
}
.anomalous-scan-tag.is-off {
background: rgba(var(--amb-ink-rgb), 0.06);
color: var(--amb-text-muted);
}
.anomalous-scan-switch {
position: relative;
flex-shrink: 0;
width: 36px;
height: 20px;
margin: 0;
border-radius: 999px;
background: var(--amb-border-strong);
appearance: none;
-webkit-appearance: none;
cursor: pointer;
transition: background 0.15s ease;
}
.anomalous-scan-switch::before {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: 16px;
height: 16px;
border-radius: 50%;
background: #ffffff;
transition: transform 0.15s ease;
}
.anomalous-scan-switch:checked {
background: var(--amb-link);
}
.anomalous-scan-switch:checked::before {
transform: translateX(16px);
}
.anomalous-scan-switch:focus-visible {
outline: 2px solid color-mix(in srgb, var(--amb-link) 60%, transparent);
outline-offset: 2px;
}
.anomalous-scan-small-btn {
flex-shrink: 0;
padding: 7px 14px;
font-size: 13px;
white-space: nowrap;
}
/* The settings page's sliders (scale, atmosphere) with their value. */
.anomalous-settings-slider {
display: flex;
flex-shrink: 0;
align-items: center;
gap: 10px;
width: min(220px, 45%);
}
.anomalous-settings-slider input {
flex: 1;
min-width: 0;
accent-color: var(--amb-link);
}
.anomalous-settings-slider-value {
width: 40px;
color: var(--amb-text-main);
font-size: 12.5px;
font-variant-numeric: tabular-nums;
text-align: right;
}
/* Settings rows: the control drops under the text when the page is too narrow for both. */
#anomalous-settings-panel .anomalous-scan-setting {
flex-wrap: wrap;
}
#anomalous-settings-panel .anomalous-scan-setting-copy {
flex: 1 1 240px;
}
/* Model folders (ui_folder_manager.js): order buttons and the switch on the right. */
.anomalous-folder-controls {
display: flex;
flex-shrink: 0;
align-items: center;
gap: 6px;
}
.anomalous-folder-move {
width: 26px;
height: 26px;
border: 1px solid var(--amb-border);
border-radius: 7px;
background: transparent;
color: var(--amb-text-soft);
font-size: 13px;
cursor: pointer;
}
.anomalous-folder-move:hover:not(:disabled) {
border-color: color-mix(in srgb, var(--amb-link) 45%, transparent);
color: var(--amb-text-main);
}
.anomalous-folder-move:disabled {
opacity: 0.3;
cursor: default;
}
.anomalous-folder-raw {
color: var(--amb-text-dim);
font-family: ui-monospace, monospace;
font-size: 11px;
}
.anomalous-folder-rare > summary {
padding: 10px 0 4px;
border-top: 1px solid var(--amb-border);
color: var(--amb-text-muted);
font-size: 12.5px;
cursor: pointer;
}
/* A list page's way back to the scan page (and the settings page's way back). */
.anomalous-scan-back {
align-self: flex-start;
margin: -8px 0 -4px -10px;
padding: 4px 10px;
border: none;
border-radius: 8px;
background: none;
color: var(--amb-text-muted);
font: inherit;
font-size: 13px;
cursor: pointer;
}
.anomalous-scan-back:hover {
background: rgba(var(--amb-ink-rgb), 0.05);
color: var(--amb-text-main);
}
/* The scan page's cards: the last scan's summary and a list page's models. */
.anomalous-scan-card {
display: flex;
flex-direction: column;
gap: 8px;
padding: 14px 16px;
border: 1px solid var(--amb-border);
border-radius: 12px;
background: rgba(var(--amb-ink-rgb), 0.02);
}
.anomalous-scan-card-title {
color: var(--amb-text-muted);
font-size: 12.5px;
}
.anomalous-scan-result-counts {
color: var(--amb-text-main);
font-size: 15px;
font-weight: 600;
}
.anomalous-scan-note {
margin: 0;
padding: 8px 10px;
border-radius: 8px;
font-size: 12.5px;
line-height: 1.55;
}
.anomalous-scan-note.is-warn {
background: rgba(252, 211, 77, 0.08);
color: var(--amb-warn-text);
}
.anomalous-scan-note.is-error {
background: rgba(248, 113, 113, 0.08);
color: var(--amb-danger-text);
}
.anomalous-scan-rows {
display: flex;
flex-direction: column;
}
.anomalous-scan-row {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 0;
border-top: 1px solid var(--amb-border);
}
.anomalous-scan-row:first-child {
border-top: none;
}
.anomalous-scan-row-mark {
flex-shrink: 0;
width: 16px;
color: var(--amb-warn-text);
text-align: center;
}
.anomalous-scan-row.is-matched .anomalous-scan-row-mark { color: var(--amb-ok-text); }
.anomalous-scan-row.is-failed .anomalous-scan-row-mark,
.anomalous-scan-row.is-damaged .anomalous-scan-row-mark,
.anomalous-scan-row.is-damaged .anomalous-scan-row-detail { color: var(--amb-danger-text); }
.anomalous-scan-row.is-unchanged .anomalous-scan-row-mark { color: var(--amb-text-muted); }
.anomalous-scan-row-copy {
display: flex;
flex: 1;
flex-direction: column;
gap: 2px;
min-width: 0;
}
.anomalous-scan-row-name,
.anomalous-scan-row-where,
.anomalous-scan-row-detail {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.anomalous-scan-row.is-damaged .anomalous-scan-row-detail { white-space: normal; } /* the advice is read whole */
.anomalous-scan-row-name {
color: var(--amb-text-main);
font-size: 13px;
font-weight: 600;
}
.anomalous-scan-row-where {
color: var(--amb-text-dim);
font-size: 11.5px;
}
.anomalous-scan-row-detail {
color: var(--amb-text-muted);
font-size: 12px;
}
.anomalous-scan-row-actions {
display: flex;
flex-shrink: 0;
gap: 6px;
}
.anomalous-scan-row-btn,
.anomalous-scan-more {
padding: 3px 10px;
border: 1px solid var(--amb-border-strong);
border-radius: 999px;
background: transparent;
color: var(--amb-text-soft);
font-size: 12px;
cursor: pointer;
}
.anomalous-scan-row-btn:hover:not(:disabled),
.anomalous-scan-more:hover {
border-color: color-mix(in srgb, var(--amb-link) 45%, transparent);
color: var(--amb-text-main);
}
.anomalous-scan-row-btn:disabled {
opacity: 0.45;
cursor: default;
}
.anomalous-scan-more {
align-self: flex-start;
margin-top: 8px;
}
@media (max-width: 560px) {
.anomalous-scan-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.anomalous-scan-page { padding: 24px 16px 32px; }
.anomalous-scan-row { flex-wrap: wrap; }
.anomalous-scan-row-actions { width: 100%; padding-left: 26px; }
}