/* PlanRelevé UI — token-based design system.
   Every visual value flows from the custom properties below; components never
   hardcode colors. Themes: light (default), dark via prefers-color-scheme,
   both overridable with <html data-theme="light|dark"> (set by shell.js). */

/* ------------------------------------------------------------------ tokens */
:root {
  color-scheme: light;
  /* type */
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Code", Menlo, Consolas, monospace;
  --fs-xs: 0.75rem;    /* 12 — eyebrows, fine print */
  --fs-sm: 0.8125rem;  /* 13 — small text floor (was 12.5) */
  --fs-md: 0.875rem;   /* 14 — controls, dense tables */
  --fs-base: 0.9375rem;/* 15 — body */
  --fs-h3: 1rem;
  --fs-h2: 1.15rem;
  --fs-h1: 1.5rem;
  /* spacing scale (4-based) */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px;
  /* radius */
  --r-xs: 6px; --r-sm: 8px; --r-md: 10px; --r-lg: 14px;
  /* neutrals — cool, blueprint-biased (chosen, not default grey) */
  --ground: #eef1f5;
  --surface: #ffffff;
  --surface-2: #f4f7fa;
  --sunken: #e2e8ef;
  --ink: #15202c;
  --ink-2: #3c4b5b;
  --ink-soft: #5d6e80;
  --line: #d8dfe7;
  --line-2: #c3cdd8;
  /* accent: blueprint ink; partner: copper (conductor) for key highlights */
  --accent: #2e6fb4;
  --accent-ink: #1f548c;
  --accent-wash: #e4edf6;
  --copper: #b96c2c;
  --copper-ink: #96551f;
  --copper-wash: #f3e7da;
  /* semantic — separate from the accent hue */
  --good: #287a4c;      --good-wash: #dceee2;
  --warn: #96660b;      --warn-wash: #f5e9cf;
  --crit: #bc3f3a;      --crit-wash: #f6dedc;
  --violet: #6443a0;    --violet-wash: #eae2f5;
  /* selected list rows: translucent yellow so it reads over any surface and
     stays distinct from the hover (surface-2) and accent washes */
  --sel-wash: rgba(250, 204, 21, 0.18);
  /* controls */
  --btn-primary-bg: var(--accent);
  --btn-primary-fg: #ffffff;
  --btn-primary-bg-hover: #255d99;
  --focus-ring: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent);
  /* elevation */
  --e1: 0 1px 2px rgba(20, 35, 50, 0.07), 0 1px 1px rgba(20, 35, 50, 0.04);
  --e2: 0 6px 20px rgba(20, 35, 50, 0.14), 0 2px 6px rgba(20, 35, 50, 0.08);
  --nav-shadow: 0 1px 3px rgba(20, 35, 50, 0.06);
  /* canvas frame: faint blueprint grid behind the plan */
  --canvas-bg: var(--sunken);
  --canvas-grid: rgba(46, 111, 180, 0.10);
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --ground: #0e1620;
    --surface: #16202c;
    --surface-2: #1c2836;
    --sunken: #101923;
    --ink: #e6edf4;
    --ink-2: #c2cfdc;
    --ink-soft: #93a5b7;
    --line: #273442;
    --line-2: #33424f;
    --accent: #5d9be0;
    --accent-ink: #8fbcec;
    --accent-wash: #1a2a3c;
    --copper: #da9860;
    --copper-ink: #e5b285;
    --copper-wash: #2c2115;
    --good: #4fb07a;   --good-wash: #14271c;
    --warn: #d4a23f;   --warn-wash: #2b2411;
    --crit: #db6560;   --crit-wash: #2e1614;
    --violet: #a486d8; --violet-wash: #251c36;
    --sel-wash: rgba(250, 204, 21, 0.16);
    --btn-primary-bg: #3d7fc4;
    --btn-primary-fg: #f2f7fc;
    --btn-primary-bg-hover: #4d8fd2;
    --e1: 0 1px 2px rgba(0, 0, 0, 0.45);
    --e2: 0 8px 24px rgba(0, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.35);
    --nav-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    --canvas-grid: rgba(93, 155, 224, 0.09);
  }
}

/* manual toggle wins over the OS preference, in both directions */
:root[data-theme="light"] {
  color-scheme: light;
  --ground: #eef1f5; --surface: #ffffff; --surface-2: #f4f7fa; --sunken: #e2e8ef;
  --ink: #15202c; --ink-2: #3c4b5b; --ink-soft: #5d6e80;
  --line: #d8dfe7; --line-2: #c3cdd8;
  --accent: #2e6fb4; --accent-ink: #1f548c; --accent-wash: #e4edf6;
  --copper: #b96c2c; --copper-ink: #96551f; --copper-wash: #f3e7da;
  --good: #287a4c; --good-wash: #dceee2;
  --warn: #96660b; --warn-wash: #f5e9cf;
  --crit: #bc3f3a; --crit-wash: #f6dedc;
  --violet: #6443a0; --violet-wash: #eae2f5;
  --sel-wash: rgba(250, 204, 21, 0.18);
  --btn-primary-bg: #2e6fb4; --btn-primary-fg: #ffffff; --btn-primary-bg-hover: #255d99;
  --e1: 0 1px 2px rgba(20, 35, 50, 0.07), 0 1px 1px rgba(20, 35, 50, 0.04);
  --e2: 0 6px 20px rgba(20, 35, 50, 0.14), 0 2px 6px rgba(20, 35, 50, 0.08);
  --nav-shadow: 0 1px 3px rgba(20, 35, 50, 0.06);
  --canvas-grid: rgba(46, 111, 180, 0.10);
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --ground: #0e1620; --surface: #16202c; --surface-2: #1c2836; --sunken: #101923;
  --ink: #e6edf4; --ink-2: #c2cfdc; --ink-soft: #93a5b7;
  --line: #273442; --line-2: #33424f;
  --accent: #5d9be0; --accent-ink: #8fbcec; --accent-wash: #1a2a3c;
  --copper: #da9860; --copper-ink: #e5b285; --copper-wash: #2c2115;
  --good: #4fb07a; --good-wash: #14271c;
  --warn: #d4a23f; --warn-wash: #2b2411;
  --crit: #db6560; --crit-wash: #2e1614;
  --violet: #a486d8; --violet-wash: #251c36;
  --sel-wash: rgba(250, 204, 21, 0.16);
  --btn-primary-bg: #3d7fc4; --btn-primary-fg: #f2f7fc; --btn-primary-bg-hover: #4d8fd2;
  --e1: 0 1px 2px rgba(0, 0, 0, 0.45);
  --e2: 0 8px 24px rgba(0, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.35);
  --nav-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  --canvas-grid: rgba(93, 155, 224, 0.09);
}

/* ------------------------------------------------------------------- base */
* { box-sizing: border-box; }
body {
  margin: 0; font-family: var(--sans); font-size: var(--fs-base); line-height: 1.5;
  color: var(--ink); background: var(--ground); -webkit-font-smoothing: antialiased;
  /* column layout so full-height workspaces size to the space left under the
     nav (and impersonation banner) instead of assuming a fixed nav height */
  min-height: 100vh; display: flex; flex-direction: column;
}
body > main { flex: 1; min-width: 0; }
/* workspace pages (review/cabling): a definite viewport height so the flex
   chain and the grid's 1fr row resolve against it — with only min-height the
   row falls back to max-content and the page grows past the viewport */
body.fullscreen { height: 100vh; overflow: hidden; }
a { color: var(--accent); text-decoration: none; text-underline-offset: 2px; }
a:hover { color: var(--accent-ink); text-decoration: underline; }
h1 { font-size: var(--fs-h1); font-weight: 700; letter-spacing: -0.01em; line-height: 1.2; }
h2 { font-size: var(--fs-h2); font-weight: 650; margin-top: 1.8em; }
h3 { font-size: var(--fs-h3); font-weight: 650; margin: 0.4em 0; }
h1, h2, h3 { text-wrap: balance; }
code { font-family: var(--mono); font-size: 0.85em; background: var(--sunken); padding: 1px 5px; border-radius: 4px; }

/* one visible keyboard-focus treatment everywhere */
:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--r-xs); }

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

/* icons: inline SVGs from _icons.html — stroke follows the text color */
.icon { width: 1.05em; height: 1.05em; vertical-align: -0.18em; flex: none; }
.btn .icon, .mainmenu .icon { margin-right: 5px; }
/* icon-only buttons: keep a tap target and never collapse to a bar */
.btn.icon-btn { min-width: 30px; min-height: 26px; padding-left: 6px; padding-right: 6px; justify-content: center; }
.btn.icon-btn .icon { margin: 0; }

/* ------------------------------------------------------------------ topnav */
.topnav {
  display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s4);
  background: var(--surface); color: var(--ink); border-bottom: 1px solid var(--line);
  box-shadow: var(--nav-shadow); position: relative; z-index: 30; flex-wrap: wrap;
}
.topnav .brand { font-weight: 750; color: var(--ink); display: inline-flex; align-items: center; gap: 7px; letter-spacing: -0.01em; }
.topnav .brand:hover { text-decoration: none; color: var(--accent-ink); }
.brand-mark { width: 20px; height: 20px; border-radius: 5px; background: linear-gradient(135deg, var(--accent), var(--accent-ink)); display: inline-flex; align-items: center; justify-content: center; color: #fff; flex: none; }
.brand-mark .icon { width: 13px; height: 13px; vertical-align: 0; }
.topnav .crumb { color: var(--ink-soft); }
.nav-select { margin-left: auto; }

.proj-chip {
  color: var(--ink-2); background: var(--surface-2); border: 1px solid var(--line);
  padding: 2px 10px; border-radius: 100px; max-width: 220px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-sm);
}
.mainmenu { display: flex; gap: 2px; }
.mainmenu a {
  display: inline-flex; align-items: center; padding: 5px 11px; border-radius: var(--r-xs);
  color: var(--ink-soft); text-decoration: none; font-size: var(--fs-md); white-space: nowrap;
}
.mainmenu a:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
.mainmenu a.active { background: var(--accent-wash); color: var(--accent-ink); font-weight: 650; }
/* nothing in the nav wraps: a wrapping badge reports no overflow, so the row
   silently grew to two and three lines tall instead of collapsing the labels */
.nav-extras { display: flex; align-items: center; gap: 10px; margin-left: auto; min-width: 0; white-space: nowrap; }
.nav-extras .badge { flex: none; }
/* the page picker ellipsizes but never collapses to nothing — it used to be
   squeezed to 0px wide before anything else in the row gave way */
.nav-extras .nav-select { margin-left: 0; max-width: 210px; min-width: 92px; }
/* above phone width the nav never wraps (the version used to fall onto a
   second line). The project menu NEVER shrinks — it used to be the flex item
   that gave way, scrolling its links out of sight behind a hidden scrollbar
   with no affordance at all. The chip and the page picker ellipsize instead. */
