/* =============================================================================
 * VIOLET DESIGN SYSTEM
 * =============================================================================
 * Loaded after components.css. Everything here is a decision taken ONCE, so
 * that fixing a screen stops being an opinion and becomes applying a rule.
 *
 * Why this file exists, in numbers measured in the repository:
 *
 *   6 057  loose pixel sizes in templates (2 618 of them text-[10px]),
 *          400+ of them below 8px. text-[5px] exists in the product.
 *   1 861  hand-written purple/violet/indigo classes.
 *      40  distinct shapes of <select>, across 291 of them in 119 files.
 *       6  different ways to paint "Critical" in red, across 24 templates.
 *
 * None of that is a bug. It is what happens when the COLOUR and the SIZE are
 * decided by the template instead of by the component: every new screen invents
 * them again, and the product ends up looking like it was assembled rather than
 * designed. That is the actual mechanism behind "this looks like AI made it".
 *
 * -----------------------------------------------------------------------------
 * THE FOUR RULES
 * -----------------------------------------------------------------------------
 * 1. The chrome is neutral. Colour is DATA, never decoration. When everything
 *    is coloured, the one red thing that matters does not read as red.
 *
 * 2. A fact is not a control. `.vs-prop` for something you can only read,
 *    `.vs-chip` for something you can change — and a chip ALWAYS carries a
 *    chevron. The Finding header used to chip everything, so the chip stopped
 *    meaning anything and six of them sat in a row in six different shapes.
 *
 * 3. One control, one shape. State changes the colour; it never changes the
 *    shape, the height or the padding.
 *
 * 4. Nothing below 11px. Text at 8px is not small, it is unread.
 * ========================================================================== */

:root {
  /* ── Neutrals. Cool-biased, so they sit under any tenant accent ────────── */
  --vs-ink:        #111827;
  --vs-ink-2:      #4b5563;
  --vs-ink-3:      #6b7280;
  --vs-ink-4:      #9ca3af;
  --vs-surface:    #ffffff;
  --vs-surface-2:  #f9fafb;
  --vs-surface-3:  #f3f4f6;
  --vs-rule:       #e5e7eb;
  --vs-rule-2:     #d1d5db;

  /* ── Semantic. Four meanings and no more. The accent is the tenant's ──── */
  --vs-very-critical: #7f1d1d;  --vs-very-critical-bg: #fecaca;  --vs-very-critical-line: #f87171;
  --vs-critical:      #b91c1c;  --vs-critical-bg: #fee2e2;  --vs-critical-line: #fecaca;
  --vs-high:          #c2410c;  --vs-high-bg:     #ffedd5;  --vs-high-line:     #fed7aa;
  --vs-medium:        #a16207;  --vs-medium-bg:   #fef3c7;  --vs-medium-line:   #fde68a;
  --vs-low:           #15803d;  --vs-low-bg:      #dcfce7;  --vs-low-line:      #bbf7d0;
  --vs-info:          #1d4ed8;  --vs-info-bg:     #dbeafe;  --vs-info-line:     #bfdbfe;
  /* Not severities. OK = done / compliant / remediated / success: the same
     green as Low, but a different meaning. PROGRESS = a workflow stage under
     way (in progress, planned-for). */
  --vs-ok:            #15803d;  --vs-ok-bg:       #dcfce7;  --vs-ok-line:       #bbf7d0;
  --vs-progress:      #1d4ed8;  --vs-progress-bg: #dbeafe;  --vs-progress-line: #bfdbfe;

  /* ── Type scale. FOUR sizes plus the metric ─────────────────────────────
     12 / 13 / 15 / 20, and 28 for the one number a screen exists to show.
     --vs-t-eyebrow is the single exception and it is not a fifth size: it is
     11px ONLY because it is always uppercase and letterspaced, which reads a
     size larger than it measures. Nothing in sentence case may use it. */
  --vs-t-eyebrow: 11px;   /* UPPERCASE labels only — never sentence case   */
  --vs-t-meta:    12px;   /* secondary text, timestamps, counts           */
  --vs-t-body:    13px;   /* running text and table cells                 */
  --vs-t-title:   15px;   /* card and section titles                      */
  --vs-t-page:    20px;   /* the one page title                           */
  --vs-t-metric:  28px;   /* the number a screen exists to show           */

  /* ── Weight. Three, and they mean something ─────────────────────────────
     400 running text · 500 a label or a row · 600 a title or an active row.
     700/800 are not in the system: bold everywhere is bold nowhere. */
  --vs-w-body:   400;
  --vs-w-label:  500;
  --vs-w-title:  600;

  /* ── Geometry. One height for controls, TWO radii ───────────────────────
     6px for every surface and every control — a card, a panel, a modal, an
     input, a button — and the pill for lozenges and chips, which are the only
     things whose shape is allowed to say "this is a small piece of state".
     --vs-radius-lg was 10px and is kept as an alias so the ~40 rules that
     name it converge instead of being hunted down one by one. */
  --vs-control-h:   32px;
  --vs-radius:      6px;      /* surfaces and controls alike               */
  --vs-radius-lg:   var(--vs-radius);
  --vs-radius-pill: 9999px;   /* lozenges and chips ONLY                   */
}

