/* The shell — rail 176 · header 46 · KPI 62 · body · footer 28,
   matching design_handoff_cnc_brain_qt direction 1a "rail + inspector". */

@font-face {
  font-family: "Inter"; font-weight: 400; font-display: swap;
  src: url("/assets/fonts/Inter-Regular.ttf") format("truetype");
}
@font-face {
  font-family: "Inter"; font-weight: 500; font-display: swap;
  src: url("/assets/fonts/Inter-Medium.ttf") format("truetype");
}
@font-face {
  font-family: "Inter"; font-weight: 600; font-display: swap;
  src: url("/assets/fonts/Inter-SemiBold.ttf") format("truetype");
}

* { box-sizing: border-box; }

/* Tells the browser to paint its own controls dark — number-input spinners,
   the material <select>'s popup, scrollbars. Without it Chrome draws a light
   spinner on a #202020 field, which is exactly where it cannot be seen. */
html { color-scheme: dark; }

html, body {
  margin: 0; height: 100%; overflow: hidden;
  background: var(--desk); color: var(--text);
  font-family: "Inter", system-ui, sans-serif;
  font-size: var(--fs-body);
  /* Every figure in this UI is compared down a column. */
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

::selection { background: rgba(255, 255, 255, .22); }
* { scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.14) transparent; }
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,.14); border: 2px solid transparent;
  background-clip: content-box; border-radius: 9px;
}
::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.26); }

/* Monochrome Phosphor icons: mask so `color` drives them, as icons.py does. */
.icon {
  display: inline-block; width: 16px; height: 16px; flex: none;
  background: currentColor;
  -webkit-mask: var(--i) center / contain no-repeat;
  mask: var(--i) center / contain no-repeat;
}

/* ── app grid ─────────────────────────────────────────────────────────── */
#app { display: flex; height: 100vh; }

/* ── rail ─────────────────────────────────────────────────────────────── */
#rail {
  width: var(--rail-w); flex: none; background: var(--rail);
  border-right: 1px solid var(--rail-rule);
  display: flex; flex-direction: column;
}
.rail-brand {
  height: var(--header-h); flex: none; display: flex; align-items: center;
  gap: 8px; padding: 0 14px; border-bottom: 1px solid var(--rail-rule);
  font-size: var(--fs-title); font-weight: 500; letter-spacing: -.01em;
}
.rail-brand .icon { width: 18px; height: 18px; color: var(--accent-icon); }
.rail-items { flex: 1; padding: 8px 8px 0; overflow-y: auto; }
.rail-item {
  display: flex; align-items: center; gap: 9px; height: 30px;
  padding: 0 9px; border-radius: var(--radius-control);
  color: var(--muted); cursor: pointer; user-select: none;
  font-size: var(--fs-body);
}
.rail-item:hover { background: var(--hover); color: var(--text-2); }
.rail-item.on { background: var(--selected); color: var(--text); }
.rail-item .icon { width: 15px; height: 15px; }
.rail-item .count {
  margin-left: auto; font-size: var(--fs-label); color: var(--faint);
}
.rail-item.on .count { color: var(--muted); }

.rail-foot {
  flex: none; padding: 10px; border-top: 1px solid var(--rail-rule);
  display: flex; flex-direction: column; gap: 8px;
}
.sync-line {
  display: flex; align-items: center; gap: 7px;
  font-size: var(--fs-label); color: var(--faint);
}
.sync-line .icon { width: 13px; height: 13px; }
.login-btn, .sync-btn { width: 100%; justify-content: center; }
body.is-admin .login-btn { border-color: var(--accent-border); color: var(--text-2); }
.login .modal-body { display: flex; flex-direction: column; gap: 8px; }
.login .input-text { padding: 7px 9px; font-size: var(--fs-body); }
.login-error { font-size: var(--fs-label); color: var(--short); min-height: 14px; }
.sync-btn:disabled { opacity: .5; cursor: default; }
.sync-btn:disabled .icon { animation: spin 1.1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ── main column ──────────────────────────────────────────────────────── */
#main { flex: 1; min-width: 0; display: flex; flex-direction: column; background: var(--bg); }

#header {
  height: var(--header-h); flex: none; display: flex; align-items: center;
  gap: 12px; padding: 0 var(--pad-screen);
  border-bottom: 1px solid var(--hairline);
}
#screen-title { font-size: var(--fs-title); font-weight: 500; letter-spacing: -.01em; }
.header-tools { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* controls */
.field {
  display: flex; align-items: center; gap: 7px; height: 28px; padding: 0 9px;
  background: var(--field); border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-control); color: var(--muted);
}
.field:focus-within { border-color: var(--accent-border); }
.field .icon { width: 14px; height: 14px; }
.field input {
  background: none; border: 0; outline: 0; color: var(--text);
  font: inherit; width: 190px;
}
.field input::placeholder { color: var(--empty); }
.field kbd {
  font: inherit; font-size: var(--fs-label); color: var(--empty);
  border: 1px solid var(--hairline-strong); border-radius: 4px; padding: 0 4px;
}