@media (min-width: 721px) {
  .topnav { flex-wrap: nowrap; }
  .topnav .crumb, .topnav .org-brand {
    flex: 0 1 auto; min-width: 60px; max-width: 260px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .mainmenu { flex: 0 0 auto; }
  .proj-chip { flex: 0 1 auto; min-width: 40px; }
  .nav-extras { flex: 0 1 auto; }
}
/* Not enough room for words: the menu keeps every icon and drops every label.
   Driven by shell.js measuring the real row, not by a width guess — the row's
   natural size swings by hundreds of px with the org name, the project name,
   the page picker and 8-vs-9 links. The media query is the no-JS fallback. */
.topnav.compact .nav-label { display: none; }
.topnav.compact .mainmenu .icon { margin-right: 0; }
.topnav.compact .mainmenu a { padding: 6px 8px; }
.topnav.compact .proj-chip { max-width: 150px; }
.topnav.compact .nav-extras .nav-select { max-width: 150px; }
/* still short: the org name is the least load-bearing thing in the row */
.topnav.compact-2 .org-brand { display: none; }
.topnav.compact-2 .proj-chip { max-width: 110px; }
@media (max-width: 1200px) {
  .mainmenu .nav-label { display: none; }
  .mainmenu .icon { margin-right: 0; }
  .mainmenu a { padding: 6px 8px; }
  .proj-chip { max-width: 150px; }
  .nav-extras .nav-select { max-width: 150px; }
}

/* account + settings popover: one trigger for everything that used to sit
   loose in the nav (bug report, suppliers, admin, super, theme, language,
   version, logout) */
.nav-menu { position: relative; flex: none; }
/* the popover is trapped in the nav's stacking context, which sits under the
   fixed editor drawers (z 70) at narrow widths — lift the whole bar while it
   is open rather than reshuffling the drawer layering */
.topnav.menu-open { z-index: 90; }
.nav-menu-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  border: 1px solid var(--line-2); border-radius: 50%; background: var(--surface);
  color: var(--ink-soft); cursor: pointer; padding: 0;
}
.nav-menu-btn:hover { color: var(--accent); border-color: var(--accent); }
.nav-menu-btn .icon { width: 15px; height: 15px; vertical-align: 0; }
.nav-avatar { font-size: 12.5px; font-weight: 700; color: var(--ink-2); line-height: 1; }
.nav-menu-btn.has-news::after {
  content: ""; position: absolute; top: -1px; right: -1px; width: 8px; height: 8px;
  border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--surface);
}
.nav-menu-pop {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 80; min-width: 216px;
  padding: 5px; background: var(--surface); border: 1px solid var(--line-2);
  border-radius: var(--r-sm); box-shadow: var(--e2);
}
.nav-menu-pop[hidden] { display: none; }
.nav-menu-pop .logout-form { display: block; }
.nav-menu-who {
  padding: 5px 9px 7px; font-size: 11.5px; color: var(--ink-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 260px;
}
.nav-menu-sep { height: 1px; margin: 5px 0; background: var(--line); }
.nav-menu-item {
  display: flex; align-items: center; gap: 9px; width: 100%; box-sizing: border-box;
  padding: 7px 9px; border: 0; border-radius: var(--r-xs); background: none;
  color: var(--ink-2); font: inherit; font-size: var(--fs-sm); text-align: left;
  text-decoration: none; cursor: pointer; white-space: nowrap;
}
.nav-menu-item:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
.nav-menu-item .icon { width: 15px; height: 15px; margin: 0; flex: none; }
.nav-menu-emoji { width: 15px; text-align: center; flex: none; }
.nav-menu-field { cursor: default; }
.nav-menu-field:hover { background: none; }
.nav-menu-field .lang-select { margin-left: auto; }
.nav-menu-hint { margin-left: auto; color: var(--ink-soft); font-size: 11.5px; }
/* the theme button and version link keep their ids/classes (shell.js drives
   the icon swap and the what's-new dot) but drop their standalone chrome */
.nav-menu-pop .theme-btn,
.nav-menu-pop .version-link {
  width: 100%; height: auto; border: 0; border-radius: var(--r-xs);
  justify-content: flex-start; margin-left: 0; padding: 7px 9px;
  font-size: var(--fs-sm); background: none;
}
.nav-menu-pop .theme-btn:hover,
.nav-menu-pop .version-link:hover { background: var(--surface-2); color: var(--ink); border-color: transparent; }
.nav-menu-pop .theme-btn .icon { width: 15px; height: 15px; }
.nav-menu-pop .version-link.has-news::after { top: 9px; right: 9px; }

/* dashboard: disabled pages stay listed (to re-enable) but visually muted */
tr.pg-disabled td { opacity: 0.45; }
tr.pg-disabled .pg-active-cell { opacity: 1; }
.pg-active-cell { margin-right: 8px; white-space: nowrap; }

/* hover tooltip: legend symbol of the detection under the cursor */
#det-hover-tip {
  position: fixed; z-index: 3500; display: flex; align-items: center; gap: 8px;
  max-width: 280px; padding: 6px 9px; pointer-events: none;
  background: var(--surface); border: 1px solid var(--line-2);
  border-radius: var(--r-xs); box-shadow: var(--e2); font-size: 12px;
}
#det-hover-tip[hidden] { display: none; }
#det-hover-tip .tip-icon { flex: 0 0 auto; max-width: 48px; max-height: 48px; }
#det-hover-tip .tip-text { min-width: 0; }
#det-hover-tip .tip-text div { color: var(--ink-soft); font-size: 11px; }
/* the yellow like-item count: capped and filtered sets differ from the
   sheet's own total, so the tip says which number it is showing */
#det-hover-tip .tip-like { color: var(--copper-ink); }

/* searchable class picker (context-menu companion) */
.class-picker { padding: 6px; width: 236px; }
.class-picker input { width: 100%; box-sizing: border-box; margin-bottom: 4px; }
.class-picker-list { max-height: 220px; overflow: auto; }
.class-picker-list button.sel { background: var(--accent-wash); color: var(--accent-ink); }
.class-picker-create { font-style: italic; }

/* nav version label + what's-new dot (dot until /changelog is opened) */
.version-link {
  position: relative; margin-left: 2px; font-size: 11.5px; color: var(--ink-soft);
  text-decoration: none; padding: 3px 5px; border-radius: var(--r-xs); white-space: nowrap;
}
.version-link:hover { color: var(--accent-ink); background: var(--surface-2); text-decoration: none; }
.version-link.has-news::after {
  content: ""; position: absolute; top: 1px; right: -1px; width: 7px; height: 7px;
  border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--surface);
}

/* changelog page */
.changelog { max-width: 720px; }
.cl-entry h2 { margin: 0 0 8px; font-size: 17px; }
.cl-date { font-weight: 400; margin-left: 6px; }
.cl-list { margin: 0; padding-left: 0; list-style: none; display: grid; gap: 8px; }
.cl-chip {
  display: inline-block; font-size: 10.5px; font-weight: 650; letter-spacing: 0.02em;
  padding: 1px 7px; border-radius: 999px; margin-right: 6px; vertical-align: 1px;
}
.cl-feature { background: var(--accent-wash); color: var(--accent-ink); }
.cl-fix { background: var(--good-wash); color: var(--good); }
.cl-improvement { background: var(--warn-wash); color: var(--warn); }

/* theme toggle: shows the icon of the theme it switches to */
.theme-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  border: 1px solid var(--line-2); border-radius: var(--r-xs); background: var(--surface);
  color: var(--ink-soft); cursor: pointer; padding: 0;
}
.theme-btn:hover { color: var(--accent); border-color: var(--accent); }
.theme-btn .icon { width: 15px; height: 15px; vertical-align: 0; }
:root:not([data-theme="dark"]) .theme-btn .icon-sun { display: none; }
:root[data-theme="dark"] .theme-btn .icon-moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .theme-btn .icon-sun { display: inline; }
  :root:not([data-theme]) .theme-btn .icon-moon { display: none; }
}

/* branding */
.brand-logo { height: 22px; vertical-align: middle; margin-right: 6px; border-radius: 4px; }
.org-brand { color: var(--ink-soft); font-size: var(--fs-sm); display: flex; align-items: center; }
.brand-current { display: flex; align-items: center; gap: 10px; margin-top: 8px; }

/* impersonation banner — deliberately loud, never theme-quiet */
.imp-banner {
  background: var(--violet); color: #fff; padding: 6px 14px; display: flex;
  gap: 12px; align-items: center; font-size: var(--fs-sm); position: sticky; top: 0; z-index: 60;
}
.imp-banner .btn { background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.5); color: #fff; }

/* ---------------------------------------------------------------- layout */
.container { max-width: 1100px; margin: 0 auto; padding: var(--s5) var(--s5) var(--s6); width: 100%; }
.review-main { padding: 0; display: flex; min-height: 0; }

.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: var(--s4); margin: var(--s3) 0; box-shadow: var(--e1);
}
.card.error { border-color: var(--crit); color: var(--crit); background: var(--crit-wash); }
.card.notice { border-color: var(--good); color: var(--good); background: var(--good-wash); }
.card.warning { border-color: var(--warn); background: var(--warn-wash); }
.toolbar { display: flex; align-items: center; gap: var(--s2); margin: var(--s2) 0; flex-wrap: wrap; }
/* Text inputs inside a toolbar match the buttons' height so a mixed row
   of input + buttons sits on one clean baseline. */
.toolbar .toolbar-input { padding: 7px 10px; margin: 0; }
/* Secondary filter row under a toolbar (checkboxes etc.) — tighter to its
   parent row and visually subordinate. */
.toolbar.toolbar-filters { margin-top: calc(-1 * var(--s1)); gap: var(--s3); }
.muted { color: var(--ink-soft); }
.small-text { font-size: var(--fs-sm); }
.warn-text { color: var(--crit); }
/* file inputs stay focusable for keyboard/SR users (display:none removed
   them from the tab order entirely — uploading was mouse-only); the label
   shows the focus ring via :focus-within */
.sr-file-input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  border: 0;
}
/* the inputs sit AFTER their labels in the DOM, so the ring uses :has() */
.dropzone:focus-within,
label.btn:focus-within,
.dropzone:has(+ .sr-file-input:focus-visible),
label.btn:has(+ .sr-file-input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.page-head { display: flex; align-items: baseline; gap: 18px; flex-wrap: wrap; }
.section-head { display: flex; align-items: center; gap: var(--s3); }
.section-head h2 { margin-right: auto; }

/* --------------------------------------------------------------- controls */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  padding: 6px 13px; border: 1px solid var(--line-2); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink-2); cursor: pointer;
  font-size: var(--fs-md); font-family: var(--sans); line-height: 1.4; text-decoration: none;
}
.btn:hover { background: var(--surface-2); color: var(--ink); border-color: var(--ink-soft); text-decoration: none; }
.btn.primary { background: var(--btn-primary-bg); border-color: var(--btn-primary-bg); color: var(--btn-primary-fg); font-weight: 600; }
.btn.primary:hover { background: var(--btn-primary-bg-hover); border-color: var(--btn-primary-bg-hover); color: var(--btn-primary-fg); }
.btn.small { padding: 3px 9px; font-size: var(--fs-sm); border-radius: var(--r-xs); }
.btn.ghost { border-color: transparent; background: transparent; }
.btn.ghost:hover { background: var(--surface-2); border-color: transparent; }
.btn.ok { border-color: var(--good); color: var(--good); }
.btn.ok:hover { background: var(--good-wash); color: var(--good); }
.btn.warn { border-color: var(--warn); color: var(--warn); }
.btn.warn:hover { background: var(--warn-wash); color: var(--warn); }
.btn.danger { border-color: var(--crit); color: var(--crit); }
.btn.danger:hover { background: var(--crit-wash); color: var(--crit); }
.btn.active { outline: 2px solid var(--accent); outline-offset: -1px; }
.btn:disabled { opacity: 0.45; cursor: default; }
.btn:disabled:hover { background: var(--surface); border-color: var(--line-2); color: var(--ink-2); }
/* an action that used to be a link out to another page and now stays here:
   it still reads as a link inside a sentence, but it is a button */
.btn-link {
  background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
  color: var(--accent); text-decoration: underline;
}
.btn-link:hover { color: var(--accent-ink); }

/* one input spec: same border, radius and focus treatment everywhere */
input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="search"], select, textarea {
  font-family: var(--sans); font-size: var(--fs-md); color: var(--ink);
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-xs);
  padding: 5px 8px;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-wash);
}
input::placeholder { color: var(--ink-soft); opacity: 0.75; }
label { color: var(--ink-2); }

