/* ==========================================================================
   Vendor Management screens.

   Every selector here is scoped under .vm.

   The reason is measured, not stylistic: this stylesheet and the shell's
   core/components.css both define 25 of the same class names, and for one
   of them they mean incompatible things. .qrow is a flex row there and an
   eight column grid here. Loading both unscoped means whichever comes
   second wins and one of the two screens breaks.

   Scoping was the cheaper of the two honest options. Renaming 354 classes
   would have touched every screen file; this touches selectors only, and no
   screen markup changed.

   The reset, html and body stay global. core/components.css declares them
   identically, so leaving them unscoped changes nothing when both load, and
   it is required when this file loads alone at standalone.html.

   The wrapper is applied in two places: the standalone shell in runtime.js,
   and the module bridge in screens.js.
   ========================================================================== */

.vm /* ============================================================
   SmartDocs 8.2 — Components and archetypes
   Specs from the 8.2 handoff,
.vm sections 6.6,
.vm 7 and 8.
   Responsive rules are set once here,
.vm at the archetype level,
.vm never per screen.
   ============================================================ */

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

html {
  /* The top bars are sticky and cover 87px, so a control scrolled
     to by keyboard must stop below them. */
  scroll-padding-top: 96px; font-size: 16px; -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--background);
  color: var(--foreground);
  font-family: 'Source Sans 3', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: 13px;
  line-height: 1.45;
  /* Set globally, not per table, so amounts and dates stay column-aligned everywhere */
  font-variant-numeric: tabular-nums;
}

.vm .mono { font-family: 'IBM Plex Mono', ui-monospace, 'Cascadia Code', Consolas, monospace; }

.vm /* One focus rule app-wide,
.vm not per component */
*:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }

.vm h1,
.vm h2,
.vm h3,
.vm h4 { margin: 0; font-weight: 700; }
.vm p { margin: 0 0 8px; }
.vm a { color: var(--primary); text-decoration: none; }
.vm a:hover { text-decoration: underline; }

.vm /* Visually hidden,
.vm and contained.
   position: absolute resolves against the nearest positioned
   ancestor,
.vm so inside a static parent these escape to the initial
   containing block and sit at a static position that can push the
   document wider. That is exactly what happened when the stage
   strip gained a hidden "(completed)" per step: the page grew from
   320 to 438 pixels at phone width.

   inset: auto with the parent made relative is one fix and needs
   every parent remembering. Sizing the box to nothing and clipping
   it is the fix that does not.
   ---------------------------------------------------------------- */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
  /* Anchored to its parent, which keeps it out of the document flow
     without letting it land somewhere off to the right. */
  inset-inline-start: 0; inset-block-start: 0;
}
.vm /* Any element that carries hidden text becomes the containing block
   for it,
.vm so the pattern above cannot escape. */
.path-step,
.vm .f-lbl,
.vm .modbar-out,
.vm .avatar,
.vm .badge,
.vm .tab,
.vm .chip { position: relative; }
.vm .skip-link {
  position: absolute; left: 8px; top: -60px; z-index: 200;
  background: var(--primary); color: var(--primary-foreground);
  padding: 9px 14px; border-radius: var(--r-md); font-weight: 600;
  transition: top .12s;
}
.vm .skip-link:focus { top: 8px; text-decoration: none; }

.vm /* ============================================================
   Typography scale,
.vm handoff 6.4
   ============================================================ */
.t-hero { font-size: 30px; font-weight: 700; letter-spacing: -.01em; }
.vm .t-page { font-size: 19px; font-weight: 700; letter-spacing: -.005em; }
.vm .t-panel { font-size: 16px; font-weight: 700; }
.vm .t-card { font-size: 14.5px; font-weight: 600; }
.vm .t-body { font-size: 13px; font-weight: 400; }
.vm .t-table { font-size: 12.5px; font-weight: 400; }
.vm .t-label { font-size: 11px; font-weight: 600; }
.vm .eyebrow {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--muted-foreground);
}
.vm .muted { color: var(--muted-foreground); }
.vm .fs11 { font-size: 11px; }
.vm .fs12 { font-size: 12px; }
.vm .fs125 { font-size: 12.5px; }
.vm .num { font-feature-settings: 'tnum'; }

.vm /* ============================================================
   Top bar,
.vm handoff 4.3. White,
.vm 50px,
.vm two levels only.
   ============================================================ */
.topbar {
  position: sticky; top: 0; z-index: 60;
  height: var(--topbar-h);
  display: flex; align-items: center; gap: 14px;
  padding: 0 var(--gutter);
  background: var(--card);
  border-bottom: 1px solid var(--border);
  /* The bar never scrolls sideways and never grows the page. */
  overflow: visible; min-width: 0;
}
.vm .brand { display: flex; align-items: center; gap: 9px; flex: 0 0 auto; cursor: pointer; }
.vm .brand-mark {
  width: 28px; height: 28px; border-radius: var(--r-sm);
  background: var(--primary); color: var(--primary-foreground);
  display: grid; place-items: center; font-weight: 700; font-size: 12px;
  flex: 0 0 28px;
}
.vm .brand-text { line-height: 1.15; }
.vm .brand-name { font-size: 13.5px; font-weight: 700; letter-spacing: -.01em; }
.vm .brand-sub { font-size: 10.5px; color: var(--muted-foreground); }

.vm .modules { display: flex; align-items: center; gap: 2px; flex: 1 1 auto; min-width: 0; }

.vm /* Selected module: filled rounded pill,
.vm never an underline. Handoff 4.4.
   Solid fill,
.vm not a tint: 8.73:1 both directions. */
.mod {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  height: 33px; padding: 0 12px; border-radius: var(--r-md);
  display: inline-flex; align-items: center; gap: 6px;
  font-family: inherit; font-size: 13px; font-weight: 500;
  color: var(--muted-foreground); white-space: nowrap;
}
.vm .mod:hover { background: var(--primary-soft); color: var(--primary); }
.vm .mod:active { background: var(--primary); color: var(--primary-foreground); }
.vm .mod[aria-current="page"] {
  background: var(--primary); color: var(--primary-foreground); font-weight: 600;
}
.vm .mod-ico { width: 15px; height: 15px; flex: 0 0 15px; }

.vm .util { display: flex; align-items: center; gap: 3px; flex: 0 0 auto; }
.vm .util-btn {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  width: 32px; height: 32px; border-radius: var(--r-md);
  display: grid; place-items: center; color: var(--muted-foreground);
  position: relative;
}
.vm .util-btn:hover { background: var(--secondary); color: var(--foreground); }
.vm .util-dot {
  position: absolute; top: 4px; right: 4px;
  min-width: 15px; height: 15px; padding: 0 3px; border-radius: 8px;
  background: var(--destructive); color: var(--on-strong);
  font-size: 9.5px; font-weight: 700; line-height: 15px; text-align: center;
}
.vm .avatar {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--navy); color: var(--navy-foreground);
  display: grid; place-items: center; font-size: 11px; font-weight: 700;
  flex: 0 0 30px; cursor: pointer;
}

.vm /* Anchored menu panel,
.vm sized to content. Never full-bleed. Handoff 4.3. */
.menu-wrap { position: relative; }
.vm .menu {
  position: absolute; top: calc(100% + 7px); left: 0; z-index: 80;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-pop);
  padding: 9px; display: flex; gap: 2px;
}
.vm .menu-col { width: 188px; }
.vm .menu-grp {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--muted-foreground);
  padding: 3px 8px 5px;
}
.vm .menu-item {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 8px; border-radius: var(--r-sm);
  font-size: 12.5px; color: var(--foreground); cursor: pointer;
  border: 0; background: transparent; width: 100%; text-align: left;
  font-family: inherit;
}
.vm .menu-item:hover { background: var(--secondary); }
.vm .menu-item .mi-ico { width: 14px; height: 14px; flex: 0 0 14px; color: var(--muted-foreground); }
.vm .menu-item .mi-count { margin-left: auto; font-size: 11px; font-weight: 600; color: var(--muted-foreground); }
.vm .menu-item[aria-current="page"] { background: var(--primary-soft); color: var(--primary); font-weight: 600; }
.vm .menu-item[aria-current="page"] .mi-ico { color: var(--primary); }
.vm .ai-all {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px dashed var(--ai-line); background: var(--ai-soft);
  color: var(--ai); border-radius: var(--r-md);
  height: 24px; padding: 0 9px; cursor: pointer; font-family: inherit;
  font-size: 11px; font-weight: 600;
}
.vm .ai-all:hover { filter: brightness(.97); }

.vm .scrim { position: fixed; inset: 0; z-index: 70; background: transparent; }