.seg {
  display: flex; background: var(--field); border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-control); padding: 2px; gap: 2px;
}
.seg button {
  background: none; border: 0; color: var(--dim); font: inherit;
  font-size: var(--fs-meta); padding: 3px 10px; border-radius: 4px; cursor: pointer;
}
.seg button:hover { color: var(--text-2); }
.seg button.on { background: var(--selected); color: var(--text); }

/* ── KPI strip ────────────────────────────────────────────────────────── */
#kpis {
  height: var(--kpi-h); flex: none; display: flex; align-items: center;
  gap: 28px; padding: 0 var(--pad-screen);
  border-bottom: 1px solid var(--hairline);
}
/* The strip centres each block, so blocks of different heights would put their
   labels on different lines. One shared box height keeps every label aligned. */
.kpi, .mix { min-height: 54px; justify-content: flex-start; }
.kpi { display: flex; flex-direction: column; gap: 1px; min-width: 96px; }
/* Not scoped to .kpi — the priority mix sits outside one and needs the
   same label treatment to read as part of the strip. */
.k-label {
  font-size: var(--fs-label); color: var(--dim);
  letter-spacing: .06em; text-transform: uppercase;
}
.kpi .k-value { font-size: var(--fs-kpi); font-weight: 500; letter-spacing: -.02em; line-height: 1.1; }
.kpi .k-sub { font-size: var(--fs-label); color: var(--faint); }
/* Sits in the strip beside the other KPIs, not pushed to the far edge. */
.kpi-extra { display: flex; align-items: center; gap: 10px; }

/* Priority mix — a KPI in its own right, at KPI weight. */
.mix { display: flex; flex-direction: column; gap: 1px; min-width: 236px; }
/* Match the height of a KPI's value line and sit on its bottom edge, so the
   smaller counts still share the strip's baseline. Expressed from the token so
   it survives a change to --fs-kpi. */
.mix-tiers {
  display: flex; gap: 14px;
  min-height: calc(var(--fs-kpi) * 1.1); align-items: flex-end;
}
.mix-tier { display: flex; align-items: baseline; gap: 5px; }
.mix-tier.zero { opacity: .45; }
.mix-stars { font-size: 12px; letter-spacing: -.5px; white-space: nowrap; }
.mix-count {
  font-size: 18px; font-weight: 500; letter-spacing: -.02em; line-height: 1.1;
  color: var(--text);
}
.mix-tier.zero .mix-count { color: var(--faint); }
.mix-bar {
  display: flex; height: 5px; border-radius: 3px; overflow: hidden;
  background: var(--track); margin-top: 2px;
}
.mix-bar span { display: block; height: 100%; }

/* Inventory reuses the bar + legend at their original, quieter size. */
.panel-body-pad .mix-bar { height: 6px; }
.mix-legend { display: flex; gap: 10px; font-size: var(--fs-label); color: var(--faint); }
.mix-legend i { display: inline-block; width: 6px; height: 6px; border-radius: 2px; margin-right: 4px; }

/* ── body ─────────────────────────────────────────────────────────────── */
#body { flex: 1; min-height: 0; display: flex; }
/* overflow:auto plus the table's min-width is what makes a wide table scroll
   sideways instead of crushing its columns. */
#content { flex: 1; min-width: 0; position: relative; overflow: auto;
           overscroll-behavior-x: contain; }

/* ── table ────────────────────────────────────────────────────────────── */
/* Fixed layout so the column widths from the Qt COLUMNS specs are honoured
   exactly; the one 0-width column absorbs the rest.
   `separate` rather than `collapse`: collapsed borders under a sticky header
   round up the table's scroll width and leave a phantom horizontal scrollbar. */