/* ----------------------------------------------------------------- tables */
.table { border-collapse: collapse; width: 100%; background: var(--surface); }
.table th, .table td { border: 1px solid var(--line); padding: 7px 9px; text-align: left; font-size: var(--fs-md); }
.table th { background: var(--surface-2); color: var(--ink-soft); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 650; }
.table.small th, .table.small td { padding: 4px 7px; font-size: var(--fs-sm); }
.table.small th { font-size: 0.68rem; }
.table td { font-variant-numeric: tabular-nums; }
.table tr.selected { background: var(--sel-wash); }
.table tr { cursor: default; }
.table-scroll { max-height: calc(100vh - 220px); overflow: auto; }
#det-table tbody tr, #paths-table tbody tr, #zones-table tbody tr[data-id] { user-select: none; cursor: pointer; }
#det-table tbody tr:hover, #paths-table tbody tr:hover,
#zones-table tbody tr[data-id]:hover { background: var(--surface-2); }
#det-table tbody tr.selected:hover, #paths-table tbody tr.selected:hover,
#zones-table tbody tr.selected:hover { background: var(--sel-wash); }
#det-table td:first-child { font-family: var(--mono); font-size: 0.72rem; }
/* the editor list tables must fit the 336px drawer: fixed layout with pinned
   narrow columns; the class/cable column absorbs the rest and ellipsizes
   (the full class name stays available via the cell's title tooltip). The
   pinned widths also apply windowed — the flexible column takes the slack. */
.drawer .table-scroll { overflow-x: hidden; }
#det-table, #paths-table, #zones-table { table-layout: fixed; }
#det-table th, #det-table td, #paths-table th, #paths-table td,
#zones-table th, #zones-table td {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#det-table th:nth-child(1) { width: 86px; }
#det-table th:nth-child(3) { width: 72px; }
#det-table th:nth-child(4) { width: 44px; }
#det-table td:nth-child(4) { text-align: right; }
#paths-table th:nth-child(1) { width: 56px; }
#paths-table th:nth-child(3) { width: 62px; }
#paths-table th:nth-child(4) { width: 56px; }
#paths-table th:nth-child(5) { width: 40px; }
#paths-table td:nth-child(5) { padding-left: 2px; padding-right: 2px; }
/* zones: key, class (flexible), area, void flag, delete */
#zones-table th:nth-child(1) { width: 56px; }
#zones-table th:nth-child(3) { width: 66px; }
#zones-table th:nth-child(4) { width: 38px; }
#zones-table th:nth-child(5) { width: 40px; }
#zones-table td:nth-child(5) { padding-left: 2px; padding-right: 2px; }

/* ----------------------------------------------------------------- badges */
.badge { padding: 2px 9px; border-radius: 100px; font-size: var(--fs-xs); background: var(--sunken); color: var(--ink-2); font-weight: 550; }
.badge.mode-vector_text { background: var(--good-wash); color: var(--good); }
.badge.mode-raster_scan { background: var(--copper-wash); color: var(--copper-ink); }
.badge.mode-mixed { background: var(--violet-wash); color: var(--violet); }
.badge.scope-default { background: var(--sunken); color: var(--ink-soft); }
.badge.scope-org { background: var(--good-wash); color: var(--good); }
.badge.scope-project { background: var(--accent-wash); color: var(--accent-ink); }
.badge.warn { background: var(--warn-wash); color: var(--warn); }

.status-confirmed { color: var(--good); }
.status-candidate { color: var(--warn); }
.status-manual { color: var(--accent-ink); }
.status-ignored { color: var(--ink-soft); }
.status-needs_review { color: var(--violet); }

/* ------------------------------------------------------------- stat chips */
.stats-row { display: flex; gap: var(--s2); flex-wrap: wrap; }
.stat-chip {
  display: inline-flex; align-items: baseline; gap: 6px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 5px 12px; font-size: var(--fs-sm); color: var(--ink-soft); box-shadow: var(--e1);
}
.stat-chip b { color: var(--ink); font-family: var(--mono); font-size: 1rem; font-weight: 700; }
.stat-chip.attention b { color: var(--copper-ink); }

/* -------------------------------------------------------------- dashboard */
.steps-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--s3); margin: var(--s4) 0; }
.step-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s4); box-shadow: var(--e1); }
.step-card h3 { margin: 0 0 6px; font-size: var(--fs-h3); color: var(--ink); }
.step-card p { margin: 0 0 12px; font-size: var(--fs-sm); color: var(--ink-soft); }
.cls-chip { display: inline-block; background: var(--accent-wash); border-radius: var(--r-xs); padding: 0 7px; margin: 0 3px 2px 0; font-size: var(--fs-xs); color: var(--accent-ink); text-decoration: none; }
.cls-chip:hover { background: var(--sunken); text-decoration: none; }
.est-grand { border-top: 2px solid var(--accent); margin-top: 6px; padding-top: 6px; }

/* ---------------------------------------------------------- review layout */
/* the single row is pinned to the container height (an auto row would grow
   to the tallest panel's content and push the whole page into overflow) */
.review-layout {
  display: grid; grid-template-columns: 250px 1fr 330px;
  grid-template-rows: minmax(0, 1fr); flex: 1; min-width: 0; min-height: 0;
}
/* rail UI: [tool rail][toolbox?][canvas][drawer?][drawer rail] — columns are
   assigned explicitly because display:none panes would otherwise shift the
   auto-placed canvas into the wrong track */
.review-layout.rail-ui {
  grid-template-columns: 46px auto minmax(0, 1fr) auto 46px;
}
.review-layout.rail-ui > .tool-rail { grid-column: 1; grid-row: 1; }
.review-layout.rail-ui > .toolbox { grid-column: 2; grid-row: 1; }
.review-layout.rail-ui > .canvas-wrap { grid-column: 3; grid-row: 1; }
.review-layout.rail-ui > .drawer { grid-column: 4; grid-row: 1; }
.review-layout.rail-ui > .drawer-rail { grid-column: 5; grid-row: 1; }

/* --------------------------------------------------- icon rails + toolbox */
.tool-rail, .drawer-rail {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 8px 0; background: var(--surface); z-index: 26;
}
/* the review rail carries both toolsets plus the queue and the help button
   (15 buttons ≈ 694px). On a short desktop viewport it WRAPS into a second
   column (see the max-height rule further down) rather than scrolling — a
   scrolled rail hides tools behind a gesture nobody looks for. The scroll
   stays as the last-resort fallback for narrow widths, where the grid has
   only one 46px rail track to give it. */
.tool-rail { border-right: 1px solid var(--line); overflow-y: auto; scrollbar-width: thin; }
.drawer-rail { border-left: 1px solid var(--line); overflow-y: auto; scrollbar-width: thin; }
/* pinned to the bottom of the rail, and NOT a .rail-btn: toolbox.js binds
   every rail button to choose(data-tool) */
.rail-help {
  margin-top: auto; width: 38px; height: 38px; border: none; border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: var(--ink-soft); cursor: pointer;
}
.rail-help:hover { background: var(--surface-2); color: var(--ink); }
.rail-help .icon { width: 19px; height: 19px; }
.rail-btn {
  position: relative; width: 38px; height: 38px; border: none; border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: var(--ink-soft); cursor: pointer;
}
.rail-btn:hover { background: var(--surface-2); color: var(--ink); }
.rail-btn.active { background: var(--accent-wash); color: var(--accent-ink); }
.rail-btn .icon { width: 19px; height: 19px; }
.rail-sep { width: 22px; border-top: 1px solid var(--line); margin: 4px 0; }
.rail-badge {
  position: absolute; top: 1px; right: 1px; min-width: 15px; height: 15px; padding: 0 3px;
  border-radius: 8px; background: var(--accent); color: #fff; font-size: 0.6rem;
  font-family: var(--mono); line-height: 15px; text-align: center;
}
/* keyboard hint inside the tooltip only — native title attribute carries it */

.toolbox {
  width: 264px; background: var(--surface); border-right: 1px solid var(--line);
  overflow-y: auto; padding: var(--s2) var(--s3) var(--s5);
  display: flex; flex-direction: column; min-height: 0;
}
.toolbox[hidden] { display: none; }
.toolbox-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--s1); }
.toolbox-head h3 { margin: 0; }
.toolbox-close {
  border: none; background: transparent; color: var(--ink-soft); cursor: pointer;
  width: 26px; height: 26px; border-radius: var(--r-xs); display: inline-flex;
  align-items: center; justify-content: center;
}
.toolbox-close:hover { background: var(--surface-2); color: var(--ink); }
.toolbox-pane[hidden] { display: none; }
/* panes inherit the .panel form rhythm */
.toolbox label { display: block; font-size: var(--fs-sm); margin: 9px 0 3px; color: var(--ink-2); }
.toolbox input[type="range"] { width: 100%; accent-color: var(--accent); }
.toolbox select, .toolbox input[type="text"] { width: 100%; margin: 2px 0; }
.toolbox .check { display: flex; align-items: center; gap: 6px; }
.toolbox .check input { accent-color: var(--accent); }
.toolbox .tiny { width: 64px; }
.toolbox .btn { width: 100%; margin: 4px 0; }
.toolbox .toolbar .btn { width: auto; margin: 0; flex: 1 1 auto; }
.toolbox output { float: right; color: var(--ink-soft); font-family: var(--mono); font-size: var(--fs-xs); }
.toolbox hr { border: none; border-top: 1px solid var(--line); margin: var(--s3) 0; }
.toolbox details summary { cursor: pointer; font-size: var(--fs-sm); color: var(--ink-soft); margin: var(--s2) 0; }

.drawer {
  width: 336px; background: var(--surface); border-left: 1px solid var(--line);
  overflow-y: auto; padding: var(--s3) var(--s3) 72px; min-height: 0;
}
.drawer[hidden] { display: none; }
.drawer h3, .drawer h4, .toolbox h3, .toolbox h4 {
  font-family: var(--mono); font-size: 0.68rem; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--ink-soft); margin: var(--s2) 0 var(--s2);
}
.drawer label { font-size: var(--fs-sm); color: var(--ink-2); }
.drawer .check input { accent-color: var(--accent); }
.panel { background: var(--surface); padding: var(--s3) var(--s3) var(--s5); overflow-y: auto; border-right: 1px solid var(--line); }
.panel.right { border-right: none; border-left: 1px solid var(--line); }
.panel h3, .panel h4 {
  font-family: var(--mono); font-size: 0.68rem; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--ink-soft); margin: var(--s2) 0 var(--s2);
}
.panel label { display: block; font-size: var(--fs-sm); margin: 9px 0 3px; color: var(--ink-2); }
.panel input[type="range"] { width: 100%; accent-color: var(--accent); }
.panel select, .panel input[type="text"] { width: 100%; margin: 2px 0; }
.panel .check { display: flex; align-items: center; gap: 6px; }
.panel .check input { accent-color: var(--accent); }
.panel .tiny { width: 64px; }
.panel .btn { width: 100%; margin: 4px 0; }
/* …except inside toolbars, where related actions share one row */
.panel .toolbar .btn { width: auto; margin: 0; flex: 1 1 auto; }
.panel output { float: right; color: var(--ink-soft); font-family: var(--mono); font-size: var(--fs-xs); }
.panel hr { border: none; border-top: 1px solid var(--line); margin: var(--s4) 0; }
.panel details summary { cursor: pointer; font-size: var(--fs-sm); color: var(--ink-soft); margin: var(--s2) 0; }

/* the plan sits on a sunken blueprint grid so the page edge reads clearly */
.canvas-wrap {
  position: relative; overflow: hidden; background: var(--canvas-bg);
  background-image: linear-gradient(var(--canvas-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--canvas-grid) 1px, transparent 1px);
  background-size: 24px 24px;
}

/* floating panel toggles (mobile/tablet drawers) — hidden on wide screens */
.panel-toggle {
  display: none; position: absolute; top: 10px; z-index: 25;
  width: 36px; height: 36px; align-items: center; justify-content: center;
  border: 1px solid var(--line-2); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink-2); cursor: pointer; box-shadow: var(--e1);
}
.panel-toggle.left { left: 10px; }
.panel-toggle.right { right: 54px; }

.inv-row { display: flex; justify-content: space-between; font-size: var(--fs-sm); padding: 3px 0; border-bottom: 1px dashed var(--line); }
.inv-row .qty { font-weight: 700; font-variant-numeric: tabular-nums; }
.inv-row .sub { color: var(--ink-soft); }