/* =============================================================================
 * TYPE — three classes replace twelve variants of the same idea
 * ========================================================================== */
/* The uppercase label. Twelve hand-written variants existed (10/11px x
   bold/semibold x wide/wider/widest); the most common one appeared 207 times. */
.vs-eyebrow {
  font-size: var(--vs-t-eyebrow);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--vs-ink-3);
  line-height: 1.4;
}
.vs-meta {
  font-size: var(--vs-t-meta);
  color: var(--vs-ink-3);
  line-height: 1.5;
}
/* Running text and table cells. Named so markup never has to spell 13px —
   the first pass at the table wrote `text-[13px]` by hand and the arbitrary-
   size ratchet caught it, correctly: a token you have to retype is a token
   that will drift. */
.vs-body { font-size: var(--vs-t-body); }
/* Section titles were font-semibold 71 times and font-bold 53 times on the same
   element, in four different greys. One answer. */
.vs-section-title {
  font-size: var(--vs-t-title);
  font-weight: 600;
  color: var(--vs-ink);
  letter-spacing: -.006em;
  line-height: 1.35;
}
/* The number a screen exists to show: large, black, and NOT inside a coloured
   box with an icon tile beside it. */
.vs-metric {
  font-size: var(--vs-t-metric);
  font-weight: 700;
  color: var(--vs-ink);
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}
.vs-metric-label {
  font-size: var(--vs-t-eyebrow);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--vs-ink-3);
}
/* A metric wears a colour ONLY when the colour is the reading. "1 critical" is
   red because red is the answer; "12 findings" is not anything, so it is ink. */
.vs-metric--very-critical { color: var(--vs-very-critical); }
.vs-metric--critical { color: var(--vs-critical); }
.vs-metric--high     { color: var(--vs-high); }
.vs-metric--medium   { color: var(--vs-medium); }
.vs-metric--low      { color: var(--vs-low); }
.vs-metric--info     { color: var(--vs-info); }
.vs-metric--ok       { color: var(--vs-ok); }
.vs-metric--progress { color: var(--vs-progress); }

/* The KPI tile. Grey by default, and that is the point: a row of four cards
   used to show four brand-coloured squares, so the eye went to the decoration
   instead of to the one number that needed attention. It takes a tone only
   when the card is reporting a severity. */
.vs-kpi-icon {
  width: 32px;
  height: 32px;
  border-radius: var(--vs-radius);
  border: 1px solid var(--vs-rule);
  background: var(--vs-surface-3);
  color: var(--vs-ink-3);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: 13px;
}
.vs-kpi-icon--very-critical { background: var(--vs-very-critical-bg); border-color: var(--vs-very-critical-line); color: var(--vs-very-critical); }
.vs-kpi-icon--critical { background: var(--vs-critical-bg); border-color: var(--vs-critical-line); color: var(--vs-critical); }
.vs-kpi-icon--high     { background: var(--vs-high-bg);     border-color: var(--vs-high-line);     color: var(--vs-high); }
.vs-kpi-icon--medium   { background: var(--vs-medium-bg);   border-color: var(--vs-medium-line);   color: var(--vs-medium); }
.vs-kpi-icon--low      { background: var(--vs-low-bg);      border-color: var(--vs-low-line);      color: var(--vs-low); }
.vs-kpi-icon--info     { background: var(--vs-info-bg);     border-color: var(--vs-info-line);     color: var(--vs-info); }
.vs-kpi-icon--ok       { background: var(--vs-ok-bg);       border-color: var(--vs-ok-line);       color: var(--vs-ok); }