.vm /* ============================================================
   Supplier-facing shell.
   A supplier has no modules,
.vm so it has no module navigation. The
   content sits in a readable measure rather than running edge to
   edge,
.vm because filling in a form is reading,
.vm not scanning a table.
   ============================================================ */
.pubbar { justify-content: space-between; }

.vm /* A preview of another application,
.vm opened from inside this one,
.vm has to say so. Without this the form read as having fallen out of
   the product,
.vm and the only way back was the button you arrived by. */
.preview-bar {
  position: sticky; top: var(--topbar-h); z-index: 55;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 7px var(--gutter);
  background: var(--ai-soft); border-bottom: 1px solid var(--ai-line);
  font-size: 11.5px; color: var(--ai);
}
.vm .preview-bar .pv-l { font-weight: 700; display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.vm .preview-bar .pv-m { color: var(--muted-foreground); min-width: 0; flex: 1 1 260px; }
.vm .preview-bar .pv-r { display: flex; gap: 6px; flex: 0 0 auto; margin-left: auto; }
@media (max-width: 768px) {
  .vm .preview-bar { position: static; }
  .vm .preview-bar .pv-m { display: none; }
}
.vm .pubbar .util { gap: 7px; }
.vm .shell-public {
  background: var(--surface);
  min-height: calc(100vh - var(--topbar-h));
  padding: 16px var(--gutter) 48px;
}
.vm .shell-public > * {
  max-width: 1000px; margin-left: auto; margin-right: auto;
}

.vm /* ============================================================
   In-module strip.
   Persistent under the top bar,
.vm so moving inside Vendors never
   needs a dropdown. The live product already did this; replacing
   it with a dropdown was a regression,
.vm because a dropdown costs a
   click to open,
.vm a read to find,
.vm and a click to choose,
.vm every
   time.
   ============================================================ */
.modbar {
  position: sticky; top: var(--topbar-h); z-index: 55;
  /* Room for the focus ring, which needs 4px outside the item and
     cannot escape a scroll container. */
  padding-block: 3px;
  display: flex; align-items: stretch; gap: 1px;
  padding: 0 var(--gutter);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  overflow-x: auto; scrollbar-width: thin;
}
.vm .modbar-i {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  font-family: inherit; font-size: 12.5px; font-weight: 500;
  color: var(--muted-foreground);
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 11px; white-space: nowrap;
  border-bottom: 2px solid transparent;
}
.vm .modbar-i:hover { color: var(--foreground); background: var(--secondary); }
.vm .modbar-i.on {
  color: var(--primary); font-weight: 600;
  border-bottom-color: var(--primary); background: var(--card);
}
.vm /* Where you are when it is not one of the six tabs. Not a tab: no
   border,
.vm no hover,
.vm not clickable. It says the strip does not
   contain this screen,
.vm which is the honest thing for a Setup
   destination reached from the dropdown. */
.modbar-out {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 0 4px 0 2px; margin-left: 2px;
  font-size: 12px; font-weight: 600; color: var(--primary);
  white-space: nowrap; flex: 0 0 auto;
}
.vm .modbar-out > svg { color: var(--muted-foreground); flex: 0 0 12px; }
.vm /* The strip scrolls sideways when it does not fit,
.vm and a marker that
   says where you are is no use parked off the right edge. On a narrow
   screen it leads. */
@media (max-width: 900px) {
  .vm .modbar-out { order: -1; margin-left: 0; margin-right: 6px; }
  .vm .modbar-out > svg { display: none; }
}

.vm .modbar-n {
  font-size: 10.5px; font-weight: 700;
  background: var(--secondary); color: var(--secondary-foreground);
  border-radius: 8px; padding: 0 6px;
}
.vm .modbar-i.on .modbar-n { background: var(--primary-soft); color: var(--primary); }
.vm .modbar-r { margin-left: auto; display: flex; align-items: center; padding-left: 10px; }
.vm .modbar-more {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  font-family: inherit; font-size: 11.5px; font-weight: 600;
  color: var(--muted-foreground);
  display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 9px; border-radius: var(--r-sm); white-space: nowrap;
}
.vm .modbar-more:hover { background: var(--secondary); color: var(--foreground); }

.vm /* The strip is the primary way around,
.vm so the panel anchors to it. */
.modbar .menu-wrap { position: relative; }

@media (max-width: 640px) {
  .vm .modbar-i { padding: 9px 9px; font-size: 12px; }
}

.vm /* ============================================================
   Shell and screen header
   Full width,
.vm no max-width cap. Handoff 7.
   One header block per screen,
.vm not three rows.
   ============================================================ */
.shell { min-height: calc(100vh - var(--topbar-h)); padding: 14px var(--gutter); }

.vm .panel {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-panel);
  overflow: hidden;
}
.vm /* The slim action row that replaced the page title block. No
   title,
.vm no description,
.vm no panel: just the controls,
.vm right
   aligned,
.vm on one line. */
.page-acts {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  justify-content: flex-end;
  padding: 0 var(--gutter); margin: 10px 0 0;
}
@media (max-width: 640px) {
  .vm .page-acts { justify-content: stretch; }
  .vm .page-acts > .btn { flex: 1 1 auto; justify-content: center; }
}

.vm /* A flagged field states what is wrong,
.vm in text,
.vm next to the
   field. Before this the only signal was an amber border: nothing
   for a screen reader,
.vm and a faint tint for a colour-blind reader. */
.f-err {
  display: flex; align-items: flex-start; gap: 5px;
  margin-top: 4px; font-size: 11px; line-height: 1.4;
  color: var(--destructive);
}
.vm .f-err .fe-ico { flex: 0 0 12px; width: 12px; height: 12px; margin-top: 1px; }

.vm /* The required marker. The word is carried for assistive technology
   beside it,
.vm so the glyph is not the only statement. */
.f-req { color: var(--destructive); font-weight: 700; }

.vm /* A sortable column header. The th keeps aria-sort; the button is
   what makes it operable by keyboard. It inherits the header's own
   type so the table does not suddenly grow controls. */
.th-sort {
  appearance: none; background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; letter-spacing: inherit;
  text-transform: inherit; text-align: inherit;
  cursor: pointer; width: 100%; min-height: 24px;
}
.vm .th-sort:hover { color: var(--foreground); }

.vm /* The stage glyph,
.vm so a decided stage is not colour alone. */
.path-step .ps-ico { width: 11px; height: 11px; margin-right: 4px; flex: 0 0 11px; }

.vm /* Overview tiles. Each one is a button,
.vm because each one opens the
   tab it counts. In 8.1 the equivalent tiles were not interactive. */
.ov-grid {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
}
.vm .ov-tile {
  appearance: none; font-family: inherit; cursor: pointer; text-align: left;
  display: flex; flex-direction: column; gap: 2px;
  padding: 12px 14px; min-height: 88px;
  background: var(--card); border: 1px solid var(--input);
  border-radius: var(--r-md); color: var(--foreground);
}
.vm .ov-tile:hover { border-color: var(--ring); background: var(--secondary); }
.vm .ov-tile.bad .ov-n { color: var(--destructive); }
.vm .ov-tile .ov-n { font-size: 24px; font-weight: 700; line-height: 1.1; font-feature-settings: 'tnum'; }
.vm .ov-tile .ov-l { font-size: 12.5px; font-weight: 600; }
.vm .ov-tile .ov-s { font-size: 11px; color: var(--muted-foreground); }

.vm .ov-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 7px 0; border-bottom: 1px solid var(--border); cursor: pointer;
}
.vm .ov-row:last-child { border-bottom: 0; }
.vm .ov-row:hover .ov-r-t { color: var(--primary); }
.vm .ov-row .ov-r-t { font-size: 12.5px; font-weight: 600; min-width: 0; }
.vm .ov-row .ov-r-s { font-size: 11.5px; color: var(--muted-foreground); min-width: 0; flex: 1 1 auto; }
.vm .ov-row .ov-r-a { font-size: 11px; font-weight: 600; color: var(--destructive); flex: 0 0 auto; }

.vm /* A record's one line: the way back,
.vm the name,
.vm its metadata and its
   decisions. Replaces the panel that used to carry a title and a
   sentence of description. */
.rec-line {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px var(--gutter) 0;
}
.vm .rec-line .rl-t {
  font-size: 16px; font-weight: 650; letter-spacing: -.005em;
  flex: 0 0 auto; margin: 0;
}
.vm .rec-line .rl-m {
  font-size: 11.5px; color: var(--muted-foreground);
  min-width: 0; flex: 1 1 200px;
}
.vm .rec-line .rl-a {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  flex: 0 0 auto; margin-left: auto;
}
@media (max-width: 768px) {
  .vm .rec-line { gap: 7px; }
  .vm .rec-line .back-to { flex-basis: 100%; }
  .vm .rec-line .rl-a { margin-left: 0; flex-basis: 100%; }
  .vm .rec-line .rl-a > .btn { flex: 1 1 auto; justify-content: center; }
}

