/* =========================================================================
   av_scan — interface stylesheet

   Identity: the AID palette. A flat slate field carries solid panels outlined
   in a hairline, with periwinkle as the single accent. Depth comes from the
   outline, the shadow and the type scale — never from translucency, blur or
   artwork behind the page.

   The rules that keep it coherent:
     1. One dark theme. There is no light mode and no theme switch; every
        surface, ink and seal below is defined once, in section 2.
     2. Two surfaces, one outline. A panel is #1d2129 on the #2a303b field and
        always carries a 1px #3d4556 border. Nested surfaces step up through
        --fill, --fill-2 and --fill-ink rather than stacking more panels.
     3. Space Grotesk is the display face (headings, brand, verdicts), Source
        Sans 3 is the text face, and JetBrains Mono is reserved for machine
        values: hashes, ids, versions, counts.
     4. Periwinkle (--violet) is the only accent. Verdict colours are the one
        other sanctioned palette, and only ever as ink plus a 10% wash.
     5. Print falls back to paper.
   ========================================================================= */


/* -------------------------------------------------------------------------
   1. Self-hosted type (static/fonts/, latin subsets)
   ------------------------------------------------------------------------- */
@font-face {
  font-family: "Source Sans 3";
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url("/static/fonts/source-sans-3.woff2") format("woff2");
}
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("/static/fonts/space-grotesk.woff2") format("woff2");
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/static/fonts/jetbrains-mono.woff2") format("woff2");
}

/* -------------------------------------------------------------------------
   2. Tokens — one theme: the AID palette

   The interface is dark and only dark. A flat slate field (#2a303b) carries
   solid panels (#1d2129) outlined in #3d4556, with periwinkle (#a6afff) as the
   single accent. Surfaces are opaque: there is no glass, no blur and no colour
   field behind the page, so every surface below is a colour rather than a
   translucent wash.

   Type: Space Grotesk for display, Source Sans 3 for text, JetBrains Mono for
   machine values — hashes, ids, versions, counts.
   ------------------------------------------------------------------------- */
:root {
  color-scheme: dark;

  /* the field. One flat slate: nothing sits behind a surface to refract. */
  --field-1: #2a303b;
  --field-2: #2a303b;
  --field-3: #2a303b;
  --bloom-violet: transparent;
  --bloom-cyan:   transparent;
  --bloom-amber:  transparent;

  /* Surfaces. "glass" keeps its name so the components that reference it do not
     have to change; it is simply an opaque panel now. */
  --glass:        #1d2129;    /* panel / card surface */
  --glass-strong: #1d2129;    /* masthead, menus — the same solid surface */
  --glass-line:   transparent; /* a flat surface has no specular top edge */
  --glass-edge:   #3d4556;    /* the hairline outline every surface carries */
  --rule-strong:  #566091;    /* heavier rule: borders of dashed fields */
  --blur: 0px;
  --saturate: 100%;

  /* nested surfaces, from the field upward */
  --fill:     #262c37;  /* a raised or hovered row */
  --fill-2:   #2a303b;  /* a field set into a panel */
  --fill-ink: #343c4b;  /* the strongest fill: pressed, selected, chips */

  /* ink */
  --ink:        #e6eaf5;
  --ink-strong: #ffffff;   /* headings and the wordmark */
  --ink-2:      #c9d1e3;
  --ink-3:      #aab3c8;

  /* brand: periwinkle */
  --violet:      #a6afff;
  --violet-2:    #c4caff;
  --violet-wash: rgba(166, 175, 255, 0.12);
  --violet-rule: rgba(166, 175, 255, 0.42);
  --on-violet:   #1d2129;

  /* verdict chips: each ink on a 10% wash of itself */
  --seal-malicious:  #ff9fb2;
  --seal-suspicious: #ffd166;
  --seal-clean:      #7fe0b4;
  --seal-unknown:    #b4bdd3;
  --wash-malicious:  rgba(255, 159, 178, 0.10);
  --wash-suspicious: rgba(255, 209, 102, 0.10);
  --wash-clean:      rgba(127, 224, 180, 0.10);
  --wash-unknown:    rgba(180, 189, 211, 0.08);
  --seal-edge:       #3d4556;

  /* the instrument readout: an inset slate inside a panel */
  --panel:       #2a303b;
  --panel-ink:   #e6eaf5;
  --panel-ink-2: #aab3c8;
  --panel-rule:  #3d4556;

  --focus: #ffffff;

  /* checkmark shape, used as a mask so it inherits the theme's ink */
  --tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 14'%3E%3Cpath d='M1.5 7.5 6 12 14.5 2' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

  --sans: "Source Sans 3", system-ui, -apple-system, "Segoe UI", sans-serif;
  --display: "Space Grotesk", var(--sans);
  --mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* Measured by the shell script: the masthead wraps to two rows on narrower
     desktops, and it slides away entirely once you scroll into a report. Every
     sticky offset and anchor jump follows this, so it is 0 while it is away.
     The value here is only the pre-script fallback. */
  --masthead-offset: 58px;

  /* The masthead's capsule floats 16px off the top of the page (see .topbar).
     Anything else that sticks keeps this much air from whatever it sticks
     under — the viewport edge when the masthead has retracted, the masthead
     itself when it has not — so the chrome reads as one floating layer rather
     than one piece glued to the screen. */
  --float-gap: 10px;

  --measure: 62ch;
  --maxw: 1160px;
  --gap: 22px;

  /* radius scale — hierarchy, not one value everywhere */
  --r-bar: 28px;      /* the masthead capsule */
  --r-panel: 20px;
  --r-inner: 12px;
  --r-control: 12px;
  --r-pill: 999px;

  --shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
  --shadow-sm: 0 4px 14px rgba(0, 0, 0, 0.25);
}


/* -------------------------------------------------------------------------
   3. Reset, field, type
   ------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* masthead + the pinned index's own height (~58px) + the air above it. The
     reservation has to clear the bar's *bottom* edge, or a jump to a section
     lands with its heading tucked behind the bar. */
  scroll-padding-top: calc(var(--masthead-offset) + 60px + var(--float-gap));
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink);
  /* one flat slate — surfaces sit on it, nothing glows through it */
  background-color: var(--field-2);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  margin: 0 0 0.4em;
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--ink-strong);
}
h1 { font-size: 1.75rem; }
h2 { font-size: 1.25rem; }
h3 { font-size: 1.05rem; }
p  { margin: 0 0 0.8em; max-width: var(--measure); }