.step-title { margin-top: 0; }
.unit-input { width: 60px; }

/* estimate tables: .tiny only sizes inputs inside .panel, so without these the
   free-lines table renders 8 columns of full-width inputs and overflows the card */
#est-free { width: 100%; }
#est-free input[data-f="label"] { width: 100%; min-width: 160px; }
#est-free input[type="number"], #est-runs input.tiny { width: 84px; text-align: right; }
#est-free td.num, #est-free th.num { text-align: right; white-space: nowrap; }

/* AI: floating copilot panel */
/* z-index sits UNDER side panels/drawers (70+ when floating) so the launcher
   never covers list rows; fullscreen editors also shift it left of the
   drawer rail */
#copilot-fab { position: fixed; right: 18px; bottom: 18px; z-index: 60; border-radius: 50%; width: 46px; height: 46px; font-size: 1.15rem; box-shadow: var(--e2, 0 4px 14px rgba(0,0,0,0.25)); }
body.fullscreen #copilot-fab { right: 58px; bottom: 12px; }
#copilot-panel { position: fixed; right: 18px; bottom: 74px; z-index: 900; width: min(420px, calc(100vw - 36px)); max-height: min(560px, calc(100vh - 110px)); display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm); box-shadow: var(--e2, 0 8px 28px rgba(0,0,0,0.3)); padding: var(--s2); }
#copilot-panel[hidden] { display: none; } /* the ID rule above beats the UA [hidden] rule */
.copilot-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px; }
.copilot-head-actions { display: flex; gap: 6px; }
.copilot-ui { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.copilot-foot { display: flex; gap: 6px; margin-top: 6px; }
/* pending image attachments (chips) between the log and the composer */
.copilot-attachments { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.copilot-attachments[hidden] { display: none; }
.copilot-chip { display: inline-flex; align-items: center; gap: 2px; border: 1px dashed var(--line); border-radius: 999px; padding: 1px 8px; font-size: var(--fs-xs); color: var(--muted, inherit); }
.copilot-chip-rm { border: 0; background: none; cursor: pointer; color: inherit; font-size: inherit; line-height: 1; padding: 0 2px; }
#copilot-panel .copilot-log { flex: 1 1 auto; min-height: 120px; }
/* A proposed-plan card can be tall; keep it (and the log above it) inside the
   fixed-height panel by letting both shrink and scroll instead of spilling out.
   Flex shrink is used rather than a % max-height because the plan box's parent
   has no definite height, so a percentage cap would resolve to none. */
#copilot-plan { overflow-y: auto; }
#copilot-plan:empty { display: none; }
#copilot-panel #copilot-plan { flex: 0 1 auto; min-height: 0; }
/* when a plan is showing, let the message log yield most of the room to it */
#copilot-panel .copilot-ui:has(#copilot-plan:not(:empty)) .copilot-log { min-height: 48px; }
.copilot-page-card .copilot-log { max-height: calc(100vh - 320px); min-height: 240px; }
.copilot-page-grid { display: grid; grid-template-columns: 260px 1fr; gap: var(--s3, 16px); align-items: start; }
@media (max-width: 900px) { .copilot-page-grid { grid-template-columns: 1fr; } }
.copilot-threads-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; gap: 8px; flex-wrap: wrap; }
/* keep the new-chat button on one line (FR "Nouvelle conversation" else wraps
   into a two-line, oversized button); it drops to its own row if space is tight */
.copilot-threads-head .btn { white-space: nowrap; }
.copilot-threads { list-style: none; margin: 0; padding: 0; max-height: calc(100vh - 320px); overflow: auto; }
.copilot-threads li { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; border-radius: var(--r-sm, 6px); cursor: pointer; border: 1px solid transparent; }
.copilot-threads li:hover { background: var(--surface-2, rgba(127,127,127,0.08)); }
.copilot-threads li.active { border-color: var(--accent); background: var(--accent-wash, rgba(0,90,200,0.06)); }
.copilot-threads .thread-title { font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.copilot-msg.tool { align-self: flex-start; background: none; border: 1px dashed var(--line); color: var(--muted, inherit); font-size: var(--fs-xs); padding: 2px 8px; }
.imp-bypass { display: inline-flex; align-items: center; }
.imp-bypass label { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; }
.copilot-plan-card { border: 1px dashed var(--accent); border-radius: var(--r-sm); padding: var(--s2); margin: 6px 0; background: var(--accent-wash, rgba(0, 90, 200, 0.06)); overflow-wrap: anywhere; }
.copilot-plan-card ol { margin: 6px 0; padding-left: 20px; }
.copilot-plan-card code { font-size: var(--fs-xs); word-break: break-all; }

/* AI: copilot chat + estimate findings */
.copilot-log { max-height: 260px; overflow: auto; display: flex; flex-direction: column; gap: 6px; padding: 4px 0; }
.copilot-log:empty { display: none; }
.copilot-msg { padding: 6px 10px; border-radius: 8px; max-width: 85%; white-space: pre-wrap; font-size: var(--fs-sm); }
.copilot-msg.user { align-self: flex-end; background: var(--accent-wash, rgba(0, 90, 200, 0.08)); }
.copilot-msg.assistant { align-self: flex-start; background: var(--surface-2, rgba(127, 127, 127, 0.08)); }
#copilot-input { flex: 1; min-width: 200px; }
#copilot-attach { flex: 0 0 auto; }
.ai-finding.ai-error { color: var(--crit); }
.ai-finding.ai-warn { color: var(--warn, #9a6b00); }
#manual-class { width: 220px; }
#manual-desc { width: 280px; }

.cable-spec { margin: 2px 0 6px; line-height: 1.35; }
.cable-spec b { font-weight: 600; color: var(--ink-2); }

.asm-editor { margin: 0 0 10px 24px; padding: var(--s2); border: 1px dashed var(--line-2); border-radius: var(--r-sm); background: var(--surface-2); }
.asm-table input { width: 100%; padding: 2px 4px; }
.asm-table .a-qty, .asm-table .a-cost, .asm-table .a-labor { max-width: 72px; }
.asm-table .a-unit { max-width: 56px; }

/* ------------------------------------------------------------ canvas chrome */
.canvas-zoom { position: absolute; top: 10px; right: 10px; display: flex; flex-direction: column; gap: 4px; z-index: 5; }
.canvas-zoom button {
  width: 34px; height: 34px; font-size: 16px; line-height: 1; border: 1px solid var(--line-2);
  border-radius: var(--r-sm); background: var(--surface); color: var(--ink-2); cursor: pointer; box-shadow: var(--e1);
}
.canvas-zoom button:hover { background: var(--surface-2); color: var(--ink); }

.ctx-menu {
  position: absolute; z-index: 40; min-width: 190px; background: var(--surface);
  border: 1px solid var(--line-2); border-radius: var(--r-sm); box-shadow: var(--e2); padding: 4px;
  /* the positioning code only ever MOVED this box: a menu taller than the
     canvas pinned to the top and its last row — always Delete — could not be
     reached at all. It scrolls now, whatever the branch turns out to be. */
  max-height: min(70vh, 520px); overflow-y: auto;
}
.ctx-menu button {
  display: block; width: 100%; text-align: left; padding: 6px 10px 6px 22px; border: none;
  background: none; font-size: var(--fs-sm); color: var(--ink); border-radius: var(--r-xs); cursor: pointer;
  position: relative; white-space: nowrap;
}
.ctx-menu button:hover, .ctx-menu button.sel { background: var(--accent-wash); color: var(--accent-ink); }
.ctx-menu button.danger { color: var(--crit); }
.ctx-menu button.danger:hover, .ctx-menu button.danger.sel { background: var(--crit-wash); color: var(--crit); }
.ctx-menu button[disabled] { color: var(--ink-3, var(--muted)); cursor: default; opacity: 0.55; }
.ctx-menu button[disabled]:hover { background: none; color: var(--ink-3, var(--muted)); }
.ctx-menu hr { border: none; border-top: 1px solid var(--line); margin: 4px 6px; }
/* the tick and the ▸ live in the padding gutters, so a row's label never
   shifts when its state changes */
.ctx-menu button.ctx-checked::before { content: "\2713"; position: absolute; left: 7px; }
.ctx-menu button.ctx-parent::after { content: "\25B8"; position: absolute; right: 8px; color: var(--muted); }
.ctx-menu.ctx-sub { z-index: 41; }
/* anchored one-field popup: it opens BESIDE the item it edits, never in the
   middle of the screen (six PTDialog.prompt calls used to) */
.ctx-popup { z-index: 42; width: 250px; padding: 8px; }
.ctx-popup-label { font-size: var(--fs-sm); font-weight: 600; margin-bottom: 4px; }
.ctx-popup-ro { margin-bottom: 4px; }
.ctx-popup-input { width: 100%; box-sizing: border-box; }
textarea.ctx-popup-input { min-height: 56px; resize: vertical; }
.ctx-popup-actions { display: flex; justify-content: flex-end; margin-top: 6px; }
.ctx-picker { z-index: 42; }

/* ---------------------------------------------------------- symbol palette */
.sym-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(34px, 1fr)); gap: 4px; margin: 6px 0; max-height: 176px; overflow-y: auto; }
.sym-btn { position: relative; padding: 3px; background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-xs); cursor: pointer; line-height: 0; }
.sym-btn:hover { border-color: var(--accent); background: var(--accent-wash); }
.sym-btn.active { border-color: var(--accent); background: var(--accent-wash); outline: 2px solid var(--accent); }
.sym-btn svg, .sym-btn canvas { background: #fff; border-radius: 3px; }
.panel .sym-btn { width: auto; margin: 0; }
.sym-grid-hint { grid-column: 1 / -1; }
.sym-add { display: flex; align-items: center; justify-content: center; font-size: 17px; color: var(--accent); text-decoration: none; line-height: 1; min-height: 30px; }
.fav-star { position: absolute; top: -3px; right: 0; font-size: 10px; line-height: 1; color: var(--line-2); cursor: pointer; z-index: 1; }
.fav-star.on { color: #e8a500; }
.sym-btn:hover .fav-star { color: #e8a500; opacity: 0.8; }
.fav-star.on:hover { color: var(--copper); }

/* --------------------------------------------------------- coverage editor */
.coverage-panel { border: 1px solid var(--line); border-radius: var(--r-sm); padding: var(--s2); margin: var(--s2) 0; background: var(--surface-2); }
.coverage-panel h4 { margin: 0 0 6px; }
.cov-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 8px; }
.cov-grid input, .cov-grid select { width: 100%; }

/* circuits panel (both editors) — one row per circuit: name, what it holds,
   and the two actions the endpoints support */
.circuit-list { max-height: 320px; overflow-y: auto; margin: 6px 0 2px; }
.circuit-row {
  display: flex; align-items: center; gap: 6px; padding: 4px 6px;
  border-radius: var(--r-xs); cursor: pointer; font-size: var(--fs-sm);
}
.circuit-row:hover { background: var(--surface-2); }
.circuit-row.selected { background: var(--accent-wash); font-weight: 600; }
/* an isolated circuit outranks every hover: the panel has to show which one,
   or "hovering highlights nothing" reads as a broken panel */
.circuit-row.isolated { box-shadow: inset 3px 0 0 var(--accent); }
.circuit-row.isolated .circuit-name::after {
  content: "◉"; margin-left: 4px; color: var(--accent);
}
.circuit-dot { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.circuit-name { font-weight: 600; }
.circuit-meta { margin-left: auto; white-space: nowrap; }
.circuit-acts { display: flex; gap: 2px; flex: none; visibility: hidden; }
.circuit-row:hover .circuit-acts { visibility: visible; }
.circuit-acts .btn { padding: 0 5px; line-height: 1.4; }

/* ----------------------------------------------------------- modal dialogs */
.pt-dialog-overlay {
  position: fixed; inset: 0; z-index: 210; background: rgba(16, 26, 36, 0.45);
  display: flex; align-items: center; justify-content: center; padding: 16px;
}
.pt-dialog {
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-md);
  box-shadow: var(--e2); padding: 18px; width: 100%; max-width: 420px;
}
.pt-dialog-msg { margin: 0 0 14px; color: var(--ink); white-space: pre-line; overflow-wrap: break-word; }
.pt-dialog-input { width: 100%; margin: 0 0 14px; }
.pt-dialog-actions { display: flex; justify-content: flex-end; gap: 8px; }

/* ------------------------------------------------------- hotkey help panel */
/* a modal, not a drawer: the estimator opens it WHILE triaging, and a drawer
   would evict the detections list they are triaging from */
.hk-overlay {
  position: fixed; inset: 0; z-index: 210; background: rgba(16, 26, 36, 0.45);
  display: flex; align-items: center; justify-content: center; padding: 16px;
}
.hk-card {
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-md);
  box-shadow: var(--e2); width: 100%; max-width: 720px; max-height: 86vh;
  display: flex; flex-direction: column; overflow: hidden;
}
.hk-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 18px; border-bottom: 1px solid var(--line);
}
.hk-head h3 { margin: 0; }
.hk-body { padding: 4px 18px 18px; overflow-y: auto; }
.hk-body section { margin-top: 14px; }
.hk-body h4 { margin: 0 0 4px; color: var(--ink-2); }
.hk-table { width: 100%; }
.hk-table td, .hk-table th { vertical-align: top; }
.hk-key {
  font-family: var(--mono); white-space: nowrap; color: var(--ink);
}

/* ----------------------------------------------------- legend panel (tool B) */
/* Deliberately NOT a backdropped modal: the tool exists to box a symbol on the
   live plan, so the sheet, the tool rail and the zoom buttons must stay
   clickable underneath. The wrapper passes the pointer straight through and
   the side padding keeps the card clear of both rails. */
.legend-panel {
  position: fixed; inset: 0; z-index: 205; display: flex;
  align-items: center; justify-content: center; padding: 16px 72px;
  pointer-events: none;
}
.legend-panel[hidden] { display: none; }
.legend-panel-card {
  pointer-events: auto;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-md);
  box-shadow: var(--e2); width: 100%; max-width: 860px; max-height: 82vh;
  display: flex; flex-direction: column; overflow: hidden;
}
.legend-panel-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; border-bottom: 1px solid var(--line);
}
.legend-panel-head h3 { margin: 0; }
.legend-panel-spacer { flex: 1; }
.legend-panel-body { padding: 10px 16px 16px; overflow-y: auto; }
.legend-panel-list { margin-top: 10px; }
/* one row per saved symbol, art big enough to recognise from across the desk */
.lg-row {
  display: grid; grid-template-columns: 132px minmax(0, 1fr) max-content;
  gap: var(--s2); align-items: center; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: var(--s2); margin: 6px 0;
}
/* legend symbols always preview on white — they live on paper */
.lg-art {
  width: 132px; height: 56px; display: flex; align-items: center; justify-content: center;
  background: #fff; border: 1px solid var(--line); border-radius: 4px; overflow: hidden;
}
.lg-art img, .lg-art canvas { max-width: 100%; max-height: 100%; }
.lg-name { font-weight: 600; overflow-wrap: anywhere; }
.lg-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
/* a scanned candidate is the saved row plus the fields that name it: same art
   column, so a reviewed list and a saved list read as one column of symbols */