table.grid { width: 100%; border-collapse: separate; border-spacing: 0; table-layout: fixed; }
table.grid thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--header-sticky);
  font-size: var(--fs-label); font-weight: 500; color: var(--dim);
  letter-spacing: .05em; text-transform: uppercase;
  text-align: left; padding: 0 8px; height: 28px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
  border-bottom: 1px solid var(--hairline); cursor: pointer; user-select: none;
}
table.grid thead th:hover { color: var(--text-2); }
/* Header columns drag to reorder; the line shows where the drop lands. */
table.grid thead th[draggable="true"] { cursor: grab; }
table.grid thead th.drop-before { box-shadow: inset 2px 0 0 var(--accent-border); }
table.grid thead th.drop-after { box-shadow: inset -2px 0 0 var(--accent-border); }

table.grid thead th.num { text-align: right; }
table.grid thead th.mid { text-align: center; }
/* Absolute, so the marker never eats width from a narrow header like MAT. */
table.grid thead th .sortmark {
  position: absolute; right: 2px; top: 50%; transform: translateY(-50%);
  font-size: 8px; opacity: 0;
}
table.grid thead th.sorted .sortmark { opacity: .75; }

table.grid tbody tr { height: var(--row-h); }
table.grid tbody td { border-bottom: 1px solid var(--row-rule); }
table.grid tbody tr:nth-child(even) { background: var(--zebra); }
table.grid tbody tr:hover { background: var(--hover); }
table.grid tbody tr.on { background: var(--selected); }
table.grid td {
  padding: 0 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Numeric columns are narrow and their headers are the longest word in them
   ("SHEETS" in 62px), so trim the gutter — header and figures keep the same
   padding so they stay aligned on the right edge. */
table.grid td.num, table.grid thead th.num { text-align: right; padding: 0 6px; }
/* Centred columns are the narrow ones (Prio, Mat) — they cannot spare 10px. */
table.grid td.mid, table.grid thead th.mid { text-align: center; padding: 0 4px; }

/* "Completed (212)" divider — click to fold the finished work away */
table.grid tbody tr.fold-row { cursor: pointer; height: 26px; }
table.grid tbody tr.fold-row td {
  background: var(--raised); color: var(--dim);
  font-size: var(--fs-label); letter-spacing: .04em; text-transform: uppercase;
  border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline);
  padding: 0 10px;
}
table.grid tbody tr.fold-row:hover td { background: var(--field); color: var(--text-2); }
tr.fold-row .caret {
  display: inline-block; margin-right: 7px; transition: transform .12s;
  color: var(--faint);
}
tr.fold-row .caret.open { transform: rotate(90deg); }
tr.fold-row .fold-hint { float: right; color: var(--faint); text-transform: none; }

.empty-note {
  position: absolute; inset: 28px 0 0 0; display: grid; place-items: center;
  color: var(--faint); font-size: var(--fs-body); pointer-events: none;
}

/* cell renderers — the web twins of delegates.py */
.stars { font-size: 10px; letter-spacing: 0; color: var(--mark); white-space: nowrap; }
.stars .off { color: var(--empty); }