a { color: var(--violet); text-decoration: none; }
a:hover { color: var(--ink-strong); }

.small { font-size: 0.85rem; }

code, kbd, samp, .mono, .hash, .scan-id {
  font-family: var(--mono);
  font-size: 0.86em;
  font-variant-ligatures: none;
}
.hash { color: var(--ink); word-break: break-all; }

.muted { color: var(--ink-2); }
.mute  { color: var(--ink-3); }
.center { text-align: center; }
.nowrap { white-space: nowrap; }
.truncate {
  display: inline-block;
  max-width: 34ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}
.accent { color: var(--violet); }
.spacer { flex: 1 1 auto; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

hr { border: 0; border-top: 1px solid var(--glass-edge); margin: 1.6rem 0; }

:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; border-radius: 4px; }
::selection { background: var(--violet-wash); color: var(--ink); }

pre {
  margin: 0 0 1em;
  padding: 14px 16px;
  background: var(--fill);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-inner);
  overflow-x: auto;
  font-size: 0.85rem;
  line-height: 1.55;
}
pre code { font-size: inherit; }

/* -------------------------------------------------------------------------
   4. The material

   One opaque surface, repeated. Every container — panel, card, sheet, menu,
   masthead — is the same solid #1d2129 with a 1px #3d4556 outline, so depth
   comes from the outline and the shadow rather than from translucency. Nothing
   blurs: there is no colour field behind the page to refract.
   ------------------------------------------------------------------------- */
.glass,
.card,
.run-sheet,
.stat,
.pack,
.balance-card,
.auth-card,
.status-panel,
.user-menu-panel,
.verdict-banner,
.topbar,
.report-tabs {
  background: var(--glass);
  border: 1px solid var(--glass-edge);
  box-shadow: var(--shadow);
}

/* -------------------------------------------------------------------------
   5. Layout
   ------------------------------------------------------------------------- */
.page { position: relative; z-index: 1; flex: 1 0 auto; padding: 30px 0 68px; }
.container { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 24px; }

.grid { display: grid; gap: var(--gap); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.row-between {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.page-head { margin: 0 0 20px; }
.page-head h1 { margin-bottom: 2px; }
.page-head .sub { color: var(--ink-2); margin: 0; }

.section-title { margin: 40px 0 18px; max-width: var(--measure); }
.section-title h2 { margin-bottom: 4px; }
.section-title p { color: var(--ink-2); margin: 0; }

.rule-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  padding-bottom: 8px;
  margin-bottom: 16px;
  border-bottom: 2px solid var(--glass-edge);
}
.rule-head h2, .rule-head h3 { margin: 0; }

/* -------------------------------------------------------------------------
   6. Masthead
   ------------------------------------------------------------------------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 60;
  /* The masthead is a floating capsule: transparent bar, opaque panel inside.
     The 16px top padding is the float gap and is measured into
     --masthead-offset, so every sticky offset follows it. */
  padding: 16px 16px 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  /* retracts when you scroll into a report so the section bar can take over */
  transition: transform 360ms cubic-bezier(0.22, 0.61, 0.36, 1), opacity 240ms ease;
  will-change: transform;
}
.topbar.is-hidden { transform: translateY(-100%); opacity: 0; pointer-events: none; }

/* Set by the report script for the first frame after load, while it applies the
   state the current scroll position implies. Without it, a reload part-way down
   a report paints the retracted bar and then animates into place — and the report
   reloads itself every 5s while a scan is running, so the whole retract replays
   on a timer. Only the initial paint is ever instant; scrolling still morphs. */
.no-morph .topbar,
.no-morph .report-tabs { transition: none !important; }

.topbar-inner {
  display: flex;
  align-items: center;
  gap: 12px 24px;
  /* the row is allowed to wrap; the shell measures whatever height results and
     every sticky offset follows it */
  flex-wrap: wrap;
  min-height: 64px;
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 10px 20px;
  background: var(--glass);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-bar);
  box-shadow: var(--shadow);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  flex: 0 0 auto;
  min-height: 44px;
  color: var(--ink-strong);
  font-family: var(--display);
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}
.brand:hover { color: var(--ink-strong); text-decoration: none; }
.brand-mark { display: block; flex: 0 0 auto; color: var(--violet); }
.brand .cursor { color: var(--violet-2); }
.brand-sub {
  display: none;
  padding-left: 10px;
  border-left: 1px solid var(--glass-edge);
  font-family: var(--sans);
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--ink-3);
}
@media (min-width: 1500px) { .brand-sub { display: inline; } }

.nav-links { display: flex; align-items: center; gap: 4px; flex-wrap: nowrap; }
.nav-links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 12px;
  border-radius: var(--r-inner);
  white-space: nowrap;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink-2);
}
.nav-links a:hover { color: var(--ink-strong); background: var(--fill-ink); text-decoration: none; }
.nav-links a.active,
.nav-links a[aria-current="page"] {
  color: var(--ink-strong);
  background: var(--fill-ink);
}

.top-search {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 150px;
  min-width: 0;
  max-width: 190px;
  padding: 0 12px;
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-pill);
  background: var(--fill);
  color: var(--ink-3);
}
.top-search:focus-within { border-color: var(--violet-rule); background: var(--fill); }
.top-search input[type="search"] {
  width: 100%;
  padding: 7px 0;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: 0.88rem;
  color: var(--ink);
}
.top-search input[type="search"]:focus { outline: none; }
.top-search input::placeholder { color: var(--ink-3); }

.nav-user { display: flex; align-items: center; gap: 8px; margin-left: auto; }

.credit-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 12px;
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-pill);
  background: var(--fill);
  font-size: 0.82rem;
  color: var(--ink-2);
  white-space: nowrap;
}
a.credit-chip:hover { border-color: var(--violet-rule); color: var(--ink); text-decoration: none; }
.credit-chip .val { font-family: var(--mono); font-size: 0.9rem; color: var(--ink); }
.credit-chip .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--seal-clean); }