.lg-cand .lg-fields {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 60px;
  gap: 6px; align-items: center;
}
.lg-cand .lg-fields input { width: 100%; }
.lg-cand .lg-label { grid-column: 1 / -1; overflow-wrap: anywhere; }
.lg-cand.saved { opacity: 0.55; }
/* the saved row's own fields, opened under it: full width so the class name
   and the description keep room to be read, not just typed into */
.lg-edit {
  grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 6px;
  align-items: center; padding-top: var(--s2); border-top: 1px dashed var(--line);
}
.lg-edit input[type="text"] { flex: 1 1 130px; min-width: 0; }
.lg-edit input.unit-input { flex: 0 0 64px; }
@media (max-width: 760px) {
  .legend-panel { padding: 12px; }
  .lg-row { grid-template-columns: 92px minmax(0, 1fr); }
  .lg-art { width: 92px; height: 44px; }
  .lg-actions { grid-column: 1 / -1; justify-content: flex-start; }
  .lg-cand .lg-fields { grid-template-columns: minmax(0, 1fr); }
}

/* Symbol-box correction bar. The panel is hidden while a box is dragged on the
   plan (it would sit on top of the very symbol being aimed at), so this strip
   is the only chrome left: what is being corrected, and the way out. */
.legend-fix-bar {
  position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%);
  z-index: 206; display: flex; align-items: center; gap: 10px;
  padding: 8px 14px; max-width: min(720px, calc(100vw - 32px)); flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--line-2);
  border-radius: var(--r-md); box-shadow: var(--e2);
}
.legend-fix-bar[hidden] { display: none; }

/* ------------------------------------------------------ searchable selects */
.ss-wrap { position: relative; min-width: 0; }
.toolbar > .ss-wrap { flex: 1 1 130px; }
.ss-wrap > select { display: none !important; }
.ss-input { width: 100%; }
.ss-list {
  position: absolute; left: 0; right: 0; top: 100%; z-index: 60; max-height: 240px;
  overflow-y: auto; background: var(--surface); border: 1px solid var(--line-2);
  border-radius: var(--r-sm); box-shadow: var(--e2); margin-top: 2px;
}
.ss-opt {
  display: block; width: 100%; text-align: left; padding: 6px 9px; border: none;
  background: none; font-size: var(--fs-sm); color: var(--ink); cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ss-opt:hover, .ss-opt.hover { background: var(--accent-wash); color: var(--accent-ink); }
.ss-opt.sel { font-weight: 600; }
.ss-none { padding: 6px 9px; color: var(--ink-soft); font-size: var(--fs-sm); }

/* ------------------------------------------------------- part search + dd */
.part-dd {
  position: absolute; left: 0; top: 100%; z-index: 40; min-width: 300px; max-height: 220px;
  overflow-y: auto; background: var(--surface); border: 1px solid var(--line-2);
  border-radius: var(--r-sm); box-shadow: var(--e2);
}
.part-dd button { display: block; width: 100%; text-align: left; padding: 5px 9px; border: none; background: none; font-size: var(--fs-sm); color: var(--ink); cursor: pointer; }
.part-dd button:hover, .part-dd button.sel { background: var(--accent-wash); }
.part-dd-none { padding: 6px 9px; color: var(--ink-soft); font-size: var(--fs-sm); }
.part-dd-create { border-top: 1px solid var(--line) !important; color: var(--accent) !important; font-weight: 600; }

/* --------------------------------------------------------- revision compare */
.diff-wrap { overflow: auto; max-height: 78vh; background: var(--sunken); }
.diff-wrap img { display: block; }
.diff-key { font-size: 1rem; margin: 0 4px 0 12px; }
.diff-key.diff-removed { color: var(--crit); }
.diff-key.diff-added { color: var(--good); }
.diff-key.diff-same { color: var(--ink-soft); }

/* --------------------------------------------------------- segmented control */
.seg-control { display: flex; margin: 6px 0 10px; border: 1px solid var(--line-2); border-radius: var(--r-sm); overflow: hidden; }
.seg-control label { flex: 1; margin: 0; }
.seg-control input { display: none; }
.seg-control span {
  display: block; text-align: center; padding: 7px 2px; font-size: var(--fs-sm); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; cursor: pointer; background: var(--surface);
  color: var(--ink-2); border-right: 1px solid var(--line);
}
.seg-control label:last-child span { border-right: none; }
.seg-control input:checked + span { background: var(--btn-primary-bg); color: var(--btn-primary-fg); font-weight: 600; }
.row-actions { display: inline-flex; gap: 6px; }

/* ------------------------------------------------------------ parts catalog */
#parts-scroll { max-height: calc(100vh - 330px); min-height: 160px; overflow: auto; }
#parts-table { table-layout: fixed; min-width: 800px; border-collapse: separate; border-spacing: 0; }
#parts-table col.col-num { width: 130px; }
#parts-table col.col-unit { width: 60px; }
#parts-table col.col-cost { width: 90px; }
#parts-table col.col-labor { width: 84px; }
#parts-table col.col-scope { width: 100px; }
#parts-table col.col-vis { width: 58px; }
#parts-table col.col-act { width: 150px; }
#parts-table th, #parts-table td { border: none; border-bottom: 1px solid var(--line); }
#parts-table th { position: sticky; top: 0; background: var(--surface-2); z-index: 2; }
#parts-table th.num { text-align: right; }
#parts-table td { overflow: hidden; white-space: nowrap; }
#parts-table input { width: 100%; padding: 3px 6px; font-size: var(--fs-sm); border: 1px solid transparent; background: transparent; border-radius: 4px; }
#parts-table input:hover { border-color: var(--line-2); }
#parts-table input:focus { border-color: var(--accent); background: var(--surface); outline: none; box-shadow: none; }
#parts-table input.p-name { text-overflow: ellipsis; }
#parts-table input.p-cost, #parts-table input.p-labor { text-align: right; }
#parts-table td.num { text-align: right; }
#parts-table td.vis-cell { text-align: center; }
#parts-table tr.part-hidden td { opacity: 0.55; }
#parts-table .ro-text { display: inline-block; max-width: 100%; padding: 3px 6px; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; }
#parts-table .name-two { display: flex; flex-direction: column; gap: 1px; }
#parts-table .name-two label { display: flex; align-items: center; gap: 5px; margin: 0; font-size: 0.62rem; color: var(--ink-soft); white-space: nowrap; }
#parts-table .name-two input { flex: 1; min-width: 0; }
.toolbar .check { display: flex; align-items: center; gap: 6px; margin: 0; font-size: var(--fs-sm); }
#parts-scroll.loading tbody { opacity: 0.5; pointer-events: none; }
/* Actions pinned right, range text pinned left: stays stable when the range
   span is empty (0 results / pre-load), unlike space-between which recenters. */
.pager { display: flex; align-items: center; justify-content: flex-end; gap: var(--s3); margin-top: var(--s2); }
.pager > :first-child { margin-right: auto; }
/* Same stability for the toolbar status: parts-specific so other toolbars keep
   their inline status placement. */
#parts-status { margin-left: auto; }

/* --------------------------------------------------------- forms & wizard */
.form-row { display: flex; gap: var(--s3); flex-wrap: wrap; margin: var(--s2) 0; }
.form-row label { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-sm); min-width: 220px; flex: 1; }
.form-row input { padding: 7px 9px; }

/* ---------------------------------------------------------------- auth */
.auth-error { border-color: var(--crit); color: var(--crit); background: var(--crit-wash); }