.pill {
  display: inline-block; padding: 1px 7px; border-radius: 4px;
  font-size: var(--fs-label); line-height: 16px;
  background: rgba(255,255,255,.10); color: var(--faint);
}
.pill.s-processing, .pill.s-next { background: #2b2b2b; color: var(--accent-text); }
.pill.s-pending, .pill.s-later, .pill.s-ordered { background: rgba(255,255,255,.07); color: var(--muted); }
.pill.s-backlog, .pill.s-none { background: rgba(255,255,255,.04); color: var(--faint); }
.pill.s-completed, .pill.s-done, .pill.s-ok { background: var(--chip-ready); color: var(--ready); }
.pill.s-blocked, .pill.s-out, .pill.s-outofstock { background: var(--chip-short); color: var(--short); }
.pill.s-low, .pill.s-needsorder { background: var(--chip-tight); color: var(--tight); }

/* Explicit tones, for values whose text cannot become a class name. */
.pill.p-neutral { background: #2b2b2b; color: var(--accent-text); }
.pill.p-quiet   { background: rgba(255,255,255,.07); color: var(--muted); }
.pill.p-faint   { background: rgba(255,255,255,.04); color: var(--faint); }
.pill.p-ready   { background: var(--chip-ready); color: var(--ready); }
.pill.p-tight   { background: var(--chip-tight); color: var(--tight); }
.pill.p-short   { background: var(--chip-short); color: var(--short); }

.dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: rgba(255,255,255,.16); flex: none; }
.dot.d-ok { background: var(--ready); }
.dot.d-warn { background: var(--tight); }
.dot.d-bad { background: var(--short); }

.dotname { display: flex; align-items: center; gap: 8px; min-width: 0; }
.dotname .dotname-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* trailing tag on a dotname cell — Inventory's NON-STANDARD marker */
.rowchip {
  flex: none; margin-left: auto; padding: 2px 6px; border-radius: 20px;
  font-size: 10px; letter-spacing: .04em;
  background: var(--chip-short); color: var(--short);
}

/* the 2px status edge on a row's first cell */
table.grid td.edge { box-shadow: inset 2px 0 0 transparent; }
table.grid td.edge.e-short { box-shadow: inset 2px 0 0 var(--short); }
table.grid td.edge.e-tight { box-shadow: inset 2px 0 0 var(--tight); }
table.grid td.edge.e-ready { box-shadow: inset 2px 0 0 var(--ready); }

/* days-left / coverage bar */
.bar { display: flex; align-items: center; gap: 8px; }
.bar-track {
  flex: 1; min-width: 24px; height: 5px; border-radius: 3px;
  background: var(--track); overflow: hidden;
}
.bar-fill { display: block; height: 100%; border-radius: 3px; background: var(--dim); }
.bar-fill.f-ready { background: var(--ready); }
.bar-fill.f-tight { background: var(--tight); }
.bar-fill.f-short { background: var(--short); }
.bar-label { flex: none; font-size: var(--fs-label); color: var(--muted); min-width: 34px; text-align: right; }

/* read-only stock figure */
.stepper {
  display: inline-block; min-width: 34px; padding: 1px 8px;
  border: 1px solid var(--hairline-strong); border-radius: var(--radius-control);
  background: var(--field); font-size: var(--fs-meta); text-align: center;
}

/* main line over a quieter second line */
.twoline { display: flex; flex-direction: column; justify-content: center; line-height: 1.25; min-width: 0; }
.twoline .l1 { overflow: hidden; text-overflow: ellipsis; }
.twoline .l2 { font-size: var(--fs-label); color: var(--faint); overflow: hidden; text-overflow: ellipsis; }

/* ── side panel ───────────────────────────────────────────────────────── */
/* The inspector grows with the window rather than sitting at a fixed 352px —
   on a fullscreen monitor the table has slack to spare and the file names,
   paths and chips in here are what actually need the room. Dragging the left
   edge overrides it, within the same 260–760 range the Qt splitter allows. */
#panel {
  /* Default to the full width the splitter allows; only give way on a screen
     too narrow to spare it, so the table keeps a workable share. */
  width: var(--panel-live, min(760px, 42vw));
  flex: none; background: var(--panel);
  border-left: 1px solid var(--hairline);
  display: flex; flex-direction: column; min-height: 0; position: relative;
}
#panel-grip {
  position: absolute; left: -3px; top: 0; bottom: 0; width: 7px;
  cursor: col-resize; z-index: 5;
}
#panel-grip:hover, #panel-grip.dragging { background: var(--selected); }
body.resizing { cursor: col-resize; user-select: none; }
/* Screens replace #panel-body, so the grip survives every reload. */
#panel-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.panel-head {
  flex: none; padding: var(--pad-panel); border-bottom: 1px solid var(--hairline-soft);
}
.panel-title { font-size: var(--fs-body); font-weight: 500; line-height: 1.4; }
.panel-sub { margin-top: 3px; font-size: var(--fs-label); color: var(--faint); word-break: break-all; }
.panel-meta { margin-top: 9px; display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: var(--fs-label); color: var(--dim); }
.panel-meta b { color: var(--text-2); font-weight: 500; }
.panel-body { flex: 1; overflow-y: auto; padding: 6px 0; min-height: 0; }
.panel-foot {
  flex: none; padding: 10px var(--pad-panel); border-top: 1px solid var(--hairline-soft);
  display: flex; gap: 8px; font-size: var(--fs-label); color: var(--faint);
}