.user-menu { position: relative; }
.user-menu > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px 4px 5px;
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-pill);
  background: var(--fill);
  cursor: pointer;
  list-style: none;
  font-size: 0.84rem;
  color: var(--ink-2);
}
.user-menu > summary::-webkit-details-marker { display: none; }
.user-menu > summary:hover,
.user-menu[open] > summary { border-color: var(--violet-rule); color: var(--ink); }
.user-menu .user-avatar {
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--violet);
  color: var(--on-violet);
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
}
.nav-email { max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  z-index: 70;
  min-width: 230px;
  padding: 14px;
  border-radius: var(--r-inner);
}
.user-menu-panel .user-menu-email { font-family: var(--mono); font-size: 0.84rem; overflow-wrap: anywhere; }
.user-menu-panel form { margin-top: 12px; }
.user-menu-panel .btn { width: 100%; justify-content: center; }

/* -------------------------------------------------------------------------
   7. Footer
   ------------------------------------------------------------------------- */
.site-foot {
  flex: 0 0 auto;
  padding: 18px 0;
  border-top: 1px solid var(--glass-edge);
  font-size: 0.85rem;
  color: var(--ink-3);
}
.site-foot .container { display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; }

/* -------------------------------------------------------------------------
   8. Controls
   ------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 18px;
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-control);
  background: var(--fill);
  color: var(--ink);
  font: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  cursor: pointer;
}
.btn:hover { border-color: var(--violet-rule); color: var(--ink); text-decoration: none; }
.btn-primary {
  background: var(--violet);
  border-color: transparent;
  color: var(--on-violet);
  box-shadow: var(--shadow-sm);
}
.btn-primary:hover { background: var(--violet-2); color: var(--on-violet); }
.btn-danger { color: var(--seal-malicious); border-color: var(--seal-edge); }
.btn-danger:hover { background: var(--wash-malicious); color: var(--seal-malicious); border-color: var(--seal-malicious); }
.btn-ghost { background: transparent; border-color: transparent; box-shadow: none; color: var(--ink-2); }
.btn-ghost:hover { background: var(--fill); border-color: var(--glass-edge); color: var(--ink); }
.btn-sm { min-height: 34px; padding: 0 12px; font-size: 0.85rem; border-radius: var(--r-inner); }
.btn-lg { min-height: 52px; padding: 0 28px; font-size: 1.05rem; }
.btn-block { width: 100%; }

/* -------------------------------------------------------------------------
   9. Forms
   ------------------------------------------------------------------------- */
.form { display: grid; gap: 16px; max-width: 560px; }
.field { display: grid; gap: 5px; }
.field > label { font-size: 0.9rem; font-weight: 500; }

/* One surface for every control, so a text box, a dropdown and a file picker
   are the same material at the same height. */
input[type="text"], input[type="email"], input[type="password"],
input[type="number"], input[type="search"], input[type="tel"], input[type="url"],
input[type="date"], input[type="time"], input[type="file"], select, textarea {
  width: 100%;
  padding: 12px 14px;
  min-height: 48px;
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-control);
  background: var(--fill-2);
  box-shadow: none;
  color: var(--ink);
  font: inherit;
  font-size: 0.92rem;
  transition: border-color 150ms ease, background-color 150ms ease, box-shadow 150ms ease;
}
textarea { min-height: 88px; resize: vertical; line-height: 1.5; }
input::placeholder, textarea::placeholder { color: var(--ink-3); }
input:hover:not(:disabled), textarea:hover:not(:disabled), select:hover:not(:disabled) {
  border-color: var(--violet-rule);
}
input:focus, select:focus, textarea:focus {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-color: var(--focus);
  background: var(--fill-2);
}
input:disabled, select:disabled, textarea:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
/* a control the browser refused to validate should say so before submit */
input:not(:placeholder-shown):invalid, textarea:not(:placeholder-shown):invalid {
  border-color: var(--seal-malicious);
}

/* ---- select: the native arrow ignores the palette, so draw ours ---------- */
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 34px;
  background-image: var(--chevron);
  background-repeat: no-repeat;
  background-position: right 11px center;
  background-size: 11px 7px;
  cursor: pointer;
}
select:disabled { cursor: not-allowed; }

/* ---- number: spin buttons are the last native chrome on the page --------- */
input[type="number"] { appearance: textfield; -moz-appearance: textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ---- file: the one control still wearing the OS's grey button ------------ */
input[type="file"] {
  padding: 6px;
  cursor: pointer;
}
input[type="file"]::file-selector-button {
  margin-right: 14px;
  min-height: 36px;
  padding: 0 16px;
  border: 0;
  border-radius: 8px;
  background: var(--fill-ink);
  color: var(--ink-strong);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 150ms ease, background-color 150ms ease;
}
input[type="file"]::file-selector-button:hover { border-color: var(--violet-rule); }
input[type="file"]:hover { border-color: var(--violet-rule); }

/* The masthead search is a bare field inside its own glass shell, so it opts
   out of the control surface above. */
.top-search input[type="search"],
.top-search input[type="search"]:hover,
.top-search input[type="search"]:focus {
  padding: 7px 0;
  border: 0;
  background: transparent;
  box-shadow: none;
  outline: none;
}

.hint { font-size: 0.83rem; color: var(--ink-3); max-width: var(--measure); }


.inline-form { display: flex; gap: 6px; align-items: center; }
.inline-form input { width: 84px; padding: 5px 8px; font-size: 0.84rem; }
.inline-form input[name="reason"] { width: 120px; }

/* -------------------------------------------------------------------------
   10. Panels
   ------------------------------------------------------------------------- */
.card { padding: 20px; border-radius: var(--r-panel); }
.card-lg { padding: 26px; }
.card-flush { padding: 0; overflow: hidden; }
/* the accent border-top our cards used to draw is now the component's rim */
.card, .stat, .pack, .balance-card, .auth-card, .run-sheet { border-top: 0; }
.card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  padding: 15px 20px;
  border-bottom: 1px solid var(--glass-edge);
}
.card-head h2, .card-head h3 { margin: 0; }
.card-body { padding: 20px; }

.panel { padding: 15px 17px; }