/* Microsoft sign-in button */
.ms-btn { background: var(--surface); color: var(--ink); border: 1px solid var(--line-2); display: inline-flex; align-items: center; gap: 8px; }
.ms-btn:hover { background: var(--surface-2); }
.ms-logo {
  width: 16px; height: 16px; display: inline-block; flex: none;
  background: linear-gradient(90deg, #f25022 0 50%, #7fba00 50% 100%) top/100% 50% no-repeat,
    linear-gradient(90deg, #00a4ef 0 50%, #ffb900 50% 100%) bottom/100% 50% no-repeat;
}

/* ---------------------------------------------- split-screen auth (login) */
.auth-main { max-width: none; margin: 0; padding: 0; }
.auth-split {
  display: grid; grid-template-columns: 1.05fr 0.95fr;
  min-height: calc(100vh - 53px);
}
/* left: branded blueprint panel (dark in both themes by design) */
.auth-brand {
  position: relative; overflow: hidden; color: #eaf2fb;
  display: flex; align-items: center;
  padding: clamp(32px, 5vw, 72px);
  background: linear-gradient(140deg, #0c2740 0%, #123a5e 48%, #1d5183 100%);
}
.auth-brand::before { /* blueprint grid, faded from the top-left */
  content: ""; position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
  background-size: 30px 30px;
  -webkit-mask-image: radial-gradient(130% 100% at 15% 12%, #000 35%, transparent 82%);
          mask-image: radial-gradient(130% 100% at 15% 12%, #000 35%, transparent 82%);
}
.auth-brand::after { /* warm copper glow, bottom-right */
  content: ""; position: absolute; right: -120px; bottom: -150px;
  width: 440px; height: 440px; border-radius: 50%;
  background: radial-gradient(circle, rgba(185, 108, 44, 0.30), transparent 68%);
  pointer-events: none;
}
.auth-brand-inner { position: relative; max-width: 440px; display: flex; flex-direction: column; gap: 26px; }
.auth-brand-mark { display: inline-flex; align-items: center; gap: 10px; font-weight: 700; font-size: 1.05rem; letter-spacing: -0.01em; color: #eaf2fb; }
.auth-brand-badge { width: 32px; height: 32px; border-radius: 9px; background: linear-gradient(135deg, #4a8dcf, #1f548c); display: inline-flex; align-items: center; justify-content: center; flex: none; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); }
.auth-brand-badge .icon { width: 19px; height: 19px; color: #fff; }
.auth-brand h2 { font-size: clamp(1.75rem, 2.6vw, 2.4rem); line-height: 1.14; font-weight: 700; letter-spacing: -0.022em; margin: 0; color: #fff; }
.auth-brand-lead { font-size: 1.02rem; line-height: 1.55; color: #b7cfe6; margin: 0; }
.auth-trust { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.auth-trust li { display: flex; align-items: center; gap: 12px; font-size: 0.95rem; color: #dceaf6; }
.auth-trust .tk { width: 28px; height: 28px; border-radius: 8px; background: rgba(122, 205, 161, 0.16); display: inline-flex; align-items: center; justify-content: center; flex: none; }
.auth-trust .tk .icon { width: 17px; height: 17px; color: #7fd6a6; }
/* right: form panel */
.auth-panel { display: flex; align-items: center; justify-content: center; padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 40px); background: var(--ground); }
.auth-card { width: 100%; max-width: 372px; display: flex; flex-direction: column; gap: var(--s4); }
.auth-head h1 { font-size: 1.6rem; margin: 0 0 5px; letter-spacing: -0.02em; }
.auth-head p { margin: 0; color: var(--ink-soft); font-size: var(--fs-base); }
.auth-alert { padding: 10px 13px; border-radius: var(--r-sm); font-size: var(--fs-sm); border: 1px solid; }
.auth-alert.crit { border-color: var(--crit); color: var(--crit); background: var(--crit-wash); }
.auth-alert.good { border-color: var(--good); color: var(--good); background: var(--good-wash); }
.auth-form { display: flex; flex-direction: column; gap: var(--s3); }
.auth-form .field { display: flex; flex-direction: column; gap: 5px; font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2); }
.auth-form .field-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.auth-form .field-link { font-weight: 500; font-size: var(--fs-xs); color: var(--accent-ink); }
.auth-form input:not([type="checkbox"]):not([type="radio"]), .auth-form select {
  padding: 11px 13px; border: 1px solid var(--line-2); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink); font-size: var(--fs-base);
  transition: border-color 0.12s, box-shadow 0.12s; width: 100%;
}
.auth-form input::placeholder { color: var(--ink-soft); }
.auth-form input:not([type="checkbox"]):focus, .auth-form select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-wash); }
.auth-form .field-hint { font-weight: 400; font-size: var(--fs-xs); color: var(--ink-soft); }
.auth-form .auth-note { margin: 0; font-size: var(--fs-sm); color: var(--ink-soft); }
.auth-form .check { display: flex; align-items: flex-start; gap: 9px; margin: 0; font-weight: 400; font-size: var(--fs-sm); color: var(--ink-2); cursor: pointer; }
.auth-form .check input[type="checkbox"] { margin-top: 2px; flex: none; width: 16px; height: 16px; accent-color: var(--accent); }
.auth-form .auth-status { font-size: var(--fs-sm); color: var(--crit); }
.auth-form .auth-status:empty { display: none; }
/* one-time code entry: big, monospaced, evenly spaced digits (text-indent
   balances the trailing letter-space so digits stay optically centered) */
.auth-form input.otp-input {
  font-family: var(--mono); font-size: 1.6rem; font-weight: 600;
  text-align: center; letter-spacing: 0.42em; text-indent: 0.42em;
}
.auth-form input.otp-input::placeholder { color: var(--line-2); }
.btn-lg { padding: 11px 16px; font-size: var(--fs-base); border-radius: var(--r-sm); width: 100%; }
.auth-or { display: flex; align-items: center; gap: 12px; color: var(--ink-soft); font-size: var(--fs-sm); }
.auth-or::before, .auth-or::after { content: ""; height: 1px; flex: 1; background: var(--line); }
.auth-foot { text-align: center; margin: 0; font-size: var(--fs-sm); color: var(--ink-soft); }
.auth-resend { margin-top: 2px; }
.auth-card .g-recaptcha { min-height: 76px; }
@media (max-width: 820px) {
  .auth-brand { display: none; }
  .auth-split { grid-template-columns: 1fr; }
}

/* -------------------------------------------------- org admin dashboard */
.admin-head h1 { margin-bottom: 2px; }
.admin-head p { margin: 0 0 var(--s4); font-size: var(--fs-sm); color: var(--ink-soft); }
.admin-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--s3); margin: 0 0 var(--s4); }
.stat-tile {
  display: flex; flex-direction: column; gap: 3px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 13px 15px; box-shadow: var(--e1);
  color: inherit; text-decoration: none;
  transition: border-color 0.12s, box-shadow 0.12s;
}
.stat-tile:hover { border-color: var(--accent); box-shadow: var(--e2); }
.stat-tile .k {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-xs); font-weight: 650; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--ink-soft);
}
.stat-tile .k .icon { width: 14px; height: 14px; color: var(--accent); }
.stat-tile .v { font-size: 1.45rem; font-weight: 700; letter-spacing: -0.02em; color: var(--ink); }
.stat-tile .v .unit { font-size: var(--fs-base); font-weight: 600; color: var(--ink-soft); margin-left: 2px; }
.stat-tile .h { font-size: var(--fs-xs); color: var(--ink-soft); }
/* thin usage meter (storage, AI quotas) */
.meter { display: block; height: 6px; border-radius: 4px; background: var(--sunken); overflow: hidden; }
.meter > i { display: block; height: 100%; border-radius: 4px; background: var(--accent); }
.meter > i.warn { background: var(--warn); }
.meter > i.crit { background: var(--crit); }
.stat-tile .meter { margin-top: 5px; }

.admin-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--s3); }
.admin-card {
  display: flex; flex-direction: column; gap: 10px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: var(--s4); box-shadow: var(--e1);
}
.admin-card.wide { grid-column: 1 / -1; }
.admin-card-head { display: flex; align-items: center; gap: 10px; }
.admin-card-head .badge-ic {
  width: 30px; height: 30px; border-radius: 8px; flex: none;
  background: var(--accent-wash); color: var(--accent-ink);
  display: inline-flex; align-items: center; justify-content: center;
}
.admin-card-head .badge-ic .icon { width: 17px; height: 17px; }
.admin-card-head h3 { margin: 0; font-size: var(--fs-h3); }
.admin-card-head .pill {
  margin-left: auto; padding: 2px 9px; border-radius: 999px;
  font-size: var(--fs-xs); font-weight: 650;
  background: var(--accent-wash); color: var(--accent-ink);
}
.admin-card .desc { margin: 0; font-size: var(--fs-sm); color: var(--ink-soft); }
.admin-card .actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: auto; }
.admin-card .check {
  display: flex; align-items: flex-start; gap: 9px;
  font-size: var(--fs-sm); color: var(--ink-2); cursor: pointer;
}
.admin-card .check input[type="checkbox"] { margin-top: 2px; flex: none; width: 16px; height: 16px; accent-color: var(--accent); }
.admin-card .note { margin: 0; font-size: var(--fs-xs); color: var(--ink-soft); }
.admin-card .note.warn { color: var(--warn); }
.meter-row { display: grid; grid-template-columns: 4.5em 1fr 3.2em; align-items: center; gap: 10px; font-size: var(--fs-sm); color: var(--ink-2); }
.meter-row .pct { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink-soft); }
.admin-form { display: flex; gap: var(--s3); flex-wrap: wrap; margin: 0; }
.admin-form label { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2); min-width: 220px; flex: 1; }
.admin-form input[type="text"] { padding: 8px 10px; }

/* AI consent modal (org admin dashboard) */
#ai-consent-overlay { position: fixed; inset: 0; background: rgba(15, 25, 35, 0.55); display: flex; align-items: center; justify-content: center; z-index: 1000; }
#ai-consent-overlay[hidden] { display: none; }
.ai-consent-modal { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--e2); max-width: 560px; margin: 16px; padding: var(--s5); }
.ai-consent-modal h3 { margin-top: 0; }
.ai-consent-extra { font-weight: 650; color: var(--warn); }

/* page heading with an action on the right (projects list, archived) */
.head-row { display: flex; align-items: center; gap: var(--s3); margin: var(--s5) 0 var(--s3); }
.head-row > h1, .head-row > h2 { margin: 0; }
.head-row > :first-child { margin-right: auto; }