/* A KPI strip of nine tiles (Score, the five severities, Open, Remediated,
   Accepted). Tailwind is compiled and ships no xl:grid-cols-9, so the xl step
   lives here; below xl the strip keeps its md:grid-cols-4 wrap. */
@media (min-width: 1280px) {
  .vs-kpi-grid--9 { grid-template-columns: repeat(9, minmax(0, 1fr)); }
}

/* =============================================================================
 * PROP — a fact. Label above, value below. No border, no background.
 * ========================================================================== */
/* This is rule 2, and it is the one that changes the product. Anything the
   reader cannot change is a prop; only what they CAN change earns a chip. */
.vs-prop { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.vs-prop__label {
  font-size: var(--vs-t-eyebrow);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--vs-ink-4);
  line-height: 1.3;
}
.vs-prop__value {
  font-size: var(--vs-t-body);
  color: var(--vs-ink);
  line-height: 1.4;
  min-width: 0;
}
.vs-prop__value a { color: var(--color-primary); text-decoration: none; }
.vs-prop__value a:hover { text-decoration: underline; }
/* A row of them. Sits under a title, reads as one block. */
.vs-prop-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  align-items: flex-start;
}
/* The right-hand properties rail: label left, value right, one row each. */
.vs-prop-list { display: flex; flex-direction: column; }
.vs-prop-list > div {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 7px 0;
  border-bottom: 1px solid var(--vs-rule);
  font-size: var(--vs-t-body);
}
.vs-prop-list > div:last-child { border-bottom: none; }
.vs-prop-list dt, .vs-prop-list .vs-prop-list__k {
  color: var(--vs-ink-3);
  font-size: var(--vs-t-meta);
  white-space: nowrap;
}
.vs-prop-list dd, .vs-prop-list .vs-prop-list__v {
  margin: 0;
  color: var(--vs-ink);
  text-align: right;
  min-width: 0;
}

/* =============================================================================
 * SEVERITY — one token, used by all 24 templates that used to invent it
 * ========================================================================== */
/* The WORD, everywhere. Not the letter: this product exports to PDF and PPTX
   for a client committee, and a bare "C" in a report needs a legend the word
   does not. `--compact` exists for the two or three genuinely dense tables (one
   already reached for it by hand in audit_detail.html) and is an exception that
   must stay an exception. */
.vs-sev {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  /* 26px, the same as .vs-chip. A finding header puts facts and controls in
     one row — SEVERITY, IMPACT, the effective-band arrow, STATUS, KEV, PEOPLE
     — and at 22px against 26px they sat on different baselines. What separates
     a fact from a control is the chevron, not four pixels.
     `.vs-sev--compact` still exists for dense tables. */
  height: 26px;
  padding: 0 .5rem;
  border-radius: 4px;
  border: 1px solid transparent;
  font-size: var(--vs-t-eyebrow);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}
.vs-sev--very-critical,
.vs-sev--very_critical { background: var(--vs-very-critical-bg); color: var(--vs-very-critical); border-color: var(--vs-very-critical-line); }
.vs-sev--critical { background: var(--vs-critical-bg); color: var(--vs-critical); border-color: var(--vs-critical-line); }
.vs-sev--high     { background: var(--vs-high-bg);     color: var(--vs-high);     border-color: var(--vs-high-line); }
.vs-sev--medium   { background: var(--vs-medium-bg);   color: var(--vs-medium);   border-color: var(--vs-medium-line); }
.vs-sev--low      { background: var(--vs-low-bg);      color: var(--vs-low);      border-color: var(--vs-low-line); }
.vs-sev--info     { background: var(--vs-info-bg);     color: var(--vs-info);     border-color: var(--vs-info-line); }
.vs-sev--none     { background: var(--vs-surface-3);   color: var(--vs-ink-3);    border-color: var(--vs-rule); }
/* Same shape for a GOOD outcome (compliant, clean, implemented). Not a
   severity: it shares Low's green, but Low is never borrowed to mean "fine". */
.vs-sev--ok       { background: var(--vs-ok-bg);       color: var(--vs-ok);       border-color: var(--vs-ok-line); }
/* The exception, declared. Square, initial only, for tables of 20+ rows. */
.vs-sev--compact {
  width: 18px; height: 18px; padding: 0;
  justify-content: center;
  font-size: 10px; font-weight: 700;
}