.stat {
  padding: 15px 17px;
  border-radius: var(--r-inner);
  border-left: 3px solid var(--glass-edge);
}
.stat .label, .stat-label { font-size: 0.83rem; color: var(--ink-2); margin-bottom: 4px; }
.stat .value {
  font-family: var(--mono);
  font-size: 1.85rem;
  font-weight: 500;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.stat .hint { margin-top: 4px; font-size: 0.83rem; color: var(--ink-3); }
.stat.bad    { border-left-color: var(--seal-malicious); }
.stat.bad .value    { color: var(--seal-malicious); }
.stat.warn   { border-left-color: var(--seal-suspicious); }
.stat.warn .value   { color: var(--seal-suspicious); }
.stat.clean  { border-left-color: var(--seal-clean); }
.stat.clean .value  { color: var(--seal-clean); }
.stat.accent { border-left-color: var(--violet); }
.stat.accent .value { color: var(--violet); }

.empty { padding: 40px 20px; text-align: center; color: var(--ink-2); }
.empty h3 { margin-bottom: 4px; }
.empty p { margin: 0 auto; max-width: 42ch; font-size: 0.9rem; }

/* -------------------------------------------------------------------------
   11. State tokens
   ------------------------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border: 1px solid var(--seal-edge);
  border-radius: var(--r-pill);
  background: var(--fill);
  color: var(--ink-2);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.015em;
  white-space: nowrap;
}
/* state tokens are the one place uppercase earns its keep; a plain badge is a
   user-supplied label, so it keeps the case it was written in */
.badge-malicious, .badge-suspicious, .badge-clean, .badge-undetected,
.badge-unknown, .badge-unsupported, .badge-error, .badge-inconclusive,
.badge-queued, .badge-running, .badge-done { text-transform: uppercase; }

.badge-malicious  { color: var(--seal-malicious);  background: var(--wash-malicious);  border-color: var(--seal-malicious); }
.badge-suspicious { color: var(--seal-suspicious); background: var(--wash-suspicious); border-color: var(--seal-suspicious); }
.badge-clean,
.badge-undetected { color: var(--seal-clean);      background: var(--wash-clean);      border-color: var(--seal-clean); }
.badge-unknown,
.badge-unsupported,
.badge-error,
.badge-inconclusive,
.badge-grey       { color: var(--seal-unknown);    background: var(--wash-unknown);    border-color: var(--seal-edge); }
.badge-queued,
.badge-running    { color: var(--violet);          background: var(--violet-wash);     border-color: var(--violet-rule); }
.badge-done       { color: var(--seal-clean);      background: var(--wash-clean);      border-color: var(--seal-clean); }
.badge-plain      { color: var(--ink-2); }

.dot-ind {
  width: 8px; height: 8px;
  border-radius: 50%;
  flex: 0 0 auto;
  background: var(--seal-unknown);
}
.dot-ind.malicious  { background: var(--seal-malicious); }
.dot-ind.suspicious { background: var(--seal-suspicious); }
.dot-ind.clean,
.dot-ind.undetected { background: var(--seal-clean); }

.av-list { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
.av-chip {
  padding: 3px 10px;
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-pill);
  background: var(--fill);
  font-size: 0.8rem;
  color: var(--ink-2);
}

/* -------------------------------------------------------------------------
   12. Banners
   ------------------------------------------------------------------------- */
.banner {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 13px 15px;
  border: 1px solid var(--glass-edge);
  border-left: 4px solid var(--glass-edge);
  border-radius: var(--r-inner);
  background: var(--fill);
  font-size: 0.9rem;
}
.banner-body { flex: 1 1 auto; min-width: 0; }
.banner-title { font-weight: 600; margin-bottom: 1px; }
.banner p { margin: 0; max-width: var(--measure); }
.banner-error   { border-left-color: var(--seal-malicious);  background: var(--wash-malicious); }
.banner-error .banner-title { color: var(--seal-malicious); }
.banner-warn    { border-left-color: var(--seal-suspicious); background: var(--wash-suspicious); }
.banner-warn .banner-title { color: var(--seal-suspicious); }
.banner-success { border-left-color: var(--seal-clean);      background: var(--wash-clean); }
.banner-success .banner-title { color: var(--seal-clean); }
.banner-info    { border-left-color: var(--violet);          background: var(--violet-wash); }
.banner-info .banner-title { color: var(--violet); }

.legend { margin: 8px 0 0; font-size: 0.83rem; color: var(--ink-3); max-width: var(--measure); }
.retry-link { font-size: 0.82rem; white-space: nowrap; }

/* -------------------------------------------------------------------------
   13. Tables
   ------------------------------------------------------------------------- */
.table-wrap { width: 100%; overflow-x: auto; }

table.data { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
table.data th {
  text-align: left;
  padding: 10px 16px;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink-2);
  background: var(--fill-2);
  border-bottom: 1px solid var(--glass-edge);
  white-space: nowrap;
}
table.data td { padding: 10px 16px; border-bottom: 1px solid var(--glass-edge); vertical-align: top; }
table.data tbody tr:last-child td { border-bottom: 0; }
table.data tbody tr:hover { background: var(--fill-2); }
table.data a.row-link { color: var(--ink); font-weight: 500; }
table.data a.row-link:hover { color: var(--violet); text-decoration: none; }
td.num, th.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* -------------------------------------------------------------------------
   14. Landing
   ------------------------------------------------------------------------- */
.hero { padding: 56px 0 40px; max-width: 960px; }
.hero h1 { font-size: clamp(2.75rem, 6.5vw, 5.25rem); line-height: 1.02; letter-spacing: -0.02em; margin-bottom: 18px; }
.hero .lede { font-size: 1.3rem; line-height: 1.55; color: var(--ink-2); max-width: 32em; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 4px 13px 4px 10px;
  margin-bottom: 20px;
  border: 1px solid var(--violet-rule);
  border-radius: var(--r-pill);
  background: var(--violet-wash);
  box-shadow: inset 0 1px 0 var(--glass-line);
  color: var(--violet);
  font-size: 0.85rem;
  font-weight: 500;
}
.hero-actions { display: flex; gap: 10px; flex-wrap: wrap; margin: 22px 0 30px; }

.engine-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 12px 14px;
}
.engine-chip {
  padding: 2px 10px;
  border-radius: var(--r-pill);
  background: var(--fill-2);
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--ink-2);
}