/* ------------------------------------------------------------ error pages */
.err-main {
  max-width: none; margin: 0;
  display: flex; align-items: center; justify-content: center;
  min-height: calc(100vh - 53px); padding: clamp(28px, 6vw, 64px) 20px;
}
.err-sheet {
  position: relative; overflow: hidden; width: 100%; max-width: 520px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--e2); text-align: center;
  padding: clamp(36px, 6vw, 56px) clamp(24px, 5vw, 48px);
}
.err-sheet::before { /* faint blueprint grid, same motif as the plan canvas */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(var(--canvas-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--canvas-grid) 1px, transparent 1px);
  background-size: 26px 26px;
  -webkit-mask-image: radial-gradient(120% 90% at 50% 0%, #000 30%, transparent 80%);
          mask-image: radial-gradient(120% 90% at 50% 0%, #000 30%, transparent 80%);
}
.err-sheet > * { position: relative; }
.err-code {
  display: inline-flex; align-items: center; gap: 16px;
  font-family: var(--mono); font-weight: 700; line-height: 1;
  font-size: clamp(56px, 11vw, 84px); letter-spacing: 0.05em;
  color: var(--accent); margin-bottom: var(--s4);
}
.err-code::before, .err-code::after { /* drafting ticks, copper */
  content: ""; width: 32px; height: 2px; background: var(--copper); opacity: 0.7;
}
.err-sheet h1 { font-size: 1.45rem; letter-spacing: -0.02em; margin: 0 0 8px; }
.err-sheet p { margin: 0 auto; max-width: 46ch; color: var(--ink-soft); font-size: var(--fs-base); line-height: 1.55; }
.err-actions { display: flex; justify-content: center; gap: 10px; flex-wrap: wrap; margin-top: var(--s5); }
.err-actions .btn { width: auto; }

/* -------------------------------------------------- loading & empty states */
.skeleton { display: flex; flex-direction: column; gap: 8px; padding: 4px 0; }
.skel-line { height: 13px; border-radius: 5px; background: linear-gradient(100deg, var(--sunken) 40%, var(--surface-2) 50%, var(--sunken) 60%); background-size: 200% 100%; animation: skel-shimmer 1.4s ease-in-out infinite; }
.skel-line.w60 { width: 60%; }
.skel-line.w80 { width: 80%; }
@keyframes skel-shimmer { from { background-position: 120% 0; } to { background-position: -80% 0; } }

.empty-state { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: var(--s6) var(--s4); text-align: center; color: var(--ink-soft); }
.empty-state .icon { width: 34px; height: 34px; color: var(--line-2); }
.empty-state b { color: var(--ink-2); font-size: var(--fs-base); font-weight: 650; }
.empty-state p { margin: 0; font-size: var(--fs-sm); max-width: 46ch; }
.empty-state .btn { margin-top: var(--s2); }
.empty-inline { color: var(--ink-soft); font-size: var(--fs-sm); padding: var(--s2) 0; }

/* upload drop zone */
.dropzone {
  display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%;
  padding: var(--s6) var(--s4); border: 2px dashed var(--line-2); border-radius: var(--r-md);
  background: var(--surface-2); color: var(--ink-soft); cursor: pointer; text-align: center;
}
.dropzone:hover, .dropzone.drag { border-color: var(--accent); background: var(--accent-wash); color: var(--accent-ink); }
.dropzone .icon { width: 30px; height: 30px; }
.dropzone b { color: var(--ink-2); font-size: var(--fs-base); }
.dropzone.drag b { color: var(--accent-ink); }

/* ------------------------------------------------------------- responsive */
/* Short viewport (a 1080p laptop with the browser chrome on): the 15-button
   tool rail wraps into two columns rather than scrolling or clipping. The
   column list mirrors the desktop grid above, with the rail track doubled. */
@media (max-height: 820px) and (min-width: 1021px) {
  .review-layout.rail-ui { grid-template-columns: 88px auto minmax(0, 1fr) auto 46px; }
  .tool-rail { flex-flow: column wrap; align-content: flex-start; }
  /* margin-top:auto in a wrapping column would push the help button into a
     column of its own */
  .tool-rail .rail-help { margin-top: 0; }
  .tool-rail .rail-sep { width: 38px; }
}
@media (max-width: 1020px) {
  .review-layout { grid-template-columns: 1fr; }
  .panel-toggle { display: inline-flex; }
  .review-layout .panel {
    /* full-height overlay: independent of nav height and the impersonation
       banner; Esc or the toggle closes it */
    position: fixed; top: 0; bottom: 0; width: min(320px, 86vw); z-index: 70;
    box-shadow: var(--e2); transition: transform 0.2s ease; overflow-y: auto;
  }
  .review-layout .panel.left { left: 0; transform: translateX(-105%); border-right: 1px solid var(--line); }
  .review-layout .panel.right { right: 0; transform: translateX(105%); border-left: 1px solid var(--line); }
  .review-layout .panel.open { transform: translateX(0); }

  /* rail UI keeps both rails; toolbox and drawer float over the canvas.
     Re-map the explicit desktop column assignments to the 3-track grid
     (fixed-position toolbox/drawer are out of flow, their column is moot) */
  .review-layout.rail-ui { grid-template-columns: 46px minmax(0, 1fr) 46px; }
  .review-layout.rail-ui > .canvas-wrap { grid-column: 2; }
  .review-layout.rail-ui > .drawer-rail { grid-column: 3; }
  .review-layout.rail-ui .toolbox {
    position: fixed; top: 0; bottom: 0; left: 46px; width: min(300px, 78vw);
    z-index: 70; box-shadow: var(--e2); border-right: 1px solid var(--line);
  }
  .review-layout.rail-ui .drawer {
    position: fixed; top: 0; bottom: 0; right: 46px; width: min(320px, 82vw);
    z-index: 70; box-shadow: var(--e2); border-left: 1px solid var(--line);
  }
}
@media (max-width: 720px) {
  .container { padding: var(--s4) var(--s3) var(--s6); }
  .topnav { gap: var(--s2); }
  .mainmenu { order: 10; width: 100%; overflow-x: auto; }
  .proj-chip { max-width: 130px; }
  .table-scroll { max-height: none; }
  h1 { font-size: 1.3rem; }
}

/* ------------------------------------------------ floating drawer window */
/* one scroll context per drawer: the drawer body scrolls, the inner table
   is capped so it never nests a second full-height scrollbar */
.review-layout.rail-ui .drawer .table-scroll { max-height: 38vh; }
.drawer-expand {
  border: none; background: transparent; color: var(--ink-soft); cursor: pointer;
  width: 24px; height: 24px; border-radius: var(--r-xs); display: inline-flex;
  align-items: center; justify-content: center; float: right;
}
.drawer-expand:hover { background: var(--surface-2); color: var(--ink); }
.drawer-expand .icon { width: 15px; height: 15px; }
/* a drawer popped out over the canvas (PTToolbox.openWindow) — placed after
   the responsive blocks so it also overrides the narrow-width fixed drawer */
.review-layout .drawer.drawer-window {
  position: fixed; left: 50%; top: 50%; right: auto; bottom: auto;
  transform: translate(-50%, -50%);
  width: min(900px, 80vw); height: min(80vh, 780px); z-index: 80;
  border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--e2);
  /* single scrollbar: the window is a fixed-height flex column where ONLY the
     table region scrolls; everything else keeps its natural height (the huge
     docked bottom padding is dropped so it doesn't eat the table's room) */
  display: flex; flex-direction: column; overflow-y: hidden;
  padding-bottom: var(--s3);
}
.review-layout .drawer.drawer-window > * { flex: 0 0 auto; }
.review-layout .drawer.drawer-window .table-scroll {
  flex: 1 1 auto; min-height: 0; max-height: none; overflow-y: auto;
}
.drawer-window-bar { display: flex; justify-content: flex-end; margin: -4px -4px 2px 0; }
.drawer-window-close {
  border: none; background: transparent; color: var(--ink-soft); cursor: pointer;
  width: 26px; height: 26px; border-radius: var(--r-xs); display: inline-flex;
  align-items: center; justify-content: center; font-size: 14px;
}
.drawer-window-close:hover { background: var(--surface-2); color: var(--ink); }

/* ------------------------------------------------------------- bug report */
.bug-modal {
  position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center;
  justify-content: center; background: rgba(10, 16, 24, 0.55); padding: var(--s4);
}
.bug-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
  box-shadow: var(--e2, 0 8px 28px rgba(0, 0, 0, 0.3)); width: min(520px, 100%);
  max-height: 90vh; overflow-y: auto; padding: var(--s4);
  display: flex; flex-direction: column; gap: var(--s3);
}
.bug-card h3 { margin: 0; }
.bug-card label { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-sm); }
.bug-card input[type="text"], .bug-card textarea, .bug-card select { padding: 7px 9px; }
.bug-card textarea { min-height: 110px; resize: vertical; }
.bug-card .bug-check { flex-direction: row; align-items: center; gap: 8px; }
.bug-card .bug-note { margin: 0; }
.bug-card .toolbar { margin: 0; }
.bug-error { color: var(--crit); background: var(--crit-wash); border: 1px solid var(--crit); border-radius: var(--r-xs); padding: 6px 10px; font-size: var(--fs-sm); }

/* severity / status badges (bug reports) */
.badge.sev-low { background: var(--sunken); color: var(--ink-soft); }
.badge.sev-medium { background: var(--accent-wash); color: var(--accent-ink); }
.badge.sev-high { background: var(--warn-wash); color: var(--warn); }
.badge.sev-critical { background: var(--crit-wash); color: var(--crit); }
.badge.bug-st-new { background: var(--accent-wash); color: var(--accent-ink); }
.badge.bug-st-triaged { background: var(--warn-wash); color: var(--warn); }
.badge.bug-st-in_progress { background: var(--warn-wash); color: var(--warn); }
.badge.bug-st-resolved { background: var(--good-wash); color: var(--good); }
.badge.bug-st-closed { background: var(--sunken); color: var(--ink-soft); }

/* super-admin bug detail: scrollable diagnostic blocks */
.bug-json-wrap { max-height: 320px; overflow: auto; }
.bug-json {
  margin: 0; max-height: 320px; overflow: auto; background: var(--sunken);
  border: 1px solid var(--line); border-radius: var(--r-xs); padding: var(--s2);
  font-size: var(--fs-xs); white-space: pre-wrap; word-break: break-word;
}
.bug-screenshot { max-width: 100%; border: 1px solid var(--line); border-radius: var(--r-xs); }