.vm /* Actions folded into a list toolbar,
.vm so they cost no extra row. */
.card-hd .card-act {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  flex: 0 0 auto; margin-left: 10px;
  padding-left: 10px; border-left: 1px solid var(--border);
}
@media (max-width: 900px) {
  .vm .card-hd .card-act { margin-left: 0; padding-left: 0; border-left: 0; flex-basis: 100%; }
}

.vm /* More air between sections than between fields,
.vm which is the
   opposite of where it was. */
.section { margin-top: 18px; }
.vm .section-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 0 0 7px;
}
.vm .section-head h2 { font-size: 14.5px; font-weight: 600; }
.vm .section-head .sh-r { margin-left: auto; display: flex; gap: 7px; align-items: center; }

.vm .grid { display: grid; gap: 10px; }
.vm .row { display: flex; align-items: center; gap: 8px; }
.vm .row.wrap { flex-wrap: wrap; }
.vm .spread { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.vm .right { margin-left: auto; }

.vm /* ============================================================
   Button,
.vm handoff 6.6. 34px,
.vm r-md,
.vm 13px/600,
.vm gap 7px.
   ============================================================ */
.btn {
  appearance: none; cursor: pointer; font-family: inherit;
  height: 34px; padding: 0 13px; border-radius: var(--r-md);
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font-size: 13px; font-weight: 600; white-space: nowrap;
  border: 1px solid transparent; background: var(--secondary);
  color: var(--secondary-foreground); transition: background .1s;
}
.vm .btn:hover { filter: brightness(.97); }
.vm .btn:active { filter: brightness(.94); }
.vm .btn.sm { height: 28px; padding: 0 10px; font-size: 12px; gap: 5px; }
.vm .btn.lg { height: 40px; padding: 0 17px; font-size: 14px; }
.vm .btn.p { background: var(--primary); color: var(--primary-foreground); }
.vm .btn.o { background: var(--card); color: var(--foreground); border-color: var(--input); }
.vm .btn.g { background: transparent; color: var(--muted-foreground); }
.vm .btn.g:hover { background: var(--secondary); color: var(--foreground); }
.vm .btn.ai { background: var(--ai); color: var(--on-strong); }
.vm .btn.d { background: var(--destructive); color: var(--on-strong); }
.vm .btn.ok { background: var(--success); color: var(--on-strong); }
.vm .btn[disabled] { opacity: .45; cursor: not-allowed; filter: none; }
.vm .btn-ico { width: 14px; height: 14px; flex: 0 0 14px; }
.vm .btn.icon-only { width: 34px; padding: 0; }
.vm .btn.sm.icon-only { width: 28px; }

.vm /* ============================================================
   Badge,
.vm handoff 6.6. 6px dot before the text so status never
   depends on colour alone.
   ============================================================ */
.badge {
  max-width: 100%;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 1px 9px; border-radius: var(--r-md);
  font-size: 11.5px; font-weight: 600; white-space: nowrap;
  background: var(--secondary); color: var(--secondary-foreground);
}
.vm .badge::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; flex: 0 0 6px; opacity: .85;
}
.vm .badge.nodot::before { display: none; }

.vm /* What a check does when it fails is a sentence,
.vm not a status. It
   reads as text next to the status badge rather than inside a
   second one,
.vm which is what pushed the page wider than the phone
   it was being read on. */
.on-fail {
  font-size: 11.5px; color: var(--muted-foreground);
  min-width: 0; overflow-wrap: anywhere;
}
.vm .badge.info { background: var(--info-soft);        color: var(--info); }
.vm .badge.ok { background: var(--success-soft);     color: var(--success); }
.vm .badge.warn { background: var(--warning-soft);     color: var(--warning); }
.vm .badge.bad { background: var(--destructive-soft); color: var(--destructive); }
.vm .badge.ai { background: var(--ai-soft);          color: var(--ai); }
.vm .badge.solid { background: var(--navy); color: var(--navy-foreground); }
.vm .badge.xs { font-size: 10.5px; padding: 0 7px; }

.vm .sup-q {
  height: 27px; padding: 0 9px; border-radius: var(--r-md);
  border: 1px solid var(--input); background: var(--card);
  font-family: inherit; font-size: 12px; color: var(--foreground);
  min-width: 0; width: 190px;
}
.vm .sup-q::placeholder { color: var(--muted-foreground); }
@media (max-width: 640px) { .vm .sup-q { width: 100%; } }

.vm .chip {
  display: inline-flex; align-items: center; gap: 5px;
  height: 27px; padding: 0 10px; border-radius: var(--r-md);
  border: 1px solid var(--input); background: var(--card);
  font-size: 12px; font-weight: 500; cursor: pointer; font-family: inherit;
  color: var(--foreground); white-space: nowrap;
}
.vm .chip:hover { background: var(--secondary); }
.vm .chip[aria-pressed="true"] {
  background: var(--primary); border-color: var(--primary);
  color: var(--primary-foreground); font-weight: 600;
}
.vm .chip .c-n { font-size: 11px; opacity: .75; }

.vm /* ============================================================
   Table,
.vm handoff 6.6. 12.5px body,
.vm 10px uppercase headers on
   surface,
.vm sticky,
.vm 7px vertical padding,
.vm hover on secondary.
   ============================================================ */
.tbl-wrap { overflow-x: auto; }
.vm table.tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.vm table.tbl thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface); text-align: left;
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--muted-foreground);
  padding: 6px 12px; border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.vm table.tbl tbody td {
  padding: 5px 12px; border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.vm table.tbl tbody tr:last-child td { border-bottom: 0; }
.vm table.tbl tbody tr.clickable { cursor: pointer; }
.vm table.tbl tbody tr.clickable:hover { background: var(--secondary); }
.vm table.tbl .num-cell { text-align: right; font-feature-settings: 'tnum'; }
.vm table.tbl .nowrap { white-space: nowrap; }
.vm .tbl-foot {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 7px 12px; border-top: 1px solid var(--border);
  background: var(--surface); font-size: 12px; color: var(--muted-foreground);
}

.vm /* Vendor identity cell,
.vm reused everywhere */
.vcell { display: flex; align-items: center; gap: 9px; min-width: 0; }
.vm .vmark {
  width: 28px; height: 28px; border-radius: var(--r-sm); flex: 0 0 28px;
  display: grid; place-items: center; font-size: 10.5px; font-weight: 700;
  background: var(--primary-soft); color: var(--primary);
}
.vm .vcell .vt { min-width: 0; line-height: 1.25; }
.vm .vcell .vn { font-size: 12.5px; font-weight: 600; }
.vm .vcell .vi { font-size: 10.5px; color: var(--muted-foreground); }

.vm /* ============================================================
   Cards,
.vm KPI tiles and work orders
   Card padding 14px,
.vm headers 9px by 14px,
.vm KPI figures 22px.
   ============================================================ */
.card {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-panel);
}
.vm .card-hd {
  padding: 6px 12px; border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
}
.vm .card-hd h3 { font-size: 13.5px; font-weight: 600; }
.vm .card-hd .ch-sub { font-size: 11px; color: var(--muted-foreground); }
.vm .card-bd { padding: 11px 12px; }
.vm .card-bd.flush { padding: 0; }
.vm .card-ft {
  padding: 6px 12px; border-top: 1px solid var(--border);
  background: var(--surface); font-size: 11.5px; color: var(--muted-foreground);
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}

.vm /* A work order is a KPI tile whose number carries the action that
   changes it. Every tile on a dashboard is one of these. */