.steps { margin: 0; padding: 0; list-style: none; counter-reset: step; max-width: 68ch; }
.steps > li {
  position: relative;
  counter-increment: step;
  padding: 0 0 16px 42px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--glass-edge);
}
.steps > li:last-child { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }
.steps > li::before {
  content: counter(step, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 2px;
  font-family: var(--mono);
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--violet);
}
.steps h3 { margin-bottom: 2px; }
.steps p { margin: 0; }

/* The FAQ: one question per rule, answered in place. Scoped to .faq so it never
   touches the account menu or the engine group summaries, which are details
   elements too. */
.faq details { border-bottom: 1px solid var(--glass-edge); }
.faq summary {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 16px 0;
  font-family: var(--display);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink-strong);
  cursor: pointer;
  list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--violet); }
.faq details p { margin: 0 0 20px; max-width: 62ch; color: var(--ink-2); }

/* -------------------------------------------------------------------------
   15. Auth
   ------------------------------------------------------------------------- */
.auth-wrap { max-width: 410px; margin: 44px auto 0; }
.auth-card { padding: 26px; border-radius: var(--r-panel); }
.auth-card h1 { font-size: 1.3rem; }
.auth-card .sub { color: var(--ink-2); margin-bottom: 20px; }
.auth-foot { margin-top: 16px; text-align: center; font-size: 0.88rem; color: var(--ink-2); }
.auth-mark {
  display: flex;
  justify-content: center;
  padding-bottom: 16px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--glass-edge);
}

/* -------------------------------------------------------------------------
   16. Report
   ------------------------------------------------------------------------- */
.task-head { align-items: flex-start; }

/* zero-height sentinel: docking triggers when this scrolls under the masthead */
.tabs-anchor { height: 1px; margin-bottom: -1px; }

/* Section index. At rest it is a slim pill row under the header; once the
   header has scrolled away it docks and becomes the page hero — bigger, more
   opaque, and carrying the sample identity so context is never lost. The morph
   is pure CSS; the script only toggles .is-docked. */
.report-tabs {
  position: sticky;
  top: calc(var(--masthead-offset) + var(--float-gap));
  z-index: 55;
  display: flex;
  align-items: center;
  gap: 0;
  margin: 0 0 22px;
  padding: 4px;
  overflow: hidden;
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-pill);
  background: var(--glass);
  box-shadow: var(--shadow-sm);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  backdrop-filter: blur(14px) saturate(160%);
  transition:
    top 360ms cubic-bezier(0.22, 0.61, 0.36, 1),
    padding 480ms cubic-bezier(0.22, 0.61, 0.36, 1),
    background-color 380ms ease,
    border-color 380ms ease,
    box-shadow 380ms ease,
    border-radius 480ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.report-tabs.is-docked {
  padding: 7px;
  border-radius: var(--r-panel);
  background: var(--glass-strong);
  border-color: var(--violet-rule);
  box-shadow: var(--shadow);
}
/* pinned = the masthead has retracted and this bar is now the top of the page */
.report-tabs.is-pinned {
  top: var(--float-gap);
  padding: 9px 9px 9px 14px;
  border-color: var(--violet-rule);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
}
/* the mark only appears once the bar has become the page's top chrome */
.tabs-brand {
  display: grid;
  grid-template-columns: 0fr;
  opacity: 0;
  transition:
    grid-template-columns 520ms cubic-bezier(0.22, 0.61, 0.36, 1),
    opacity 320ms ease,
    margin-right 520ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.report-tabs.is-pinned .tabs-brand {
  grid-template-columns: 1fr;
  opacity: 1;
  margin-right: 12px;
}
.tabs-brand-inner {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  overflow: hidden;
  padding-right: 12px;
  border-right: 1px solid var(--glass-edge);
  white-space: nowrap;
  font-family: var(--mono);
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--ink);
}

.tabs-links {
  display: flex;
  align-items: center;
  gap: 3px;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs-links::-webkit-scrollbar { display: none; }

.report-tabs a {
  padding: 6px 14px;
  border-radius: var(--r-pill);
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--ink-2);
  white-space: nowrap;
  transition: background-color 260ms ease, color 260ms ease, padding 480ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.report-tabs.is-docked a { padding: 8px 16px; }
.report-tabs a:hover { color: var(--ink); background: var(--fill-ink); text-decoration: none; }
.report-tabs a.is-active,
.report-tabs a[aria-current="true"] {
  color: var(--violet);
  background: var(--violet-wash);
  box-shadow: inset 0 1px 0 var(--glass-line);
}

/* the identity block that slides open on dock. Animating grid-template-columns
   from 0fr to 1fr is what keeps this smooth without measuring anything. */
.tabs-hero {
  display: grid;
  grid-template-columns: 0fr;
  opacity: 0;
  margin-left: 0;
  transition:
    grid-template-columns 520ms cubic-bezier(0.22, 0.61, 0.36, 1),
    opacity 320ms ease,
    margin-left 520ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.report-tabs.is-docked .tabs-hero {
  grid-template-columns: 1fr;
  opacity: 1;
  margin-left: 12px;
}
.tabs-hero-inner {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
}
.tabs-hero-name {
  font-weight: 500;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 30ch;
}
.tabs-hero-score {
  font-family: var(--mono);
  font-size: 0.88rem;
  color: var(--ink-2);
}
.tabs-hero-score .den { color: var(--ink-3); font-size: 0.8rem; }

/* reading progress, drawn along the bottom edge of the docked bar */
.tabs-progress {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 2px;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--violet), var(--violet-2));
  opacity: 0;
  transition: opacity 380ms ease;
}
.report-tabs.is-docked .tabs-progress { opacity: 1; }

@media (max-width: 1150px) {
  .tabs-brand, .report-tabs.is-pinned .tabs-brand { display: none; }
}

@media (max-width: 900px) {
  /* the index is not sticky here, so there is nothing to dock to */
  .tabs-hero, .report-tabs.is-docked .tabs-hero { display: none; }
  .report-tabs.is-pinned { padding: 4px; border-radius: var(--r-pill); }
  .report-tabs.is-docked {
    padding: 4px;
    border-radius: var(--r-pill);
    border-color: var(--glass-edge);
    background: var(--glass);
    box-shadow: var(--shadow-sm);
  }
  .report-tabs.is-docked a, .report-tabs.is-pinned a { padding: 6px 14px; }
  .tabs-progress { display: none; }
}