/* unknown-symbol + attribute suggestions (review right panel) */
#sugg-box, #attr-box { margin-top: 10px; border-top: 1px solid var(--line-2); padding-top: 8px; }
#sugg-box h4, #attr-box h4 { margin: 0 0 6px; font-size: 12.5px; }
.sugg-row { display: flex; align-items: center; gap: 5px; margin-bottom: 6px; flex-wrap: wrap; }
.sugg-row .sugg-label { flex: 1; font-size: 11.5px; min-width: 0; }
/* like .lg-art: symbols always preview on white — they live on paper */
.sugg-thumb { height: 40px; max-width: 88px; object-fit: contain; padding: 2px;
  background: #fff; border: 1px solid var(--line); border-radius: 4px; cursor: pointer; }
.sugg-actions { display: flex; gap: 5px; width: 100%; align-items: center; }
.sugg-actions .sugg-attach { flex: 1; min-width: 0; }
#attr-manual-add[hidden] { display: none; } /* .toolbar's flex beats UA [hidden] */
/* a suggestion label centres the plan, so it is a control — styled flat, but
   it is a real <button> and reachable from the keyboard */
button.sugg-label { background: none; border: 0; padding: 0; font: inherit; text-align: left; cursor: pointer; color: inherit; }
button.sugg-label:hover { text-decoration: underline; }

/* attributes pane: three collapsible bands (confirmed / suggested / refused) */
.attr-sec { margin-top: 8px; border-top: 1px solid var(--line); padding-top: 6px; }
.attr-sec[hidden] { display: none; }
.attr-sec > summary { cursor: pointer; font-size: 12.5px; font-weight: 600; list-style: none; }
.attr-sec > summary::-webkit-details-marker { display: none; }
.attr-sec > summary::before {
  content: "\25B8"; display: inline-block; width: 11px; color: var(--ink-soft);
  transition: transform 0.12s;
}
.attr-sec[open] > summary::before { transform: rotate(90deg); }

/* one group = one line until it is opened; the editor and the per-symbol
   chips are built on expand, never rendered-then-hidden */
.attr-grp-head {
  display: flex; align-items: baseline; gap: 4px; width: 100%;
  background: none; border: 0; padding: 2px 0; cursor: pointer;
  font: inherit; font-size: 11.5px; text-align: left; color: inherit;
}
.attr-grp-head:hover .attr-grp-name { text-decoration: underline; }
.attr-grp-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attr-grp-chev { display: inline-block; width: 9px; color: var(--ink-soft); transition: transform 0.12s; }
.attr-grp-head[aria-expanded="true"] .attr-grp-chev { transform: rotate(90deg); }
.attr-grp-body { padding-left: 11px; }
.attr-grp-body[hidden] { display: none; }
.attr-conf-dets { margin: -2px 0 6px; display: flex; flex-wrap: wrap; gap: 3px; }

/* confirmed detection attributes: table/tooltip chip + inventory sub-rows */
.attr-chip { display: inline-block; padding: 0 4px; border: 1px solid var(--line-2); border-radius: 8px; font-size: 10px; color: var(--ink-soft); white-space: nowrap; }
.inv-attr-row { padding: 1px 0 3px 12px; border-bottom: 1px dashed var(--line); }

/* global top-of-page notifications (toast.js) */
#pt-toasts {
  position: fixed; top: 12px; left: 50%; transform: translateX(-50%);
  z-index: 4000; display: flex; flex-direction: column; gap: 8px;
  width: min(560px, calc(100vw - 32px)); pointer-events: none;
}
.pt-toast {
  display: flex; align-items: flex-start; gap: 10px; pointer-events: auto;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-2); border-left: 4px solid var(--ink-soft);
  border-radius: var(--r-sm); padding: 10px 12px; font-size: var(--fs-sm);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
}
.pt-toast span { flex: 1; min-width: 0; overflow-wrap: break-word; }
.pt-toast.error { border-left-color: #c23b3b; }
.pt-toast.success { border-left-color: #2e9e5b; }
.pt-toast.info { border-left-color: #3b7dc2; }
.pt-toast-close {
  border: 0; background: none; color: var(--ink-soft); font-size: 16px;
  line-height: 1; cursor: pointer; padding: 0 2px;
}

/* ---- browser-compute progress (all-pages detect) ---- */
.detect-progress { margin-top: 6px; }
.detect-progress-track {
  height: 6px;
  border-radius: 3px;
  background: var(--accent-wash);
  overflow: hidden;
}
.detect-progress-fill {
  height: 100%;
  width: 0;
  border-radius: 3px;
  background: var(--accent);
  transition: width 0.3s ease;
}
/* indeterminate phases (preparing / finalizing): a sliding pulse */
.detect-progress.indeterminate .detect-progress-fill {
  width: 30%;
  animation: detect-progress-slide 1.2s ease-in-out infinite;
}
@keyframes detect-progress-slide {
  0% { margin-left: 0; }
  50% { margin-left: 70%; }
  100% { margin-left: 0; }
}

/* ---- detection progress modal: the plan explodes into its CAD layers and a
   reticle finds the symbols — a picture of the actual pipeline. ---- */
.detect-modal { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center; }
.detect-modal[hidden] { display: none; }
.detect-modal-backdrop { position: absolute; inset: 0; background: rgba(15, 27, 42, 0.45); backdrop-filter: blur(2px); }
.detect-modal-card {
  position: relative;
  width: min(440px, calc(100vw - 32px));
  background: var(--surface, #fff);
  border: 1px solid var(--border, #d8dee6);
  border-radius: 12px;
  box-shadow: 0 24px 60px rgba(10, 20, 35, 0.35);
  overflow: hidden;
}
.detect-modal-body { padding: 4px 22px 20px; text-align: center; }
/* every text slot has a FIXED height so changing copy never reflows the card */
.detect-modal-stage {
  font-weight: 650; font-size: 1.02rem; margin-bottom: 2px;
  height: 1.55em; line-height: 1.55em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.detect-modal-detail {
  font-size: 0.82rem; line-height: 1.35;
  height: 4.05em; /* three lines, always reserved */
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  transition: opacity 0.25s;
}
.detect-modal-detail.swap { opacity: 0; }
.detect-modal-meter { display: flex; align-items: center; gap: 10px; margin: 8px 0 0; }
.detect-modal-pct {
  font-size: 1.5rem; font-weight: 700; width: 4.2ch; flex: none;
  font-variant-numeric: tabular-nums; text-align: right; color: var(--accent);
}
.detect-modal-track { flex: 1; height: 10px; border-radius: 5px; background: var(--accent-wash); overflow: hidden; }
.detect-modal-fill {
  height: 100%; width: 0; border-radius: 5px;
  background: linear-gradient(90deg, var(--accent) 0%, var(--accent-ink) 100%);
  transition: width 0.35s ease;
  background-size: 200% 100%;
}
.detect-modal.working .detect-modal-fill { animation: detect-fill-sheen 1.6s linear infinite; }
@keyframes detect-fill-sheen { from { background-position: 0 0; } to { background-position: -200% 0; } }
.detect-modal-count {
  font-size: 0.82rem; font-variant-numeric: tabular-nums;
  height: 1.5em; line-height: 1.5em; margin: 4px 0 10px;
  white-space: nowrap; overflow: hidden;
}

/* --- the scene: a plan sheet tilts back in 3D and its CAD layers lift
   apart in depth while a reticle finds the symbols --- */
.detect-scene {
  height: 176px;
  background: var(--accent-wash);
  display: flex; align-items: center; justify-content: center;
  perspective: 800px; perspective-origin: 50% 20%;
  overflow: hidden;
}
.scene-stack {
  position: relative; width: 190px; height: 120px;
  transform-style: preserve-3d;
  animation: stack-open 5.6s ease-in-out infinite;
}
@keyframes stack-open {
  0%, 8%   { transform: rotateX(0deg) rotateZ(0deg) translateY(0); }
  26%, 82% { transform: rotateX(54deg) rotateZ(-10deg) translateY(14px); }
  96%, 100% { transform: rotateX(0deg) rotateZ(0deg) translateY(0); }
}
.sheet3d {
  position: absolute; inset: 0;
  border-radius: 6px;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #c9d4e0);
  box-shadow: 0 10px 24px rgba(15, 30, 50, 0.16);
  transform-style: preserve-3d;
  animation-duration: 5.6s; animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}
.sheet3d svg { width: 100%; height: 100%; display: block; }
.sheet-walls  { animation-name: sheet-sink; }
.sheet-symbols { animation-name: sheet-hold; }
.sheet-text   { animation-name: sheet-lift; }
@keyframes sheet-sink {
  0%, 8% { transform: translateZ(-1px); }
  26%, 82% { transform: translateZ(-34px); }
  96%, 100% { transform: translateZ(-1px); }
}
@keyframes sheet-hold {
  0%, 8% { transform: translateZ(0); }
  26%, 82% { transform: translateZ(2px); }
  96%, 100% { transform: translateZ(0); }
}
@keyframes sheet-lift {
  0%, 8% { transform: translateZ(1px); opacity: 1; }
  26%, 82% { transform: translateZ(40px); opacity: 0.45; }
  96%, 100% { transform: translateZ(1px); opacity: 1; }
}
.detect-scene .stroke-w { stroke: var(--accent-ink); stroke-width: 2; fill: none; opacity: 0.55; stroke-linecap: round; }
.detect-scene .stroke-w.arc { stroke-width: 1.4; }
.detect-scene .stroke-t { stroke: var(--muted, #7c8794); stroke-width: 2.4; fill: none; opacity: 0.65; stroke-linecap: round; }
.detect-scene .sym { fill: none; stroke: var(--accent); stroke-width: 2; }
.detect-scene .sym-glyph { stroke: var(--accent); stroke-width: 1.4; fill: none; }
/* the reticle hops symbol to symbol while the stack is open */
.detect-scene .reticle { fill: none; stroke: var(--accent); stroke-width: 1.8; }
.detect-scene .reticle rect { stroke-dasharray: 5 4; }
.detect-scene .reticle { animation: reticle-hop 5.6s ease-in-out infinite; }
@keyframes reticle-hop {
  0%, 22% { transform: translate(52px, 48px) scale(1.7); opacity: 0; }
  30%, 42% { transform: translate(52px, 48px) scale(1); opacity: 1; }
  50%, 62% { transform: translate(120px, 44px) scale(1); opacity: 1; }
  70%, 80% { transform: translate(146px, 82px) scale(1); opacity: 1; }
  88%, 100% { transform: translate(146px, 82px) scale(1.7); opacity: 0; }
}
.detect-scene .ping { fill: var(--accent); animation: sym-ping 5.6s ease-out infinite; }
@keyframes sym-ping {
  0%, 28% { transform: translate(52px, 48px) scale(0.4); opacity: 0; }
  36% { transform: translate(52px, 48px) scale(1.6); opacity: 0.35; }
  44% { transform: translate(52px, 48px) scale(2.4); opacity: 0; }
  56% { transform: translate(120px, 44px) scale(1.6); opacity: 0.35; }
  64% { transform: translate(120px, 44px) scale(2.4); opacity: 0; }
  76% { transform: translate(146px, 82px) scale(1.6); opacity: 0.35; }
  84%, 100% { transform: translate(146px, 82px) scale(2.4); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .scene-stack, .sheet3d, .detect-scene .reticle, .detect-scene .ping,
  .detect-modal.working .detect-modal-fill { animation: none; }
  .detect-scene .ping { opacity: 0; }
  .scene-stack { transform: rotateX(54deg) rotateZ(-10deg) translateY(14px); }
  .sheet-walls { transform: translateZ(-34px); }
  .sheet-text { transform: translateZ(40px); opacity: 0.45; }
  .detect-scene .reticle { transform: translate(120px, 44px); opacity: 1; }
}

/* -------------------------------------- revision match review (Task 2.2) */
.match-row { display: flex; gap: var(--s3); flex-wrap: wrap; align-items: flex-start; }
.match-thumbs { display: flex; gap: var(--s2); }
.match-thumbs figure { margin: 0; }
.match-thumbs img {
  width: 180px; max-width: 40vw; border: 1px solid var(--line);
  border-radius: var(--r-xs); background: #fff; display: block;
}
.match-thumbs figcaption { font-size: var(--fs-xs); color: var(--ink-soft); margin-top: 2px; max-width: 180px; }
.match-thumb-empty {
  width: 180px; max-width: 40vw; min-height: 90px; border: 1px dashed var(--line);
  border-radius: var(--r-xs); display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-xs); text-align: center; padding: 4px; align-self: stretch;
}
.match-meta { display: flex; flex-direction: column; gap: 6px; min-width: 140px; align-items: flex-start; }
.match-actions { display: flex; flex-direction: column; gap: 6px; margin-left: auto; }
.match-actions form { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin: 0; }
.badge.match-conflict { background: var(--crit-wash); color: var(--crit); }
.badge.match-proposed { background: var(--warn-wash); color: var(--warn); }
.badge.match-confirmed { background: var(--good-wash); color: var(--good); }
.badge.match-rejected { background: var(--sunken); color: var(--ink-soft); }
.badge.rev-status-match_review { background: var(--warn-wash); color: var(--warn); }
.badge.rev-status-analyzing { background: var(--accent-wash); color: var(--accent-ink); }
.badge.rev-status-approved { background: var(--good-wash); color: var(--good); }
.badge.rev-status-failed { background: var(--crit-wash); color: var(--crit); }
.rev-upload-form { display: flex; flex-direction: column; gap: var(--s2); max-width: 480px; }
@media (max-width: 700px) { .match-actions { margin-left: 0; } }

/* -------------------------------------- revision change queue (Task 3.3) */
.badge.rev-status-change_review { background: var(--warn-wash); color: var(--warn); }
.badge.rev-status-ready_for_approval { background: var(--good-wash); color: var(--good); }
.rev-readiness { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; justify-content: space-between; }
.rev-queue-filter { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: flex-end; }
.rev-delta { display: flex; flex-direction: column; gap: var(--s2); }
.rev-delta .toolbar h3, .rev-delta h4 { margin: 0; }
.rev-delta-grand { display: flex; gap: var(--s2); align-items: baseline; flex-wrap: wrap; font-size: 1.05rem; }
.rev-delta .table-wrap { overflow-x: auto; }
.rev-delta-table { border-collapse: collapse; min-width: 320px; }
.rev-delta-table th, .rev-delta-table td { padding: 3px 10px 3px 0; text-align: left; font-size: var(--fs-sm); }
.rev-delta-table .num { text-align: right; white-space: nowrap; }
.rev-delta-amount.up { color: var(--crit); font-weight: 600; }
.rev-delta-amount.down { color: var(--good); font-weight: 600; }
.rev-queue-filter label { display: flex; flex-direction: column; gap: 2px; }
.change-row { display: flex; gap: var(--s3); flex-wrap: wrap; align-items: flex-start; }
.change-row.blocking { border-left: 3px solid var(--crit); }
.change-main { display: flex; flex-direction: column; gap: 4px; flex: 1 1 320px; }
.change-evidence { display: flex; gap: var(--s2); flex-wrap: wrap; }
.change-actions { display: flex; flex-direction: column; gap: 6px; margin-left: auto; }
.change-actions form { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin: 0; }
.change-comments { list-style: none; margin: 4px 0 0; padding: 0; flex-basis: 100%; }
.change-comments li { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; padding: 2px 0; }
.change-comments form, .rev-comment-form { display: inline-flex; gap: 6px; align-items: center; margin: 0; }
.badge.blocking { background: var(--crit-wash); color: var(--crit); }
.badge.change-status-accepted { background: var(--good-wash); color: var(--good); }
.badge.change-status-rejected { background: var(--sunken); color: var(--ink-soft); }
.badge.change-status-pending, .badge.change-status-needs_review { background: var(--warn-wash); color: var(--warn); }
@media (max-width: 700px) { .change-actions { margin-left: 0; } }