.wo {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-panel);
  padding: 10px 12px; display: flex; flex-direction: column; gap: 7px;
  min-width: 0;
}
.vm .wo-top { display: flex; align-items: baseline; gap: 9px; }
.vm .wo-fig {
  font-size: 21px; font-weight: 700; line-height: 1;
  letter-spacing: -.02em; font-feature-settings: 'tnum';
  flex: 0 0 auto;
}
.vm .wo-fig.bad { color: var(--destructive); }
.vm .wo-fig.warn { color: var(--warning); }
.vm .wo-fig.ok { color: var(--success); }
.vm .wo-lbl { font-size: 12px; font-weight: 600; }
.vm .wo-sub {
  font-size: 11px; color: var(--muted-foreground); margin-top: 2px;
  /* Two lines maximum. A tile that grows with its caption makes a
     row of tiles as tall as its wordiest member. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.vm .wo-act { margin-top: auto; display: flex; gap: 5px; flex-wrap: wrap; }
.vm .wo.urgent { border-color: var(--destructive); box-shadow: 0 0 0 1px var(--destructive-soft), var(--shadow-panel); }

.vm /* Meter */
.meter { height: 6px; border-radius: 3px; background: var(--muted); overflow: hidden; }
.vm .meter > i { display: block; height: 100%; border-radius: 3px; background: var(--primary); }
.vm .meter > i.bad { background: var(--destructive); }
.vm .meter > i.warn { background: var(--warning); }
.vm .meter > i.ok { background: var(--success); }

.vm /* ============================================================
   AI surfaces. Cyan is reserved. An AI proposal always renders
   inline,
.vm next to the section it drafts for,
.vm with a dashed border
   and its own Accept and Reject. Collapsible: collapsed still
   shows the verdict,
.vm the confidence and a one-line gist.
   ============================================================ */
.ai-note {
  border: 1px dashed var(--ai-line); background: var(--ai-soft);
  border-radius: var(--r-md);
}
.vm .ai-hd {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  font-family: inherit; width: 100%; text-align: left;
  display: flex; align-items: center; gap: 7px;
  padding: 6px 10px;
  font-size: 11px; font-weight: 700; color: var(--ai);
  text-transform: uppercase; letter-spacing: .06em;
}
.vm .ai-hd .ai-t { min-width: 0; }
.vm .ai-hd .ai-conf {
  margin-left: auto; text-transform: none; letter-spacing: 0;
  font-weight: 600; font-size: 11px; opacity: .85; flex: 0 0 auto;
}
.vm .ai-hd .ai-chev { display: flex; flex: 0 0 14px; transition: transform .12s; }
.vm .ai-note.is-open .ai-hd .ai-chev { transform: rotate(180deg); }
.vm /* An agent finding that is not the screen summary. Same colour as
   the collapsible block so it reads as the same voice,
.vm no caret
   because there is nothing to collapse,
.vm and its action is always
   reachable. */
.ai-in {
  border: 1px solid var(--ai-line); background: var(--ai-soft);
  border-radius: var(--r-md); padding: 9px 11px;
}
.vm .ai-in + .ai-in { margin-top: 8px; }
.vm .ai-in-hd {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--ai);
}
.vm .ai-in-hd > svg { flex: 0 0 13px; }
.vm .ai-in-t { min-width: 0; }
.vm .ai-in-b { font-size: 12.5px; line-height: 1.5; margin-top: 5px; }
.vm .ai-in .ai-act { margin-top: 8px; }

.vm /* Content that stays visible whether the block is open or shut.
   Calls to action live here: an action inside a collapsed note is an
   action nobody finds. */
.ai-always { padding: 10px 12px 12px; }
.vm .ai-note.is-open .ai-always { padding-top: 0; }

.vm .ai-gist {
  padding: 0 10px 8px 31px; font-size: 12.5px; color: var(--foreground);
  cursor: pointer; line-height: 1.5;
}
.vm .ai-body { padding: 0 10px 9px 31px; font-size: 12.5px; color: var(--foreground); }
.vm .ai-act { display: flex; gap: 6px; padding: 0 10px 9px 31px; flex-wrap: wrap; }
.vm .ai-ico { width: 14px; height: 14px; flex: 0 0 14px; }
.vm .ai-cite {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; color: var(--ai); font-weight: 600;
  border-bottom: 1px dashed var(--ai-line); cursor: pointer;
}

.vm /* Reason list. A score with no reason list is banned. */
/* Duplicate compare,
.vm split. What matches on one side,
.vm what does
   not on the other,
.vm so the reader is not scanning across a table
   working out which column means what. */
.split-row {
  display: grid; grid-template-columns: 150px 1fr 1fr; gap: 10px;
  padding: 7px 12px; border-bottom: 1px solid var(--border);
  align-items: center; font-size: 12px;
}
.vm .split-row:last-child { border-bottom: 0; }
.vm .split-row .s-attr { display: flex; align-items: center; gap: 6px; font-weight: 600; flex-wrap: wrap; }
.vm .split-row .s-val { font-size: 11px; min-width: 0; overflow-wrap: anywhere; }
.vm .split-row.is-same { background: var(--success-soft); }
.vm .split-row.is-diff { background: var(--warning-soft); }
.vm .split-key {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 8px; padding: 7px 12px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); font-size: 11.5px; color: var(--muted-foreground);
}
@media (max-width: 768px) {
  .vm .split-row { grid-template-columns: minmax(0, 1fr); gap: 3px; }
  .vm .split-row .s-val::before { content: ''; }
}

.vm .cost-figs { display: flex; flex-wrap: wrap; gap: 4px 24px; }
.vm .cost-fig { display: flex; flex-direction: column; min-width: 0; }
.vm .cost-n {
  font-size: 17px; font-weight: 700; line-height: 1.15;
  font-feature-settings: 'tnum'; color: var(--foreground);
}
.vm .cost-l { font-size: 11px; color: var(--muted-foreground); line-height: 1.3; }

.vm /* A filter that carries consequence reads as one. */
.chip.is-risk { border-color: var(--destructive); color: var(--destructive); }
.vm .chip.is-risk[aria-pressed="true"] {
  background: var(--destructive); border-color: var(--destructive); color: var(--on-strong);
}

.vm .reasons { display: flex; flex-direction: column; gap: 0; }
.vm .reason {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 6px 0; border-bottom: 1px solid var(--border); font-size: 12.5px;
}
.vm .reason:last-child { border-bottom: 0; }
.vm .reason .r-pts {
  flex: 0 0 44px; text-align: right; font-weight: 700; font-size: 12px;
  font-feature-settings: 'tnum';
}
.vm .reason .r-pts.neg { color: var(--destructive); }
.vm .reason .r-body { min-width: 0; flex: 1; }
.vm .reason .r-src { font-size: 11px; color: var(--muted-foreground); margin-top: 2px; }

.vm /* ============================================================
   Queue archetype.
   A grid,
.vm not a flex row with one stretchy middle. The middle used
   to hold a short sentence and several hundred pixels of nothing,
.vm and the columns now line up down the list so the eye can run
   vertically instead of reading every row from the start.
   ============================================================ */
.qrow {
  display: grid;
  grid-template-columns: 22px 28px minmax(140px, 1.1fr) minmax(130px, 1fr) 96px minmax(150px, 1.3fr) 78px 84px;
  align-items: center; gap: 12px;
  padding: 7px 12px; border-bottom: 1px solid var(--border);
  cursor: pointer; background: var(--card);
}
.vm .qrow:last-child { border-bottom: 0; }
.vm .qrow:hover { background: var(--secondary); }
.vm .qrow .q-rank { text-align: center; font-size: 11px; font-weight: 700; color: var(--muted-foreground); }