.status-panel {
  display: flex;
  align-items: flex-start;
  gap: 13px;
  padding: 16px 18px;
  margin-bottom: 22px;
  border-radius: var(--r-panel);
  border-left: 4px solid var(--violet);
}
.spinner {
  flex: 0 0 auto;
  width: 16px; height: 16px;
  margin-top: 4px;
  border: 2px solid var(--violet-rule);
  border-top-color: var(--violet);
  border-radius: 50%;
  animation: av-spin 0.9s linear infinite;
}
@keyframes av-spin { to { transform: rotate(360deg); } }

/* --- verdict stamp --- */
.verdict-banner {
  display: flex;
  align-items: stretch;
  margin-bottom: 22px;
  border: 1px solid var(--glass-edge);
  border-left: 6px solid var(--seal-unknown);
  border-radius: var(--r-panel);
  background: var(--glass);
  box-shadow: var(--shadow);
  overflow: hidden;
  -webkit-backdrop-filter: blur(var(--blur)) saturate(var(--saturate));
  backdrop-filter: blur(var(--blur)) saturate(var(--saturate));
}
.verdict-main { flex: 1 1 auto; min-width: 0; padding: 20px 22px; }
.verdict-banner .verdict-label { font-size: 0.83rem; font-weight: 500; color: var(--ink-2); }
.verdict-banner .verdict-word {
  display: flex;
  align-items: center;
  gap: 11px;
  margin: 2px 0 8px;
  font-size: clamp(1.6rem, 3.2vw, 2.15rem);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.05;
  color: var(--seal-unknown);
}
.verdict-banner .verdict-note { font-size: 0.94rem; color: var(--ink-2); margin: 0; }
.verdict-why {
  margin: 10px 0 0;
  padding-left: 11px;
  border-left: 2px solid var(--glass-edge);
  font-size: 0.85rem;
  color: var(--ink-3);
  max-width: var(--measure);
}

.verdict-malicious  { border-left-color: var(--seal-malicious); }
.verdict-malicious  .verdict-word { color: var(--seal-malicious); }
.verdict-suspicious { border-left-color: var(--seal-suspicious); }
.verdict-suspicious .verdict-word { color: var(--seal-suspicious); }
.verdict-clean      { border-left-color: var(--seal-clean); }
.verdict-clean      .verdict-word { color: var(--seal-clean); }
.verdict-unknown,
.verdict-grey       { border-left-color: var(--seal-unknown); }
.verdict-unknown    .verdict-word { color: var(--seal-unknown); }

/* the score is an instrument reading: dark glass in either theme */
.verdict-score {
  flex: 0 0 auto;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 2px;
  min-width: 152px;
  padding: 18px 22px;
  background: var(--panel);
  border-left: 1px solid var(--glass-edge);
  box-shadow: inset 0 1px 0 var(--panel-rule);
  color: var(--panel-ink);
}
.verdict-score .num {
  font-family: var(--mono);
  font-size: 2.3rem;
  font-weight: 500;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--panel-ink);
}
.verdict-score .den { font-size: 0.9rem; color: var(--panel-ink-2); }
.verdict-score .cap { font-size: 0.8rem; color: var(--panel-ink-2); }

.vbar {
  display: flex;
  height: 9px;
  margin-top: 12px;
  background: var(--fill-2);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-pill);
  overflow: hidden;
}
.vbar > span { display: block; height: 100%; }
.vbar .seg-malicious  { background: var(--seal-malicious); }
.vbar .seg-suspicious { background: var(--seal-suspicious); }
.vbar .seg-undetected,
.vbar .seg-clean      { background: var(--seal-clean); }
.vbar .seg-unsupported,
.vbar .seg-errors     { background: var(--seal-unknown); }

.tally { display: flex; flex-wrap: wrap; gap: 6px 20px; margin-top: 10px; }
.tally-item { display: flex; align-items: center; gap: 7px; font-size: 0.87rem; color: var(--ink-2); }
.tally-item b { font-family: var(--mono); font-weight: 500; color: var(--ink); }

/* --- engine ledger --- */
.ledger-head,
.engine-tile {
  display: grid;
  grid-template-columns: 144px minmax(180px, 1.1fr) minmax(0, 1.8fr) 84px;
  gap: 16px;
  align-items: baseline;
}
.ledger-head {
  padding: 0 4px 7px 14px;
  border-bottom: 1px solid var(--glass-edge);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink-2);
}
.ledger-head span:last-child { text-align: right; }

.engine-grid { display: block; }
.engine-tile {
  padding: 11px 4px 11px 14px;
  border-bottom: 1px solid var(--glass-edge);
  border-left: 3px solid transparent;
}
.engine-tile:last-child { border-bottom: 0; }
.engine-tile.cat-malicious  { border-left-color: var(--seal-malicious); }
.engine-tile.cat-suspicious { border-left-color: var(--seal-suspicious); }

.engine-outcome { display: flex; align-items: center; gap: 8px; font-size: 0.86rem; font-weight: 500; }
.engine-outcome.cat-malicious  { color: var(--seal-malicious); }
.engine-outcome.cat-suspicious { color: var(--seal-suspicious); }
.engine-outcome.cat-clean,
.engine-outcome.cat-undetected { color: var(--seal-clean); }
.engine-outcome.cat-unsupported,
.engine-outcome.cat-error,
.engine-outcome.cat-unknown,
.engine-outcome.cat-inconclusive { color: var(--seal-unknown); }