.file-row {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 7px var(--pad-panel); border-left: 2px solid transparent;
}
.file-row:hover { background: var(--hover); }
.file-row.e-short { border-left-color: var(--short); }
.file-row.e-tight { border-left-color: var(--tight); }
.file-row > .icon { width: 15px; height: 15px; margin-top: 1px; color: var(--dim); }
.file-row.done { color: var(--faint); }
.file-row.done > .icon { color: var(--ready); }
.file-main { flex: 1; min-width: 0; }
.file-name { font-size: var(--fs-meta); line-height: 1.35; word-break: break-word; }
.file-meta { font-size: var(--fs-label); color: var(--faint); margin-top: 2px; }
.file-side { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.file-hours { font-size: var(--fs-label); color: var(--muted); }
.chip {
  font-size: 10px; padding: 1px 5px; border-radius: 3px;
  background: rgba(255,255,255,.08); color: var(--muted);
}
.chip.c-ready { background: var(--chip-ready); color: var(--ready); }
.chip.c-short { background: var(--chip-short); color: var(--short); }
.chip.c-tight { background: var(--chip-tight); color: var(--tight); }
.chip.c-neutral { background: var(--selected); color: var(--accent-text); }

.path-row { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; margin-top: 10px; }
.path-row .panel-sub { margin-top: 0; font-family: ui-monospace, Consolas, monospace; font-size: 10px; line-height: 1.45; }
.btn {
  display: inline-flex; align-items: center; gap: 6px; height: 24px; padding: 0 9px;
  background: none; border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-control); color: var(--muted);
  font: inherit; font-size: var(--fs-label); cursor: pointer;
}
.btn:hover { border-color: var(--accent-border); color: var(--text); background: var(--hover); }
.btn .icon { width: 13px; height: 13px; }

/* ── panel building blocks ────────────────────────────────────────────── */
.panel-stack { overflow-y: auto; min-height: 0; }
.panel-stack > div + div { border-top: 1px solid var(--hairline-soft); }
.panel-stack .panel-head { border-bottom: 0; padding-bottom: 6px; }
.panel-body-pad { padding: 0 var(--pad-panel) 10px; }
.panel-note {
  padding: 2px var(--pad-panel) 14px; font-size: var(--fs-label);
  color: var(--faint); line-height: 1.5;
}
.stat-lines { padding: 0 var(--pad-panel) 12px; }
.stat-line {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; padding: 3px 0; font-size: var(--fs-meta); color: var(--dim);
}
.stat-line b { font-weight: 500; color: var(--text-2); }
.code-list { padding: 0 var(--pad-panel) 6px; }
.code-row {
  display: flex; justify-content: space-between; gap: 10px; padding: 4px 0;
  font-size: var(--fs-meta); color: var(--faint);
}
.code-row b { color: var(--tight); font-weight: 500; }

/* ── schedule week grid ───────────────────────────────────────────────── */
.week {
  display: grid; grid-template-columns: 150px repeat(5, minmax(0, 1fr));
  align-content: start; min-height: 100%;
}
.week > * { border-right: 1px solid var(--row-rule); border-bottom: 1px solid var(--row-rule); }
.week-head {
  position: sticky; top: 0; z-index: 2; background: var(--header-sticky);
  display: flex; align-items: center; gap: 7px; height: 30px; padding: 0 10px;
  font-size: var(--fs-label); font-weight: 500; color: var(--dim);
  letter-spacing: .05em; text-transform: uppercase;
  border-bottom: 1px solid var(--hairline);
}
.week-head.today { color: var(--accent-text); box-shadow: inset 0 -2px 0 var(--mark); }
.week-date { color: var(--faint); letter-spacing: 0; text-transform: none; }
.week-person {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 0 10px; min-height: 62px; background: var(--rail);
  font-size: var(--fs-body);
}
.week-person.week-head { min-height: 0; background: var(--header-sticky); }
.week-load { font-size: var(--fs-label); color: var(--muted); }
.week-cell { padding: 6px; min-height: 62px; display: flex; flex-direction: column; gap: 4px; }
.week-cell.over { background: rgba(193, 101, 74, .07); }
.week-cell-load { margin-top: auto; font-size: 10px; color: var(--faint); text-align: right; }
.week-cell.over .week-cell-load { color: var(--short); }
.job {
  display: flex; align-items: baseline; gap: 6px; padding: 3px 7px;
  background: var(--raised); border: 1px solid var(--hairline-strong);
  border-radius: 5px; font-size: var(--fs-label); min-width: 0;
}
.job-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.job-hours { flex: none; color: var(--muted); }
.week-label { font-size: var(--fs-meta); color: var(--muted); }