.vm .qrow .q-who { min-width: 0; display: flex; flex-direction: column; }
.vm .qrow .q-name {
  font-size: 12.5px; font-weight: 600;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.vm .qrow .q-ref { font-size: 10.5px; color: var(--muted-foreground); }

.vm .qrow .q-what { min-width: 0; display: flex; flex-direction: column; }
.vm .qrow .q-type { font-size: 12px; overflow-wrap: anywhere; }
.vm .qrow .q-stage { font-size: 10.5px; color: var(--muted-foreground); }

.vm .qrow .q-state { min-width: 0; }
.vm .qrow .q-why2 {
  font-size: 11.5px; color: var(--muted-foreground); min-width: 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

.vm .qrow .q-num { text-align: right; display: flex; flex-direction: column; }
.vm .qrow .q-amt { font-size: 12px; font-weight: 700; font-feature-settings: 'tnum'; }
.vm .qrow .q-age { font-size: 10.5px; color: var(--muted-foreground); }
.vm .qrow .q-age.over { color: var(--destructive); font-weight: 600; }
.vm .qrow .q-act { display: flex; justify-content: flex-end; }

.vm /* A picker row. Looks like a queue row and is not one: it selects
   rather than opening,
.vm so it keeps its own class. */
.pick {
  display: grid; grid-template-columns: 22px minmax(0, 1fr) 88px;
  align-items: center; gap: 12px;
  padding: 8px 12px; border-bottom: 1px solid var(--border);
  cursor: pointer; background: var(--card);
}
.vm .pick:last-child { border-bottom: 0; }
.vm .pick:hover { background: var(--secondary); }
.vm .pick[aria-pressed="true"],
.vm .pick.on { background: var(--primary-soft); }
.vm .pick-n { text-align: center; font-size: 11px; font-weight: 700; color: var(--muted-foreground); }
.vm .pick-main { min-width: 0; display: flex; flex-direction: column; }
.vm .pick-t { font-size: 13px; font-weight: 600; }
.vm .pick-d { font-size: 11.5px; color: var(--muted-foreground); }
.vm .pick-num { text-align: right; display: flex; flex-direction: column; }

.vm /* A header row,
.vm so the columns are labelled rather than guessed at. */
.qhead {
  display: grid;
  grid-template-columns: 22px 28px minmax(140px, 1.1fr) minmax(130px, 1fr) 96px minmax(150px, 1.3fr) 78px 84px;
  align-items: center; gap: 12px;
  padding: 6px 12px; background: var(--surface);
  border-bottom: 1px solid var(--border);
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--muted-foreground);
}
.vm .qhead span:nth-child(7) { text-align: right; }

@media (max-width: 1100px) {
  .vm /* Drop the reason column first: it is the one the record repeats. */
  .qrow,
.vm .qhead { grid-template-columns: 22px 28px minmax(140px, 1.2fr) minmax(120px, 1fr) 92px 74px 84px; }
  .vm .qrow .q-why2,
.vm .qhead span:nth-child(6) { display: none; }
  .vm .qhead span:nth-child(7) { text-align: left; }
}
@media (max-width: 768px) {
  .vm .qhead { display: none; }
  .vm .qrow {
    grid-template-columns: 22px 28px minmax(0, 1fr) auto;
    grid-template-areas:
      'rank mark who  act'
      '.    .    what num'
      '.    .    state state';
    row-gap: 4px;
  }
  .vm .qrow .q-rank { grid-area: rank; }
  .vm .qrow .vmark { grid-area: mark; }
  .vm .qrow .q-who { grid-area: who; }
  .vm .qrow .q-what { grid-area: what; }
  .vm .qrow .q-state { grid-area: state; }
  .vm .qrow .q-num { grid-area: num; text-align: left; }
  .vm .qrow .q-act { grid-area: act; }
  .vm .qrow .q-why2 { display: none; }
}

.vm /* A bundle row expands to show its members */
.bundle-members { background: var(--surface); border-bottom: 1px solid var(--border); }
.vm .bundle-member {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 14px 7px 48px; font-size: 12px;
  border-bottom: 1px solid var(--border);
}
.vm .bundle-member:last-child { border-bottom: 0; }

.vm /* ============================================================
   Diff. The fix for the empty OLD panel. Current and proposed,
.vm side by side,
.vm always.
   ============================================================ */
.diff { display: flex; flex-direction: column; }
.vm .diff-hd {
  display: grid; grid-template-columns: 190px 1fr 1fr;
  gap: 12px; padding: 7px 14px; background: var(--surface);
  border-bottom: 1px solid var(--border);
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--muted-foreground);
}
.vm .diff-row {
  display: grid; grid-template-columns: 190px 1fr 1fr;
  gap: 12px; padding: 6px 14px; border-bottom: 1px solid var(--border);
  align-items: center;
}
.vm .diff-row:last-child { border-bottom: 0; }
.vm .diff-row .d-lbl { font-size: 12px; font-weight: 600; }
.vm .diff-row .d-lbl .d-path { font-size: 10px; color: var(--muted-foreground); font-weight: 400; display: block; }
.vm .diff-val { font-size: 12.5px; padding: 4px 9px; border-radius: var(--r-sm); }
.vm .diff-val.was { background: var(--surface); color: var(--muted-foreground); text-decoration: line-through; text-decoration-color: var(--muted-foreground); text-decoration-thickness: 1px; }
.vm .diff-val.now { background: var(--primary-soft); color: var(--foreground); font-weight: 600; }
.vm .diff-val.same { background: transparent; color: var(--muted-foreground); text-decoration: none; }
.vm .diff-val.unset { background: transparent; color: var(--muted-foreground); font-style: italic; }
.vm .diff-row.unchanged .diff-val.now { background: transparent; font-weight: 400; color: var(--muted-foreground); }

.vm /* An Add has nothing to compare against,
.vm so it renders as the
   value being added rather than a column of "not set". */
.vblock { padding: 10px 12px; display: flex; flex-direction: column; gap: 10px; }
.vm .v-lbl {
  display: block; font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--muted-foreground); margin-bottom: 3px;
}
.vm .v-val { font-size: 13px; font-weight: 600; }
.vm .vgrid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 10px 18px;
}
.vm .vpair { min-width: 0; }
.vm /* A postal address,
.vm laid out the way an envelope is. */
.addr { font-size: 13px; line-height: 1.5; }
.vm .addr span { display: block; }
.vm .vgroup { min-width: 0; }

.vm /* Labelled field groups.
   Separation runs sideways,
.vm divided by a vertical rule,
.vm so the
   groups share one row of fields. Stacking them instead read
   clearly but made the card 45% taller,
.vm which is the opposite of
   what was wanted. A rule plus an eyebrow costs nothing in height.
   Groups are weighted by how many fields they hold. */
.fgroups { display: flex; align-items: stretch; gap: 0; }
.vm .fgroup { flex: 1 1 0; min-width: 0; padding: 0 13px; }
.vm .fgroup:first-child { padding-left: 0; }
.vm .fgroup:last-child { padding-right: 0; }
.vm .fgroup + .fgroup { border-left: 1px solid var(--border); }
.vm .fgroup > .fg-hd {
  display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap;
  margin-bottom: 3px; min-height: 15px;
}
.vm .fgroup > .fg-hd .fg-t {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--muted-foreground); white-space: nowrap;
}
.vm .fgroup > .fg-hd .fg-n { font-size: 10.5px; color: var(--muted-foreground); }

.vm /* Below tablet the rule turns horizontal and the groups stack. */
@media (max-width: 900px) {
  .vm .fgroups { flex-direction: column; }
  .vm .fgroup { padding: 0; }
  .vm .fgroup + .fgroup {
    border-left: 0; border-top: 1px solid var(--border);
    margin-top: 9px; padding-top: 9px;
  }
}

.vm .diff-none {
  display: flex; align-items: center; gap: 9px;
  padding: 12px 14px; font-size: 12.5px; color: var(--muted-foreground);
}
.vm .diff-same {
  padding: 7px 14px; border-top: 1px solid var(--border); background: var(--surface);
  font-size: 11.5px; color: var(--muted-foreground);
}

.vm /* A bundle member,
.vm collapsed. Its fields live on its own record. */
.bmem {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 14px; border-bottom: 1px solid var(--border); cursor: pointer;
}
.vm .bmem:last-child { border-bottom: 0; }
.vm .bmem:hover { background: var(--secondary); }
.vm .bmem.is-here { background: var(--primary-soft); }
.vm .bmem .btn { pointer-events: none; }
.vm .bmem .b-ref { flex: 0 0 66px; font-size: 11.5px; font-family: 'IBM Plex Mono', monospace; color: var(--muted-foreground); }
.vm .bmem .b-main { flex: 1 1 auto; min-width: 0; }
.vm .bmem .b-type { font-size: 12.5px; font-weight: 600; }
.vm .bmem .b-sum { font-size: 11.5px; color: var(--muted-foreground); margin-top: 2px; }
.vm .bmem .b-r { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }

.vm /* ============================================================
   Check list. Every failure carries its fix.
   ============================================================ */