.engine-id { min-width: 0; }
.engine-name { font-weight: 500; overflow-wrap: anywhere; }
.engine-tag {
  display: inline-block;
  margin-left: 7px;
  padding: 0 7px;
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-pill);
  background: var(--fill-2);
  font-size: 0.73rem;
  color: var(--ink-3);
  white-space: nowrap;
}
.engine-tile-result { min-width: 0; font-size: 0.89rem; color: var(--ink-2); overflow-wrap: anywhere; }
.engine-sig { font-family: var(--mono); font-size: 0.84rem; color: var(--ink); }
.engine-tile.cat-malicious .engine-sig  { color: var(--seal-malicious); }
.engine-tile.cat-suspicious .engine-sig { color: var(--seal-suspicious); }
.engine-desc { font-size: 0.89rem; color: var(--ink-2); }
.engine-tile-meta {
  text-align: right;
  font-family: var(--mono);
  font-size: 0.81rem;
  color: var(--ink-3);
}

.engine-group { margin-top: 14px; border-top: 1px solid var(--glass-edge); padding-top: 10px; }
.engine-group > summary { cursor: pointer; font-size: 0.87rem; font-weight: 500; color: var(--ink-2); padding: 6px 10px; }
.engine-group > summary:hover { color: var(--ink); }
.engine-group .engine-grid { margin-top: 6px; }

/* --- behavior sheets --- */
.run-sheet {
  padding: 16px;
  border-radius: var(--r-inner);
  border-left: 4px solid var(--glass-edge);
}
.run-sheet.state-malicious { border-left-color: var(--seal-malicious); }
.run-sheet.state-error     { border-left-color: var(--seal-suspicious); }
.run-sheet.state-clean     { border-left-color: var(--seal-clean); }
.run-sheet.state-unknown   { border-left-color: var(--seal-unknown); }
.run-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding-bottom: 8px;
  margin-bottom: 10px;
  border-bottom: 1px solid var(--glass-edge);
}
.run-host { display: flex; align-items: center; gap: 9px; font-size: 1rem; font-weight: 600; }
.run-line { margin: 0 0 5px; font-size: 0.87rem; color: var(--ink-2); max-width: var(--measure); }
.run-line.note { color: var(--ink-3); font-size: 0.84rem; }

/* --- ATT&CK --- */
.attack-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
.attack-col { padding: 12px 14px; border-top: 2px solid var(--violet-rule); }
.attack-tactic { margin-bottom: 7px; font-size: 0.87rem; font-weight: 600; color: var(--violet); }
.attack-tech { display: flex; gap: 9px; margin-bottom: 3px; font-size: 0.85rem; color: var(--ink-2); }
.attack-id { flex: 0 0 auto; font-family: var(--mono); font-size: 0.79rem; color: var(--ink-3); }
.attack-name { min-width: 0; overflow-wrap: anywhere; }

/* --- definition lists and fingerprint --- */
.kv { display: grid; grid-template-columns: minmax(140px, 200px) minmax(0, 1fr); gap: 0 22px; margin: 0; }
.kv > dt { padding: 9px 0; border-top: 1px solid var(--glass-edge); font-size: 0.87rem; color: var(--ink-2); }
.kv > dd {
  margin: 0;
  padding: 9px 0;
  border-top: 1px solid var(--glass-edge);
  font-size: 0.91rem;
  overflow-wrap: anywhere;
}
.kv > dt:first-of-type, .kv > dd:first-of-type { border-top: 0; }

.hash-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.hash-item { min-width: 0; padding: 11px 13px; }
.hash-item .hash-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 5px;
  font-size: 0.82rem;
  color: var(--ink-2);
}
.hash-item .hash-value { font-family: var(--mono); font-size: 0.83rem; line-height: 1.5; word-break: break-all; }
.scan-id {
  padding: 1px 8px;
  border: 1px dashed var(--glass-edge);
  border-radius: var(--r-pill);
  font-size: 0.81rem;
  color: var(--ink-2);
  overflow-wrap: anywhere;
}

.mitig { display: flex; flex-wrap: wrap; gap: 6px; }
.mitig .badge { font-size: 0.77rem; }
.mitig .on  { color: var(--seal-clean); background: var(--wash-clean); border-color: var(--seal-clean); }
.mitig .off { color: var(--ink-2); background: var(--fill-2); border-color: var(--glass-edge); }

/* -------------------------------------------------------------------------
   17. Keys, credits
   ------------------------------------------------------------------------- */
.balance-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 18px 20px;
  border-radius: var(--r-panel);
  border-left: 3px solid var(--violet);
}
.balance-num { font-family: var(--mono); font-size: 2rem; font-weight: 500; line-height: 1; }

.delta-up { color: var(--seal-clean); font-family: var(--mono); }
.delta-down { color: var(--seal-malicious); font-family: var(--mono); }
.score-read { font-family: var(--mono); font-size: 1.4rem; font-weight: 500; color: var(--seal-malicious); }

.pack {
  display: grid;
  gap: 3px;
  padding: 18px;
  border-radius: var(--r-panel);
  border-top: 2px solid var(--violet-rule);
}
.pack-credits { font-family: var(--mono); font-size: 1.8rem; font-weight: 500; line-height: 1.1; }
.pack-unit, .pack-rate { font-size: 0.85rem; color: var(--ink-3); }
.pack-price { margin-top: 5px; font-size: 1rem; font-weight: 600; }
.pack-tag {
  justify-self: start;
  padding: 1px 9px;
  border: 1px solid var(--violet-rule);
  border-radius: var(--r-pill);
  background: var(--violet-wash);
  color: var(--violet);
  font-size: 0.75rem;
  font-weight: 500;
}
.pack .btn { margin-top: 12px; }

.key-reveal {
  padding: 13px 15px;
  margin-bottom: 18px;
  background: var(--violet-wash);
  border-color: var(--violet-rule);
  font-family: var(--mono);
  font-size: 0.89rem;
  overflow-wrap: anywhere;
}