/* =============================================================================
 * CARD — a surface, and nothing else
 * ========================================================================== */
/* No gradient band, no coloured icon tile, no oversized padding, and since the
   canvas is tinted (--page-bg), no outline either: the ground separates the
   card, and drawing a hairline as well is the same boundary twice. The border
   is kept and made transparent rather than removed, so the 1px still occupies
   its space and no layout shifts. Rules INSIDE a card (.vs-card__head's
   bottom edge, table rules, dividers) are a different job and stay. */
.vs-card {
  background: var(--vs-surface);
  border: 1px solid transparent;
  border-radius: var(--vs-radius-lg);
  overflow: hidden;
}

/* The same card, hand-written. 145 templates draw their surfaces as
   `bg-white rounded-lg border border-gray-200` instead of .vs-card, and they
   are not going to be swept in one sitting — so the rule reaches them where
   they are. Four classes outrank Tailwind's single `border-gray-200`, and the
   combination is specific enough to mean "a card": a bordered white rounded
   box. Anything that needs its edge (inputs, the bordered variants of a
   lozenge) does not match all four. */
main .bg-white.rounded-lg.border.border-gray-200,
main .bg-white.rounded-xl.border.border-gray-200 {
  border-color: transparent;
}
.vs-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  padding: .75rem 1rem;
  border-bottom: 1px solid var(--vs-rule);
}
.vs-card__head h2, .vs-card__head h3 {
  font-size: var(--vs-t-title);
  font-weight: 600;
  color: var(--vs-ink);
  margin: 0;
}
.vs-card__body { padding: 1rem; }

/* =============================================================================
 * BUTTON — hierarchy comes from position, not from colour
 * ========================================================================== */
/* One height, one radius, one type size. `--primary` is the tenant accent and
   there is at most ONE on a screen; everything else is quiet. 156 buttons had
   their own px-* padding, which is why no two action rows lined up. */
.vs-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  height: var(--vs-control-h);
  padding: 0 .75rem;
  border-radius: var(--vs-radius);
  border: 1px solid var(--vs-rule-2);
  background: var(--vs-surface);
  color: var(--vs-ink-2);
  font-size: var(--vs-t-meta);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.vs-btn > i { font-size: 11px; opacity: .8; }
.vs-btn:hover { background: var(--vs-surface-2); border-color: var(--vs-ink-4); color: var(--vs-ink); }
.vs-btn:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 1px; }
.vs-btn[disabled], .vs-btn.is-disabled { opacity: .5; cursor: not-allowed; }
.vs-btn--primary {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #fff;
}
.vs-btn--primary:hover { filter: brightness(.94); background: var(--color-primary); color: #fff; }
.vs-btn--danger { background: var(--vs-critical); border-color: var(--vs-critical); color: #fff; }
.vs-btn--danger:hover { filter: brightness(.94); background: var(--vs-critical); color: #fff; }
/* Icon-only, square, same height as everything else in the row. */
.vs-btn--icon { width: var(--vs-control-h); padding: 0; }

/* =============================================================================
 * TABLE — one header treatment
 * ========================================================================== */
.vs-table { width: 100%; border-collapse: collapse; font-size: var(--vs-t-body); }
.vs-table th {
  text-align: left;
  padding: .5rem .75rem;
  font-size: var(--vs-t-eyebrow);
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--vs-ink-3);
  border-bottom: 1px solid var(--vs-rule-2);
  white-space: nowrap;
  background: var(--vs-surface-2);
}
.vs-table td {
  padding: .625rem .75rem;
  border-bottom: 1px solid var(--vs-rule);
  color: var(--vs-ink);
  vertical-align: middle;
}
.vs-table tbody tr:last-child td { border-bottom: none; }
.vs-table tbody tr:hover td { background: var(--vs-surface-2); }
.vs-table .is-num { text-align: right; font-variant-numeric: tabular-nums; }

/* =============================================================================
 * SUB-NAV — the second strip, inside a section
 * ========================================================================== */
/* No second strip any more. GRC used to carry a top strip (Posture /
 * Compliance / Risk / Policies / Reports) repeating the sidebar entry the
 * reader had just clicked, with these below it — so a quieter `--sub`
 * variant existed to say "subordinate". The top strip is gone: the sidebar
 * owns that level, and each section keeps only its own strip, which is
 * therefore the module's PRIMARY nav and wears `.page-tabs` like every
 * other module. A second size with no second level to mark was just a
 * second size. */

/* =============================================================================
   Lifecycle rail (Audits). One row, six steps, a hairline between them.
   Node + label + count read left to right like a sentence; the active step is
   the only filled node on the row, hover borrows the accent for one node.
   ========================================================================== */
.vs-rail {
  display: flex;
  align-items: center;
  gap: 1rem;
  background: #fff;
  border: 1px solid var(--vs-rule);
  border-radius: .75rem;
  padding: .625rem 1.125rem;
  margin-bottom: 1.25rem;
}
.vs-rail__eyebrow {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--vs-ink-4);
  white-space: nowrap;
  padding-right: 1rem;
  border-right: 1px solid var(--vs-rule);
}
.vs-rail__track {
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  min-width: 0;
  gap: .375rem;
  overflow-x: auto;
  scrollbar-width: none;
}
.vs-rail__track::-webkit-scrollbar { display: none; }
.vs-rail__step {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .25rem .5rem .25rem .25rem;
  border-radius: 9999px;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .15s ease;
}
.vs-rail__step:hover { background: var(--vs-surface-3); }
.vs-rail__node {
  width: 26px;
  height: 26px;
  border-radius: 9999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--vs-surface-3);
  border: 1px solid var(--vs-rule);
  color: var(--vs-ink-3);
  font-size: 10.5px;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.vs-rail__label {
  font-size: 13px;
  font-weight: 600;
  color: #111827;
  letter-spacing: -.005em;
}
.vs-rail__count {
  font-size: 11.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--vs-ink-4);
  min-width: 1.25rem;
  height: 18px;
  line-height: 18px;
  padding: 0 .375rem;
  text-align: center;
  border-radius: 9999px;
  background: var(--vs-surface-3);
}
/* Stuck = urgency, but five red pills in a row is a siren, not a signal: the
   colour goes in the number and a tint, and the loudest thing on the row is
   still the one step you are filtering by. */