.check {
  display: flex; align-items: flex-start; gap: 11px;
  padding: 8px 12px; border-bottom: 1px solid var(--border);
}
.vm .check:last-child { border-bottom: 0; }
.vm .check .k-ico { flex: 0 0 18px; width: 18px; height: 18px; margin-top: 1px; }
.vm .check .k-ico.ok { color: var(--success); }
.vm .check .k-ico.bad { color: var(--destructive); }
.vm .check .k-ico.warn { color: var(--warning); }
.vm .check .k-ico.off { color: var(--muted-foreground); }
.vm .check .k-main { flex: 1 1 auto; min-width: 0; }
.vm .check .k-name { font-size: 12.5px; font-weight: 600; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.vm .check .k-ev { font-size: 11.5px; color: var(--muted-foreground); margin-top: 3px; }
.vm .check .k-fix { margin-top: 7px; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.vm .check .k-st { flex: 0 0 auto; }

.vm /* ============================================================
   Record archetype. Main panel plus a side rail.
   ============================================================ */
.record { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 11px; align-items: start; }
.vm .rail { display: flex; flex-direction: column; gap: 11px; }

.vm .rec-head {
  padding: 9px 14px; border-bottom: 1px solid var(--border);
}
.vm /* Title and actions share a row. Three stacked rows was the
   complaint,
.vm and the actions row was the one that earned its place
   least,
.vm because it repeated what the title already said. */
.rec-top {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
.vm /* The back link names where back is,
.vm rather than being an arrow
   the reader has to guess about. */
.back-to {
  appearance: none; cursor: pointer; font-family: inherit;
  display: inline-flex; align-items: center; gap: 5px;
  height: 28px; padding: 0 9px 0 6px; border-radius: var(--r-md);
  border: 1px solid var(--input); background: var(--card);
  font-size: 12px; font-weight: 600; color: var(--muted-foreground);
  white-space: nowrap; flex: 0 0 auto;
}
.vm .back-to:hover { background: var(--secondary); color: var(--foreground); }
.vm .rec-title { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; min-width: 0; flex: 1 1 320px; }
.vm .rec-title h1 { font-size: 18px; letter-spacing: -.005em; }
.vm .rec-title .r-ref { font-size: 12.5px; font-weight: 700; color: var(--muted-foreground); font-family: 'IBM Plex Mono', monospace; }
.vm .rec-meta {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 5px 14px 7px; font-size: 11.5px; color: var(--muted-foreground);
}
.vm .rec-meta .m-sep { opacity: .45; }

.vm /* Actions,
.vm grouped so position carries meaning. A filled button is
   the decision,
.vm an outlined one an ordinary alternative,
.vm and the
   menu holds the exceptions. */
.rec-acts { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; flex: 0 0 auto; }
.vm .acts-div {
  width: 1px; align-self: stretch; margin: 2px 4px;
  background: var(--border);
}
.vm .acts-menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 80;
  min-width: 268px; padding: 5px;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--r-md); box-shadow: var(--shadow-pop);
}
.vm .acts-item {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  font-family: inherit; text-align: left; width: 100%;
  display: block; padding: 7px 9px; border-radius: var(--r-sm);
  color: var(--foreground);
}
.vm .acts-item:hover { background: var(--secondary); }
.vm .acts-item .ai-t { display: block; font-size: 12.5px; font-weight: 600; }
.vm .acts-item .acts-note {
  display: block; font-size: 11px; color: var(--muted-foreground); margin-top: 2px;
}
.vm .acts-item.is-danger .ai-t { color: var(--destructive); }

.vm /* A blocked decision explains itself on the stage row,
.vm where it
   reads as a status. Between two buttons it read as a third one. */
.rec-stage { border-bottom: 1px solid var(--border); }
.vm .rec-blocked {
  display: flex; align-items: center; gap: 7px;
  padding: 5px 14px 7px; font-size: 11.5px; font-weight: 600;
  color: var(--destructive);
}
.vm .rec-blocked svg { flex: 0 0 14px; }

@media (max-width: 768px) {
  .vm .rec-acts { flex-basis: 100%; }
  .vm .acts-menu { right: auto; left: 0; min-width: 240px; }
}

.vm /* Tab strip */
.tabs {
  display: flex; gap: 2px; padding: 0 16px; border-bottom: 1px solid var(--border);
  overflow-x: auto; scrollbar-width: thin; background: var(--card);
}
.vm .tab {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  font-family: inherit; font-size: 12.5px; font-weight: 500;
  color: var(--muted-foreground); padding: 9px 12px;
  border-bottom: 2px solid transparent; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 6px;
}
.vm .tab:hover { color: var(--foreground); }
.vm .tab[aria-selected="true"] {
  color: var(--primary); font-weight: 600; border-bottom-color: var(--primary);
}
.vm .tab .t-n {
  font-size: 10.5px; font-weight: 700; background: var(--secondary);
  color: var(--secondary-foreground); border-radius: 8px; padding: 0 6px;
}
.vm .tab[aria-selected="true"] .t-n { background: var(--primary-soft); color: var(--primary); }

.vm /* Path indicator,
.vm borrowed from Salesforce. Where the document is
   in its lifecycle,
.vm on the record. */
/* overflow-x alone does not make a flex item scroll: without
   min-width it grows to fit its content and pushes the page
   instead. Five fixed-width stages at 320px did exactly that. */
.path {
  display: flex; gap: 3px; padding: 7px 14px;
  overflow-x: auto; scrollbar-width: thin;
  min-width: 0; max-width: 100%;
}
.vm .path-step {
  flex: 1 1 0; min-width: 96px; padding: 6px 10px;
  background: var(--secondary); color: var(--muted-foreground);
  font-size: 11px; font-weight: 600; text-align: center;
  clip-path: polygon(0 0, calc(100% - 9px) 0, 100% 50%, calc(100% - 9px) 100%, 0 100%, 9px 50%);
}
.vm .path-step:first-child { clip-path: polygon(0 0, calc(100% - 9px) 0, 100% 50%, calc(100% - 9px) 100%, 0 100%); }
.vm .path-step:last-child { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 9px 50%); }
.vm .path-step.done { background: var(--success-soft); color: var(--success); }
.vm .path-step.now { background: var(--primary); color: var(--primary-foreground); }
.vm .path-step.fail { background: var(--destructive); color: var(--on-strong); }

.vm /* Key-value grid */
dl.kv { display: grid; grid-template-columns: 124px 1fr; gap: 4px 12px; margin: 0; font-size: 12.5px; }
.vm dl.kv dt { color: var(--muted-foreground); font-size: 11.5px; }
.vm dl.kv dd { margin: 0; }

.vm /* Field,
.vm read-only display with an inline check badge */
.field { padding: 3px 0; }
.vm .field .f-lbl { display: block; font-size: 10.5px; font-weight: 600; color: var(--muted-foreground); margin-bottom: 2px; }
.vm .field .f-val {
  font-size: 13px; padding: 4px 9px; border: 1px solid var(--input);
  border-radius: var(--r-sm); background: var(--card);
  display: flex; align-items: center; gap: 8px; min-height: 28px;
}
.vm .field .f-val.flag { border-color: var(--warning); background: var(--warning-soft); }
.vm .field .f-val .f-badge { margin-left: auto; }
.vm .fgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 0 12px; }

.vm /* Timeline */
.tl { display: flex; flex-direction: column; }
.vm .tl-item { display: flex; gap: 11px; padding: 7px 0; border-bottom: 1px solid var(--border); }
.vm .tl-item:last-child { border-bottom: 0; }
.vm .tl-dot { flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%; background: var(--border); margin-top: 5px; }
.vm .tl-dot.ai { background: var(--ai); }
.vm .tl-dot.ok { background: var(--success); }
.vm .tl-dot.now { background: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
.vm .tl-body { min-width: 0; flex: 1; }
.vm .tl-who { font-size: 12.5px; font-weight: 600; }
.vm .tl-what { font-size: 12px; color: var(--muted-foreground); margin-top: 2px; }
.vm .tl-when { font-size: 10.5px; color: var(--muted-foreground); margin-top: 3px; }

.vm /* List item,
.vm used in rails */
.lst { display: flex; flex-direction: column; }
.vm .lst-item {
  display: flex; align-items: center; gap: 9px;
  padding: 6px 0; border-bottom: 1px solid var(--border); font-size: 12.5px;
}
.vm .lst-item:last-child { border-bottom: 0; }

.vm /* ============================================================
   Workbench archetype. Compare columns plus a findings block.
   ============================================================ */
.wb { display: grid; gap: 14px; }
.vm .wb-cols { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }

.vm /* ============================================================
   Registration wizard,
.vm supplier-facing.

   The step rail wraps rather than scrolls. A supplier on a phone
   needs to see how many steps are left,
.vm and a strip that scrolls
   hides exactly that.
   ============================================================ */
.reg { display: flex; flex-direction: column; gap: 18px; max-width: 1040px; }

.vm .reg-top {
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
  padding: 12px 14px;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-panel);
}
.vm .reg-top .r-name { font-size: 17px; font-weight: 700; letter-spacing: -.005em; }
.vm .reg-top .r-sub { font-size: 12px; color: var(--muted-foreground); min-width: 0; flex: 1 1 200px; }
.vm .reg-top .r-right { margin-left: auto; display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }

.vm .reg-rail { display: flex; flex-wrap: wrap; gap: 6px; }
.vm .reg-chip {
  appearance: none; cursor: pointer; font-family: inherit;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px 5px 6px; border-radius: 999px;
  border: 1px solid var(--input); background: var(--secondary);
  font-size: 12px; font-weight: 500; color: var(--secondary-foreground);
  white-space: nowrap;
}
.vm .reg-chip:hover { filter: brightness(.97); }
.vm .reg-chip-n {
  width: 18px; height: 18px; flex: 0 0 18px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--card); color: var(--muted-foreground);
  font-size: 10.5px; font-weight: 700; font-feature-settings: 'tnum';
}
.vm .reg-chip.is-done { background: var(--success-soft); border-color: var(--success); color: var(--success); }
.vm .reg-chip.is-done .reg-chip-n { background: var(--success); color: var(--on-strong); }
.vm .reg-chip.is-now {
  background: var(--primary); border-color: var(--primary);
  color: var(--primary-foreground); font-weight: 600;
}
.vm .reg-chip.is-now .reg-chip-n { background: var(--primary-foreground); color: var(--primary); }
.vm .reg-chip.has-flag { border-color: var(--destructive); }
.vm .reg-chip.has-flag:not(.is-now) { color: var(--destructive); }

.vm .reg-hd {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin-bottom: 10px;
}
.vm .reg-hd h2 { font-size: 19px; letter-spacing: -.005em; }
.vm .reg-hd .r-desc { font-size: 12.5px; color: var(--muted-foreground); min-width: 0; flex: 1 1 200px; }
.vm .reg-hd .r-right { margin-left: auto; }




.vm .reg-cite {
  display: flex; align-items: center; gap: 4px;
  font-size: 11px; color: var(--muted-foreground);
}
.vm .reg-cite svg { flex: 0 0 12px; width: 12px; height: 12px; }


.vm .reg-in {
  appearance: none; width: 100%; min-width: 0;
  min-height: 26px;
  border: 0; background: transparent; padding: 0;
  font-family: inherit; font-size: 13px; color: var(--foreground);
  /* The .f-val box draws the border, the background and the flag
     state. A control that drew its own would double them. */
}
.vm .reg-in:focus { outline: none; }
.vm .reg-in::placeholder { color: var(--muted-foreground); }
.vm select.reg-in { appearance: auto; cursor: pointer; }
.vm /* The popup list does not inherit the transparent background the box
   wants,
.vm so in dark mode it renders dark on dark. State it. */
select.reg-in option { background: var(--card); color: var(--foreground); }
.vm .field .f-val:focus-within { border-color: var(--ring); box-shadow: 0 0 0 2px var(--primary-soft); }
.vm .field .f-val.flag:focus-within { box-shadow: 0 0 0 2px var(--warning-soft); }

.vm /* The autofill offer. One row,
.vm never more than two lines tall: a
   taller one reads as a drop zone,
.vm and a drop zone in place of the
   form is what made step 1 look like a demonstration. */
.reg-offer {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 10px; margin-bottom: 12px;
  border: 1px dashed var(--ai-line); background: var(--ai-soft);
  border-radius: var(--r-md);
}
.vm .reg-offer > svg { flex: 0 0 15px; color: var(--ai); }
.vm .reg-offer .o-t { font-size: 12.5px; min-width: 0; flex: 1 1 240px; }
.vm .reg-offer .o-t b { color: var(--ai); }
.vm .reg-offer .o-a { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }

.vm /* Where a value came from,
.vm under the field holding it. */
.reg-from {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-top: 4px; font-size: 11px; color: var(--muted-foreground);
}
.vm .reg-from > svg { flex: 0 0 12px; width: 12px; height: 12px; }
.vm .reg-from .f-t { min-width: 0; }
.vm .reg-from .f-a { display: flex; gap: 5px; margin-left: auto; }
@media (max-width: 640px) {
  .vm .reg-from .f-a { margin-left: 0; flex-basis: 100%; }
}

.vm /* One proposal inside the AI block. A rule and some space,
.vm not a
   card,
.vm so the block stays one surface rather than a stack. */
.reg-fix {
  padding-top: 9px; margin-top: 9px;
  border-top: 1px solid var(--ai-line);
}
.vm .reg-fix:first-child { padding-top: 0; margin-top: 0; border-top: 0; }
.vm .reg-fix .x-t { font-size: 12.5px; font-weight: 600; display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.vm .reg-fix .x-b { font-size: 12px; color: var(--foreground); margin-top: 3px; }
.vm .reg-fix .x-a { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 7px; }

.vm /* A picked NAICS code. The whole chip removes it,
.vm so it states
   that on hover and takes focus like a control. */
.reg-pick {
  appearance: none; cursor: pointer; font-family: inherit;
  display: inline-flex; align-items: center; gap: 7px; max-width: 100%;
  padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--input); background: var(--secondary);
  font-size: 12px; color: var(--foreground); text-align: left;
}
.vm .reg-pick:hover { border-color: var(--destructive); color: var(--destructive); }
.vm .reg-pick .p-c { font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: var(--muted-foreground); flex: 0 0 auto; }
.vm .reg-pick:hover .p-c { color: var(--destructive); }
.vm .reg-pick .p-n { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vm .reg-pick .p-x { flex: 0 0 auto; opacity: .6; }
.vm .reg-pick:hover .p-x { opacity: 1; }

.vm /* Prose with no mic,
.vm so no room reserved for one. */
.reg-ta {
  width: 100%; min-height: 62px; resize: vertical;
  font-family: inherit; font-size: 13px; line-height: 1.45; color: var(--foreground);
  background: var(--card); border: 1px solid var(--input);
  border-radius: var(--r-md); padding: 8px 10px;
}
.vm .reg-ta::placeholder { color: var(--muted-foreground); }

.vm .reg-foot {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 11px 14px;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-panel);
}
.vm .reg-foot .r-mid { flex: 1 1 auto; min-width: 0; font-size: 12px; color: var(--muted-foreground); }

@media (max-width: 768px) {
  .vm /* Keep the way forward reachable without scrolling to it.

     This block used to also hold a verbatim copy of every desktop
     .reg-* rule,
.vm pasted in by mistake. It overrode the desktop
     rules below 768px,
.vm so a fix made above was silently undone on a
     phone: the .reg-in minimum height for the 24px target size was
     exactly that. Only the sticky footer belongs here. */
  .reg-foot {
    position: sticky; bottom: 0; z-index: 40;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    box-shadow: 0 -2px 10px oklch(0.3 0.05 250 / .07);
  }
}


.vm /* ============================================================
   Charts,
.vm plain SVG. Kept simple: a bar row set and a donut.
   ============================================================ */
/* The tallest bar UI.bars draws is 118px,
.vm and each column also
   carries a value above it and a label below. The box was 112px,
.vm so
   any chart whose largest bar hit the maximum spilled out of the
   top of its card and over the heading. Sized to what it can hold. */
.bars {
  display: flex; align-items: flex-end; gap: 10px;
  min-height: 162px; padding-top: 4px;
}
.vm .bar-col { flex: 1 1 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 6px; min-width: 0; }
.vm .bar {
  border-radius: var(--r-sm) var(--r-sm) 2px 2px; background: var(--primary);
  min-height: 3px; position: relative;
}
.vm .bar.ai { background: var(--ai); }
.vm .bar-lbl { font-size: 10.5px; color: var(--muted-foreground); text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vm .bar-val { font-size: 11px; font-weight: 700; text-align: center; }

.vm /* Funnel */
.funnel { display: flex; flex-direction: column; gap: 8px; }
.vm .fstep { display: grid; grid-template-columns: 1fr 58px 78px; gap: 10px; align-items: center; font-size: 12px; }
.vm .fstep .f-bar { height: 22px; border-radius: var(--r-sm); background: var(--primary-soft); position: relative; overflow: hidden; }
.vm .fstep .f-bar > i { display: block; height: 100%; background: var(--primary); }
.vm .fstep .f-n { text-align: right; font-weight: 700; font-feature-settings: 'tnum'; }
.vm .fstep .f-drop { font-size: 11px; color: var(--destructive); font-weight: 600; text-align: right; }

.vm /* ============================================================
   Toast and modal
   ============================================================ */
.toast {
  position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%);
  z-index: 300; background: var(--navy); color: var(--navy-foreground);
  padding: 10px 16px; border-radius: var(--r-md); box-shadow: var(--shadow-raised);
  font-size: 12.5px; font-weight: 600; display: flex; align-items: center; gap: 9px;
  max-width: calc(100vw - 32px);
}
.vm .modal-scrim {
  position: fixed; inset: 0; z-index: 200; background: oklch(0.2 0.03 258 / .42);
  display: grid; place-items: center; padding: 20px;
}
.vm .modal {
  background: var(--card); border-radius: var(--r-xl); box-shadow: var(--shadow-pop);
  width: min(620px, 100%); max-height: calc(100vh - 40px); overflow: auto;
  border: 1px solid var(--border);
}
.vm .modal-hd { padding: 14px 18px; border-bottom: 1px solid var(--border); }
.vm .modal-hd h3 { font-size: 15px; }
.vm .modal-bd { padding: 18px; }
.vm .modal-ft {
  padding: 12px 18px; border-top: 1px solid var(--border); background: var(--surface);
  display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap;
}