/* -------------------------------------------------------------------------
   18. Responsive — one breakpoint, 900px
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
  .container { padding: 0 16px; }
  .topbar-inner { flex-wrap: wrap; gap: 10px; padding: 10px 16px; }
  .nav-links { order: 3; width: 100%; flex-wrap: wrap; }
  .top-search { order: 4; flex: 1 1 100%; max-width: none; }
  .page { padding: 22px 0 52px; }
  .grid-3, .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hash-grid { grid-template-columns: 1fr; }
  .report-tabs { position: static; }
  html { scroll-padding-top: 18px; }

  .ledger-head { display: none; }
  .engine-tile { grid-template-columns: 1fr; gap: 5px; padding: 12px 12px; }
  .engine-tile-meta { text-align: left; }
}

@media (max-width: 620px) {
  body { font-size: 15.5px; }
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
  .hero { padding: 32px 0 22px; }
  .card, .card-body, .card-lg { padding: 16px; }
  .kv { grid-template-columns: 1fr; gap: 0; }
  .kv > dd { border-top: 0; padding-top: 0; padding-bottom: 10px; }
  .verdict-banner { flex-direction: column; }
  .verdict-score { width: 100%; border-left: 0; border-top: 1px solid var(--glass-edge); }
  .attack-grid { grid-template-columns: 1fr; }
}

/* -------------------------------------------------------------------------
   19. Upload card — the form beside the scanner picker

   The form is capped for typing comfort (see .scan-fields), which used to
   leave half the card empty. The picker uses that half: local engines in one
   group, the AV guests in another, everything ticked by default.
   ------------------------------------------------------------------------- */
.scan-layout {
  display: grid;
  grid-template-columns: minmax(0, 500px) minmax(0, 1fr);
  gap: 32px;
  align-items: stretch;
}
/* The old .form, minus the max-width that caused the dead space. Flex, so the
   submit button can sit on the card bottom edge however tall the picker is. */
.scan-fields { display: flex; flex-direction: column; gap: 16px; }
.scan-submit { margin-top: auto; padding-top: 8px; }

.picker { display: grid; gap: 14px; }
.picker-group {
  padding: 14px 16px;
  background: var(--fill);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-inner);
}
.picker-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding-bottom: 8px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--glass-edge);
}
.picker-head h3 { margin: 0; font-size: 0.94rem; }
.picker-actions { display: flex; gap: 4px; }

.picker-list { display: grid; gap: 1px; }
.picker-row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 5px 6px;
  border-radius: var(--r-control);
  cursor: pointer;
  font-size: 0.89rem;
}
.picker-row:hover { background: var(--fill-ink); }
.picker-row input { flex: 0 0 auto; }
.picker-name { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.picker-row .engine-tag { margin-left: 0; }

@media (max-width: 900px) {
  .scan-layout { grid-template-columns: 1fr; gap: 22px; }
}

/* -------------------------------------------------------------------------
   20. Checkboxes

   appearance:none so the box is ours rather than the operating system's: the
   native control is the one thing on the page that ignores the palette, and it
   looks worst on the dark theme. The tick is a mask rather than an image so it
   can take its colour from the theme — the dark theme's violet is pale, so the
   tick there has to be dark.
   ------------------------------------------------------------------------- */
input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 0 auto;
  display: inline-grid;
  place-content: center;
  width: 17px;
  height: 17px;
  margin: 0;
  border: 1px solid var(--rule-strong);
  border-radius: 4px;
  background: var(--fill);
  box-shadow: none;
  cursor: pointer;
  transition: background-color 150ms ease, border-color 150ms ease, box-shadow 150ms ease;
}
input[type="checkbox"]::after {
  content: "";
  width: 11px;
  height: 9px;
  background-color: var(--on-violet);
  -webkit-mask: var(--tick) no-repeat center / contain;
  mask: var(--tick) no-repeat center / contain;
  opacity: 0;
  transform: scale(0.6);
  transition: transform 150ms cubic-bezier(0.22, 0.61, 0.36, 1), opacity 120ms ease;
}
input[type="checkbox"]:hover { border-color: var(--violet-rule); }
input[type="checkbox"]:checked {
  background: var(--violet);
  border-color: var(--violet);
  box-shadow: none;
}
input[type="checkbox"]:checked::after { opacity: 1; transform: scale(1); }
input[type="checkbox"]:indeterminate {
  background: var(--violet-wash);
  border-color: var(--violet-rule);
}
input[type="checkbox"]:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
input[type="checkbox"]:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  border-color: var(--glass-edge);
}
@media (prefers-reduced-motion: reduce) {
  input[type="checkbox"], input[type="checkbox"]::after { transition: none; }
}

/* -------------------------------------------------------------------------
   20. Print — the dark palette becomes paper
   ------------------------------------------------------------------------- */
.print-head { display: none; }

@media print {
  :root {
    --field-1: #fff; --field-2: #fff; --field-3: #fff;
    --glass: #fff; --glass-strong: #fff; --glass-edge: #c9c9c9;
    --fill: #f4f4f4; --fill-2: #f4f4f4; --fill-ink: #eee;
    --ink: #000; --ink-strong: #000; --ink-2: #333; --ink-3: #555;
    --violet: #3b4396; --violet-2: #3b4396; --violet-wash: #eceefb; --violet-rule: #aeb4e6;
    --on-violet: #fff;
    --seal-malicious: #9d2231; --seal-suspicious: #7d5200;
    --seal-clean: #1d6b45; --seal-unknown: #5f6a75; --seal-edge: #bbb;
    --wash-malicious: #fbecec; --wash-suspicious: #fbf1e0;
    --wash-clean: #e9f4ee; --wash-unknown: #eef0f2;
    --panel: #222; --panel-ink: #fff; --panel-ink-2: #ccc; --panel-rule: #555;
    --shadow: none; --shadow-sm: none;
  }
  body { background: #fff; color: #000; font-size: 11pt; }
  .topbar, .report-tabs, .status-panel, .btn { display: none !important; }
  .site-foot .container span:last-child { display: none; }
  .page { padding: 0; }
  .container { max-width: none; padding: 0; }
  .card, .run-sheet, .verdict-banner, .stat, .pack, .balance-card {
    break-inside: avoid;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  a { color: inherit; text-decoration: none; }
  .print-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-bottom: 9px;
    margin-bottom: 16px;
    border-bottom: 2px solid #333;
    font-family: var(--mono);
    font-size: 0.95rem;
    font-weight: 500;
  }
}

/* -------------------------------------------------------------------------
   20. Motion
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  html { scroll-behavior: auto; }
}

/* -------------------------------------------------------------------------
   21. Background decoration

   The AID design is flat: there is no colour field behind the page and no
   artwork behind the panels, so nothing sits behind a surface. The fixed art
   layer stays in the DOM — the templates still fill it — and is simply not
   shown.
   ------------------------------------------------------------------------- */
.art-layer { display: none; }