.vs-rail__count--stuck { color: var(--vs-critical); background: color-mix(in srgb, var(--vs-critical) 10%, white); }
.vs-rail__link { flex: 1 1 auto; min-width: .75rem; height: 1px; background: var(--vs-rule); }
.vs-rail__step:hover .vs-rail__node { border-color: var(--color-primary); color: var(--color-primary); }
.vs-rail__step--active .vs-rail__node { background: var(--color-primary); border-color: var(--color-primary); color: #fff; }
.vs-rail__step--active .vs-rail__label { color: var(--color-primary); }
.vs-rail__step--active .vs-rail__count { background: color-mix(in srgb, var(--color-primary) 12%, white); color: var(--color-primary); }
.vs-rail__clear {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  font-size: 12px;
  color: var(--vs-ink-4);
  white-space: nowrap;
  text-decoration: none;
}
.vs-rail__clear:hover { color: #111827; }
@media (max-width: 1100px) { .vs-rail__eyebrow { display: none; } }



/* ══════════════════════════════════════════════════════════════════════════
   THE KPI TILE — .vs-kpi, rendered by components/_exec_kpi.html
   ══════════════════════════════════════════════════════════════════════════
   This is the product's ONE card for "a number that means something", and as
   of 7-sep-2026 it is the canonical one: components/kpi_card.html delegates
   to it, so the 107 tiles that used the older card wear this shape too.

   It used to live inside violet/partials/_vs_design_system.html, an OPTIONAL
   per-page include - which is precisely why it could not be canonical: a page
   that adopted the component and forgot the partial rendered an unstyled div,
   so 25 templates kept using the older card instead. A shared component whose
   styles are opt-in is not shared.

   Every var() carries the literal it resolves to inside `.vs-dash` as its
   fallback, so the tile is identical on a dashboard (tokens present) and on a
   plain page (tokens absent), and nothing has to be defined on :root where it
   could collide.
   ══════════════════════════════════════════════════════════════════════════ */
.vs-kpi{
  position:relative; background:#fff;
  border:1px solid var(--border-1, #e5e7eb); border-radius:var(--vs-radius, 6px);
  padding:12px 14px; cursor:pointer; overflow:hidden;
  display:flex; flex-direction:column; gap:8px;
  transition:border-color .2s var(--e, cubic-bezier(.4,0,.2,1));
}
.vs-kpi:hover{ border-color:var(--border-2, #d1d5db); }
/* A tile that is also a filter says so HERE, not in the page that uses it.
   Three screens had grown their own selected state as an inline
   `border-[var(--color-primary)] ring-1 ring-.../20` on a hand-built box,
   which is the whole reason they could not adopt the component. Pass
   kpi_class="vs-kpi--on". */
.vs-kpi--on{
  border-color:var(--color-primary);
  box-shadow:0 0 0 1px color-mix(in srgb, var(--color-primary) 25%, transparent);
}
/* The audit Summary cockpit: eight tiles on one slim row. Same tile, half the
   height, so the page's own summary card is whole on screen when it opens. */
.vs-cockpit .vs-kpi{ padding:8px 12px; gap:2px; }
.vs-cockpit .vs-kpi__label{ font-size:10.5px; letter-spacing:.04em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; display:block; }
.vs-cockpit .vs-kpi__label i{ font-size:11px; margin-right:4px; }
.vs-cockpit .vs-kpi__num{ font-size:20px; margin-top:0; }
.vs-cockpit .vs-kpi__num--word{ font-family:inherit; font-size:13px; font-weight:600; letter-spacing:0; line-height:1.4; }
.vs-cockpit .vs-kpi__sub{ font-size:11px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.vs-cockpit .vs-kpi > div{ min-width:0; }
/* A row of many small tiles (one per status): same tile, tighter. */
.vs-kpi--compact{ padding:10px 12px; gap:4px; }
.vs-kpi--compact .vs-kpi__label{ font-size:10.5px; letter-spacing:.04em; line-height:1.25; min-height:2.5em; align-items:flex-start; }
.vs-kpi--compact .vs-kpi__label i{ font-size:12px; }
.vs-kpi--compact .vs-kpi__num{ font-size:22px; }
.vs-kpi__label{
  font-size:11px; letter-spacing:.06em; text-transform:uppercase; font-weight:600;
  color:var(--fg-3, #8a8aa0); display:flex; align-items:center; gap:6px;
}
.vs-kpi__label i{ font-size:14px; color:var(--ink-300, #b8b8c8); }
/* The tinted 28px icon chip is gone from the component. The class survives as
   the rule that UNDOES it, so the handful of tiles still hand-written with it
   land in the same place without those pages being edited. */
.vs-kpi__chip{
  width:auto !important; height:auto !important; padding:0 !important;
  background:transparent !important; border:0 !important; border-radius:0 !important;
  display:inline-flex; align-items:center; font-size:14px; flex-shrink:0;
}
.vs-kpi__num{
  font-family:var(--font-display, 'Space Grotesk', system-ui, sans-serif);
  font-weight:600; font-size:28px; line-height:1.02; letter-spacing:-.02em;
  color:var(--fg-1, #0f0f1c); margin-top:2px;
}
/* A value that is a word, not a figure. See components/_exec_kpi.html: the
   28px display size is what makes a number legible across a row of tiles, and
   what makes "No" read as shouting. */
.vs-kpi__num--word{ font-size:18px; letter-spacing:-.01em; }
/* A tile whose value is a name (a finding, a milestone) keeps one line and
   ends in an ellipsis, so a row of tiles keeps one height. kpi_class="vs-kpi--clip". */
.vs-kpi--clip{ min-width:0; }
.vs-kpi--clip > div{ min-width:0; }
.vs-kpi--clip .vs-kpi__num,
.vs-kpi--clip .vs-kpi__sub{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* A name is read, not scanned: body size, not the 18px word size, so a row
   of names (stage, finding, milestone, report) does not shout. */
.vs-kpi--clip .vs-kpi__num--word{
  font-family:inherit; font-size:14px; font-weight:600; letter-spacing:0; line-height:1.35; margin-top:0;
}
.vs-kpi__sub{ font-size:12px; color:var(--fg-3, #8a8aa0); margin-top:1px; }
/* State or flow: "Now" / "Last 30 days", top-right, quieter than the label. */
.vs-kpi__scope{
  font-size:11px; letter-spacing:.06em; text-transform:uppercase; font-weight:500;
  color:#9ca3af; white-space:nowrap;
}
.vs-kpi__spark{ position:relative; width:100%; height:52px; margin-top:auto; }
.vs-kpi__spark canvas{ position:absolute; inset:0; width:100% !important; height:100% !important; }
.vs-kpi__spark > div{ position:absolute; inset:0; }