.vm /* ============================================================
   Long-form text with dictation.
   The mic sits inside the field,
.vm top right,
.vm so it reads as a way
   of filling this field rather than a page-level tool.
   ============================================================ */
.lt { display: block; }
.vm .lt-box { position: relative; }
.vm .lt textarea {
  width: 100%; min-height: 62px; resize: vertical;
  font-family: inherit; font-size: 13px; line-height: 1.45; color: var(--foreground);
  background: var(--card); border: 1px solid var(--input);
  border-radius: var(--r-md); padding: 8px 10px 8px 10px;
  padding-right: 104px;
}
.vm .lt textarea::placeholder { color: var(--muted-foreground); }
.vm .lt-mic {
  position: absolute; top: 6px; right: 6px;
  appearance: none; cursor: pointer; font-family: inherit;
  display: inline-flex; align-items: center; gap: 5px;
  height: 26px; padding: 0 9px; border-radius: var(--r-sm);
  border: 1px solid var(--input); background: var(--ai-soft); color: var(--ai);
  font-size: 11.5px; font-weight: 600;
}
.vm .lt-mic:hover { filter: brightness(.97); }
.vm .lt-mic[aria-pressed="true"] {
  background: var(--destructive); border-color: var(--destructive); color: var(--on-strong);
}
.vm .lt.is-live textarea { border-color: var(--ai); box-shadow: 0 0 0 2px var(--ai-soft); }
.vm .lt-live {
  display: flex; align-items: center; gap: 6px;
  margin-top: 5px; font-size: 11.5px; font-weight: 600; color: var(--ai);
}
.vm .lt-live svg { animation: lt-pulse 1.1s ease-in-out infinite; }
@keyframes lt-pulse { .vm 0%,
.vm 100% { opacity: 1 } .vm 50% { opacity: .35 } }
.vm .f-hint { font-size: 11px; color: var(--muted-foreground); margin-top: 4px; }

@media (max-width: 640px) {
  .vm /* The label alone is enough on a phone. */
  .lt textarea { padding-right: 44px; }
  .vm .lt-mic { padding: 0 6px; }
  .vm .lt-mic-t { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .vm .lt-live svg { animation: none; }
}

.vm .empty { padding: 40px 20px; text-align: center; color: var(--muted-foreground); }
.vm .empty h4 { font-size: 14px; color: var(--foreground); margin-bottom: 5px; }

.vm .note {
  border: 1px solid var(--border); background: var(--surface);
  border-radius: var(--r-md); padding: 8px 10px; font-size: 12.5px;
}
.vm .note.warn { border-color: var(--warning); background: var(--warning-soft); }
.vm .note.bad { border-color: var(--destructive); background: var(--destructive-soft); }
.vm .note.ok { border-color: var(--success); background: var(--success-soft); }
.vm .note.info { border-color: var(--info); background: var(--info-soft); }

.vm /* Utility spacing */
.mt0 {margin-top:0}.vm .mt4 {margin-top:4px}.vm .mt6 {margin-top:6px}.vm .mt8 {margin-top:8px}
.vm .mt10 {margin-top:10px}.vm .mt12 {margin-top:12px}.vm .mt14 {margin-top:11px}.vm .mt16 {margin-top:12px}
.vm .mb0 {margin-bottom:0}.vm .mb6 {margin-bottom:6px}.vm .mb8 {margin-bottom:8px}.vm .mb10 {margin-bottom:10px}.vm .mb12 {margin-bottom:9px}
.vm .g2 {gap:2px}.vm .g4 {gap:4px}.vm .g6 {gap:6px}.vm .g8 {gap:8px}.vm .g10 {gap:10px}.vm .g12 {gap:12px}.vm .g14 {gap:14px}
.vm .cols2 {display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
.vm .cols3 {display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
.vm .cols4 {display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}
.vm .cols5 {display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:10px}
.vm .flex1 {flex:1 1 auto;min-width:0}

.vm /* ============================================================
   RESPONSIVE. Set once,
.vm at the archetype level.
   IA document section 7.
   ============================================================ */

/* Below 1100px: module buttons go into an overflow menu rather
   than a scrolling strip. */
@media (max-width: 1100px) {
  .vm .modules .mod.overflowable { display: none; }
  .vm .modules .mod-more { display: inline-flex; }
}
@media (min-width: 1101px) {
  .vm .modules .mod-more { display: none; }
}

.vm /* Below 1024px: record side rail moves below the main panel.
   Designer three panes become a tab switch. Workbench stacks. */
@media (max-width: 1024px) {
  .vm .record { grid-template-columns: minmax(0, 1fr); }
  .vm .cols5,
.vm .cols4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .vm .cols3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .vm .menu { flex-wrap: wrap; max-width: calc(100vw - 32px); }
}

.vm /* Below 768px */
@media (max-width: 768px) {
  :root { --gutter: 16px; }
  .vm .cols5,
.vm .cols4,
.vm .cols3,
.vm .cols2 { grid-template-columns: minmax(0, 1fr); }
  .vm .diff-hd { display: none; }
  .vm .diff-row { grid-template-columns: minmax(0, 1fr); gap: 5px; }
  .vm .diff-row .d-lbl { margin-bottom: 2px; }
  .vm .diff-val.was::before { content: 'Current  '; font-size: 10px; font-weight: 700; letter-spacing: .06em; opacity: .7; }
  .vm .diff-val.now::before { content: 'Proposed  '; font-size: 10px; font-weight: 700; letter-spacing: .06em; opacity: .7; }
  .vm .fgrid { grid-template-columns: minmax(0, 1fr); }
  .vm dl.kv { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .vm dl.kv dd { margin-bottom: 7px; }
  .vm /* The whole module strip becomes a single overflow trigger.
     A scrolling strip of module buttons is what the handoff
     rejected,
.vm so it must not reappear at phone width. */
  .brand-sub { display: none; }
  .vm .modules .mod { display: none; }
  .vm .modules .mod-more { display: inline-flex; }
  .vm /* Six utility buttons do not fit a phone. Search,
.vm notifications
     and the account stay; tickets,
.vm inbox and the theme toggle fold
     into the overflow menu. */
  .util .foldable { display: none; }
  .vm .qrow { flex-wrap: wrap; }
  .vm .qrow .q-meta,
.vm .qrow .q-act { flex-basis: 100%; text-align: left; }
  .vm .qrow .q-act { justify-content: flex-start; }
  .vm /* A bundle member row is indented on desktop and wraps on a phone.
     Without this the per-member action pushes the page sideways. */
  .bundle-member { flex-wrap: wrap; padding-left: 14px; }
  .vm .bundle-member .right { margin-left: 0; flex-basis: 100%; }
}

.vm /* Below 640px: tables become one card per row carrying the
   columns that matter. Not horizontal scroll. */
@media (max-width: 640px) {
  .vm table.tbl thead { display: none; }
  .vm table.tbl,
.vm table.tbl tbody,
.vm table.tbl tr,
.vm table.tbl td { display: block; width: 100%; }
  .vm table.tbl tbody tr {
    border: 1px solid var(--border); border-radius: var(--r-md);
    margin-bottom: 9px; padding: 10px 12px; background: var(--card);
  }
  .vm table.tbl tbody td { border: 0; padding: 3px 0; }
  .vm table.tbl tbody td::before {
    content: attr(data-l); display: block;
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .07em; color: var(--muted-foreground); margin-bottom: 1px;
  }
  .vm table.tbl tbody td[data-l=""]::before { display: none; }
  .vm table.tbl .num-cell { text-align: left; }
  .vm /* Touch targets. WCAG 2.5.8 is 24px; primary actions get 44px. */
  .btn { height: 38px; }
  .vm .btn.p,
.vm .btn.ai,
.vm .btn.d,
.vm .btn.ok { height: 44px; }
  .vm .btn.sm { height: 32px; }
  .vm .util-btn { width: 40px; height: 40px; }
  .vm .tab { padding: 11px 12px; }
  .vm .path-step { min-width: 82px; }
}

@media (prefers-reduced-motion: reduce) {
  .vm *,
.vm *::before,
.vm *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

@media print {
  .vm .topbar,
.vm .page-acts,
.vm .rec-actions,
.vm .wo-act,
.vm .ai-act,
.vm .toast { display: none !important; }
  .vm .panel,
.vm .card { box-shadow: none; border-color: #ccc; }
  body { background: #fff; }
}