/* ── edit controls ────────────────────────────────────────────────────── */
.input-text {
  background: var(--field); color: var(--text-2); font: inherit;
  font-size: var(--fs-label); border: 1px solid var(--hairline-strong);
  border-radius: 4px; padding: 1px 4px; max-width: 100%;
}
.input-text:hover { border-color: var(--accent-border); }
.input-text:focus { outline: 0; border-color: var(--mark); }

.panel-assign { margin-top: 10px; display: flex; flex-direction: column; gap: 6px; }
.assign-row { display: flex; align-items: flex-start; gap: 8px; }
.assign-label {
  flex: none; width: 50px; padding-top: 3px;
  font-size: var(--fs-label); color: var(--dim);
}
.chip-toggles { display: flex; flex-wrap: wrap; gap: 4px; }
/* Read-only assignment chips — Odoo owns these values. */
.chip-static {
  border: 1px solid var(--hairline-strong); border-radius: 4px;
  color: var(--text-2); font-size: var(--fs-label); padding: 1px 7px;
}
.assign-none { font-size: var(--fs-label); color: var(--empty); padding-top: 2px; }

.editable { cursor: text; border-bottom: 1px dashed transparent; }
.editable:hover { border-bottom-color: var(--accent-border); }

.stepper-edit { display: inline-flex; align-items: center; gap: 2px; }
.stepper-edit button {
  width: 18px; height: 18px; padding: 0; line-height: 1;
  background: var(--field); border: 1px solid var(--hairline-strong);
  border-radius: 4px; color: var(--muted); font: inherit; cursor: pointer;
}
.stepper-edit button:hover { color: var(--text); border-color: var(--accent-border); }
.stepper-value { min-width: 24px; text-align: center; font-size: var(--fs-meta); }

.file-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* ── footer ───────────────────────────────────────────────────────────── */
#footer {
  height: var(--footer-h); flex: none; display: flex; align-items: center;
  gap: 12px; padding: 0 var(--pad-screen);
  border-top: 1px solid var(--hairline);
  font-size: var(--fs-label); color: var(--faint);
}
#footer-right { margin-left: auto; display: flex; gap: 14px; }
.legend { display: inline-flex; align-items: center; gap: 5px; }
.legend i { width: 6px; height: 6px; border-radius: 50%; display: inline-block; }

/* ── right-click menu ─────────────────────────────────────────────────── */
.menu-panel {
  background: var(--raised); border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-control); padding: 4px;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .55);
  min-width: 186px; font-size: var(--fs-meta);
}
.menu-root { position: fixed; z-index: 60; }
.menu-heading {
  padding: 4px 9px 5px; font-size: var(--fs-label); color: var(--faint);
  letter-spacing: .05em; text-transform: uppercase;
}
.menu-sep { height: 1px; background: var(--hairline); margin: 4px 2px; }
.menu-item {
  position: relative; display: flex; align-items: center; gap: 10px;
  padding: 5px 9px; border-radius: 4px; color: var(--text-2); cursor: pointer;
  white-space: nowrap;
}
.menu-item:hover { background: var(--hover); color: var(--text); }
.menu-item.disabled { color: var(--empty); cursor: default; background: none; }
.menu-item.on .menu-label::before { content: "✓ "; color: var(--mark); }
.menu-label { flex: 1; }
.menu-note { color: var(--faint); font-size: var(--fs-label); }
.menu-caret { color: var(--faint); }
/* one level of nesting, opened on hover */
.menu-sub { display: none; position: absolute; left: 100%; top: -5px; margin-left: 2px; }
.menu-sub.flip { left: auto; right: 100%; margin: 0 2px 0 0; }
.menu-item.has-sub:hover > .menu-sub { display: block; }

/* ── Odoo cover-image preview ─────────────────────────────────────────── */
.img-preview {
  position: fixed; z-index: 55; padding: 4px; pointer-events: none;
  background: var(--raised); border: 1px solid #3a3a3a;
  border-radius: 6px; box-shadow: 0 10px 26px rgba(0, 0, 0, .55);
  opacity: 0; transition: opacity .1s; display: none;
}
.img-preview.on { opacity: 1; display: block; }
.img-preview img { display: block; max-width: 420px; max-height: 420px; border-radius: 3px; }

/* ── modal ────────────────────────────────────────────────────────────── */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 70; display: grid; place-items: center;
  background: rgba(0, 0, 0, .55); padding: 24px;
}
.modal-card {
  background: var(--bg); border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-card); box-shadow: 0 18px 50px rgba(0, 0, 0, .6);
  display: flex; flex-direction: column;
  width: min(920px, 100%); max-height: min(680px, 100%);
}
.modal-head { flex: none; padding: 14px 18px; border-bottom: 1px solid var(--hairline); }
.modal-title { font-size: var(--fs-title); font-weight: 500; }
.modal-sub { margin-top: 2px; font-size: var(--fs-label); color: var(--faint); }
.modal-body { flex: 1; overflow-y: auto; padding: 14px 18px; min-height: 0; }
.modal-foot {
  flex: none; padding: 12px 18px; border-top: 1px solid var(--hairline);
  display: flex; flex-direction: column; gap: 7px;
}
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; }
.btn.primary { border-color: var(--accent-border); color: var(--text); background: var(--field); }
.btn.primary:hover { background: var(--selected); }
.btn:disabled { opacity: .5; cursor: default; }

/* ── log-material dialog ──────────────────────────────────────────────── */
.lm-intro { font-size: var(--fs-meta); color: var(--muted); line-height: 1.55; margin-bottom: 14px; }
.lm-grid {
  display: grid; grid-template-columns: 84px minmax(0, 1fr) 92px minmax(0, 210px);
  gap: 8px 12px; align-items: start;
}
.lm-head { font-size: var(--fs-label); color: var(--faint); text-transform: uppercase; letter-spacing: .05em; }
.lm-nr { font-size: var(--fs-meta); color: var(--accent-icon); padding-top: 5px; }
.lm-count { width: 100%; padding: 4px 6px; font-size: var(--fs-meta); }
.lm-warn { font-size: var(--fs-label); color: var(--tight); padding-top: 5px; line-height: 1.4; }
.lm-empty { color: var(--faint); font-size: var(--fs-body); padding: 24px 0; text-align: center; }
.lm-notes { margin-top: 16px; display: flex; flex-direction: column; gap: 10px; }
.lm-note { font-size: var(--fs-label); color: var(--faint); line-height: 1.6; }
.lm-note b { display: block; color: var(--muted); margin-bottom: 2px; }
.lm-note.bad b { color: var(--short); }
.lm-check { display: flex; align-items: center; gap: 7px; font-size: var(--fs-meta); color: var(--muted); }
.lm-status { font-size: var(--fs-meta); color: var(--faint); min-height: 16px; }

/* filtered combobox — 650 sheets is far too many for a plain <select> */
.combo { position: relative; }
.combo-input { width: 100%; padding: 4px 22px 4px 7px; font-size: var(--fs-meta); }
/* The caret is the only thing saying this is a dropdown and not a text field —
   without it nobody finds the other sheets in the family. */
.combo-caret {
  position: absolute; right: 1px; top: 1px; bottom: 1px; width: 20px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 0; padding: 0; cursor: pointer; color: var(--faint);
}
.combo-caret:hover { color: var(--text-2); }
.combo-caret .caret { width: 12px; height: 12px; }
.combo-list {
  display: none; position: absolute; left: 0; right: 0; top: calc(100% + 2px);
  z-index: 5; max-height: 260px; overflow-y: auto;
  background: var(--raised); border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-control); box-shadow: 0 10px 26px rgba(0, 0, 0, .5);
}
.combo-list.on { display: block; }
.combo-opt {
  padding: 4px 9px; font-size: var(--fs-label); color: var(--text-2);
  cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.combo-opt:hover, .combo-opt.on { background: var(--hover); color: var(--text); }
.combo-opt.current { color: var(--mark); }
.combo-empty { padding: 6px 9px; font-size: var(--fs-label); color: var(--empty); }

/* loading / error */
#toast {
  position: fixed; bottom: 14px; left: 50%; transform: translateX(-50%);
  background: var(--raised); border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-control); padding: 7px 13px;
  font-size: var(--fs-meta); color: var(--text-2);
  opacity: 0; transition: opacity .15s; pointer-events: none; z-index: 40;
}
#toast.on { opacity: 1; }
#toast.bad { border-color: var(--short); color: var(--short); }

/* Narrow screens: the inspector drops away rather than crushing the table. */
@media (max-width: 1100px) {
  #panel { display: none; }
}
@media (max-width: 720px) {
  #rail { width: 52px; }
  .rail-item .label, .rail-brand span, .sync-line span { display: none; }
  .rail-item { justify-content: center; }
  .rail-item .count { display: none; }
}
