/* Krantz Quoting — dark app chrome. Tokens from BRAND.md, sampled from the
   real brand assets. The quote preview/Word output is a SEPARATE light
   stylesheet — never share tokens between the two. */

:root {
  /* Brand — do not alter */
  --krantz-charcoal:       #444247;
  --krantz-charcoal-print: #4C494B;
  --krantz-bone:           #EBEBE1;
  --krantz-stone:          #B8B5B0;

  /* Surfaces — stepped from the brand grey #444247, per BRAND.md.
     Anchored on THE brand grey (--bg-raised), stepped either side.
     Cool, faintly violet — deliberately NOT navy, NOT near-black. */
  --bg-base:       #2B2A2E;   /* app background, one step under brand */
  --bg-surface:    #333237;   /* cards / panels */
  --bg-raised:     #444247;   /* THE brand grey — nav, headers, active rows */
  --bg-input:      #26252A;   /* inset fields — darker than base */
  --bg-hover:      #3C3B40;

  /* Ink */
  --text-primary:   #EBEBE1;  /* bone */
  --text-secondary: #B8B5B0;  /* stone */
  --text-muted:     #7C7A80;  /* labels, units, disabled — a11y floor on base */

  /* Lines */
  --border:        #4F4D53;
  --border-strong: #605E66;

  /* Semantic — muted, never saturated (BRAND.md). The interactive accent is
     Krantz WHITE (bone) — estimator 2026-07-19: no gold on chrome. Brass
     survives ONLY as the awaiting-price status signal (never colour alone). */
  --accent:        #EBEBE1;   /* bone — links / focus / active nav */
  --accent-hover:  #FFFFFF;   /* pure white on hover/active */
  --positive:      #8FA68A;   /* sage */
  --warning:       #C4A67A;   /* brass — the awaiting-price signal */
  --danger:        #B57F7F;   /* muted clay */

  /* Money */
  --figure:        #EBEBE1;   /* bone, tabular numerals */
  --figure-total:  #FFFFFF;   /* pure white — room / job totals only */

  --font-ui: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-display: "Cormorant Garamond", Georgia, serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg-base);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.45;
}

/* ── chrome ─────────────────────────────────────────────────────────── */

.topbar {
  display: flex;
  align-items: center;
  gap: 30px;
  height: 64px;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  padding: 0 28px;
}
/* the real bone wordmark (krantz-logo-bone.png), top-left on the dark chrome */
.wordmark { display: flex; align-items: center; text-decoration: none; }
.wordmark img { display: block; height: 44px; width: auto; }
.topbar nav { display: flex; gap: 4px; }
.topbar nav a {
  color: var(--text-secondary);
  text-decoration: none;
  padding: 7px 14px;
  border-radius: 7px;
  font-weight: 500;
}
.topbar nav a:hover { color: var(--text-primary); background: var(--bg-hover); }
.topbar nav a.active { color: var(--text-primary); background: var(--bg-raised); }
.save-indicator { margin-left: auto; color: var(--positive); font-size: 12px; }

/* who's signed in — top-right of the chrome */
.user-chip { display: flex; align-items: center; gap: 8px; }
.user-chip .user-name { color: var(--text-secondary); font-size: 12.5px;
  white-space: nowrap; }
.user-chip form { display: flex; }
.avatar-chip { display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%; background: var(--bg-raised);
  border: 1px solid var(--border-strong); font-size: 10.5px; font-weight: 600;
  color: var(--text-primary); text-decoration: none !important; }
a.avatar-chip:hover { border-color: var(--accent); }
a.user-chip-setup { color: var(--text-muted); font-size: 12px;
  text-decoration: none; padding: 5px 10px; border: 1px solid var(--border);
  border-radius: 6px; }
a.user-chip-setup:hover { color: var(--text-primary); text-decoration: none;
  border-color: var(--border-strong); }
.saved-flash { animation: fade 2s forwards; }
@keyframes fade { 0%,60% { opacity: 1; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .saved-flash { animation: none; } }

.page { padding: 20px; max-width: 1280px; margin: 0 auto; }
/* A screen with more columns than 1280px fits — see base.html's page_class. */
.page-wide { max-width: 1560px; }

/* ── pagination ─────────────────────────────────────────────────────────
   The library is 732 codes. Numbered pages rather than infinite scroll: an
   admin fixing points works down a list and needs to be able to come back to
   where they were, which a scroll position does not give you. */
.pager { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 14px 0 4px; font-size: 12.5px; }
.pager-step { padding: 5px 12px; border-radius: 5px;
  border: 1px solid var(--border-strong); background: var(--bg-raised);
  color: var(--text-primary); text-decoration: none; white-space: nowrap; }
.pager-step:hover { border-color: var(--accent); text-decoration: none; }
.pager-step.is-off { opacity: .32; }
.pager-nums { display: flex; gap: 3px; }
.pager-n { min-width: 30px; padding: 5px 0; border-radius: 5px;
  text-align: center; color: var(--text-secondary); text-decoration: none;
  font-variant-numeric: tabular-nums; }
.pager-n:hover { background: var(--bg-hover); color: var(--text-primary);
  text-decoration: none; }
.pager-n.is-here { background: var(--accent); color: var(--bg-base);
  font-weight: 600; }
.pager-of { margin-left: auto; color: var(--text-muted); }

h1, h2 { font-weight: 500; }
h1.display { font-family: var(--font-display); font-weight: 600; font-size: 34px;
             color: var(--figure-total); margin: 0 0 6px; line-height: 1.05; }
h2 { font-size: 11px; text-transform: uppercase; letter-spacing: .12em;
     color: var(--text-secondary); font-weight: 600; margin: 26px 0 10px; }

/* Text links carry a quiet at-rest underline: the accent is now bone — the
   same colour as body text — so colour alone can no longer mark a link as
   clickable. Chrome anchors (nav, wordmark, .btn, cards, crumbs) opt out. */
a { color: var(--accent); text-decoration: underline;
    text-decoration-color: var(--border-strong); text-underline-offset: 2px; }
a:hover { color: var(--accent-hover); text-decoration-color: var(--accent-hover); }
.wordmark, .crumbs a, .proc-card, .proc-link { text-decoration: none; }
.proc-card:hover, .proc-link:hover, .crumbs a:hover { text-decoration: none; }

/* breadcrumb row at the top of every working screen */
.crumbs { font-size: 12px; color: var(--text-muted); margin: 0 0 6px; }
.crumbs a { color: var(--text-secondary); }
.crumbs a:hover { color: var(--accent-hover); }

/* ── inputs ─────────────────────────────────────────────────────────── */

input, select, button, textarea {
  font: inherit;
  color: var(--text-primary);
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
}
input:focus, select:focus, button:focus, textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}
input::placeholder { color: var(--text-muted); }
/* A <select> sizes itself to its LONGEST option ("Based on the Greenwich
   Collection by Hendel & Hendel…") and will happily blow a panel open.
   Never let it: cap at the container and truncate the closed control. */
select { background: var(--bg-input); max-width: 100%; min-width: 0;
         text-overflow: ellipsis; }

/* dark, quiet scrollbars — the OS default light bar looks broken on charcoal */
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 6px;
  border: 3px solid var(--bg-base); }
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }

/* library combo fields (datalist): show a caret so they read as dropdowns
   while still accepting free-typed bespoke values */
input[list], table.grid td input[list] {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%237C7A80' stroke-width='1.5'/></svg>");
  background-repeat: no-repeat;
  background-position: right 4px center;
  padding-right: 16px;
}

/* select + type-your-own combos (spec-sheet Cabinet Details & F&F). A real
   <select> always shows every option; picking "type your own" reveals the
   sibling input for a bespoke value. */
.combo-cell { width: 100%; }
select.combo { width: 100%; max-width: 100%; }
input.combo-value { width: 100%; margin-top: 5px; }
.combo-note {
  margin-top: 4px; font-size: 11px; color: var(--accent);
}

button { cursor: pointer; background: var(--bg-surface); }
button:hover { background: var(--bg-hover); border-color: var(--border-strong); }

/* THE primary action: bone on charcoal, like the wordmark. One per form. */
button.primary {
  background: var(--krantz-bone); color: #2B2A2E;
  border-color: var(--krantz-bone); font-weight: 600;
}
button.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
/* the inverted primary button needs its own focus ring — the shared bone
   outline is invisible on its bone fill. Float it clear on the dark panel. */
button.primary:focus { outline: 2px solid var(--accent); outline-offset: 2px; }
button.danger { color: var(--danger); }

/* Anchor-buttons: navigation actions that must read as solid controls, not
   underlined text ("back to the quote", "cost calculator", document exports).
   text-transform/letter-spacing reset so they survive inside <h2>s. */
.btn, a.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 13px;
  background: var(--bg-surface);
  border: 1px solid var(--border-strong); border-radius: 6px;
  color: var(--text-primary); text-decoration: none;
  font-size: 13px; font-weight: 500; line-height: 1.45;   /* match native button height */
  text-transform: none; letter-spacing: normal; white-space: nowrap;
  cursor: pointer;
}
.btn:hover, a.btn:hover {
  background: var(--bg-hover); border-color: var(--accent);
  color: var(--accent-hover); text-decoration: none;
}
.btn-sm, a.btn-sm { padding: 3px 10px; font-size: 11.5px; }
/* Ghost (icon) buttons — the ×, chevron, ＋, ↵ on every row. A hairline border
   and stone (not muted) text so they actually read as buttons at rest, not just
   on hover. (Usability: controls must be discoverable when you don't already
   know they're there.) */
button.ghost {
  background: none; border: 1px solid var(--border); color: var(--text-secondary);
  padding: 2px 6px;
}
button.ghost:hover { color: var(--text-primary); background: var(--bg-hover);
  border-color: var(--border-strong); }

/* ── panels & forms ─────────────────────────────────────────────────── */

.panel {
  background: var(--bg-surface);
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  padding: 18px 20px;
  margin-bottom: 18px;
}
.field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 10px 14px;
}
.field-grid label {
  display: flex; flex-direction: column; gap: 3px;
  font-size: 11px; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .05em;
}
.inline-form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* ── data tables: dense, hairline rules, no zebra ───────────────────── */

table.grid { width: 100%; border-collapse: collapse; }
/* Fixed layout for tables holding library dropdowns: the columns keep their
   declared widths and a long option can never stretch the table past its
   panel (the spec-sheet / F&F overrun fix). */
table.grid-fixed { table-layout: fixed; }
table.grid th {
  text-align: left; font-size: 10px; font-weight: 600;
  color: var(--text-muted); text-transform: uppercase; letter-spacing: .1em;
  padding: 8px; background: var(--bg-base);
  border-bottom: 1px solid var(--border-strong);
}
/* figure headers must right-align to sit over their right-aligned numbers.
   `table.grid th` (0,1,2) outranks a bare `th.figure` (0,1,1), so the header
   would otherwise drift left of the column of numbers. This wins (0,2,2). */
table.grid th.figure { text-align: right; }
table.grid th.actions { text-align: right; }
table.grid td {
  height: 32px; padding: 0 8px;
  border-bottom: 1px solid var(--border);
}
table.grid tr:hover td { background: var(--bg-hover); }

/* inputs live inside rows and inherit the row background (BRAND density: no
   boxed inputs in a data grid). They fill on hover/focus so it's clear you can
   type there — the discoverable "start here" affordance is the boxed entry
   row below, not a per-cell border. */
table.grid td input, table.grid td select {
  width: 100%; background: transparent; border: none;
  border-radius: 0; padding: 6px 2px; height: 31px;
}
table.grid td input:hover, table.grid td select:hover {
  background: var(--bg-input);
}
table.grid td input:focus, table.grid td select:focus {
  outline: 2px solid var(--accent); outline-offset: -2px;
  background: var(--bg-input);
}

.figure, td.figure, th.figure {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  text-align: right;
  color: var(--figure);
  white-space: nowrap;
}
/* 3.1 — numeric inputs align on the right (Qty, cost, margin, VAT, £ figures)
   so columns of numbers line up on the decimal and read cleanly. */
input[inputmode="decimal"], input[inputmode="numeric"] {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
/* right-aligned numeric inputs sit 8px off the cell edge, same as figure
   headers and plain money cells, so values line up under their column head. */
table.grid td.figure input { text-align: right; padding-right: 8px; }
.figure-total { color: var(--figure-total); font-weight: 600;
  font-family: var(--font-display); font-size: 20px; }
.muted { color: var(--text-muted); }
.warn { color: var(--warning); }
.pos { color: var(--positive); }

/* a fixed 1.00 / 0.80 factor sits where the a–d slot picker would be, so it
   reads as "this is settled", not as a control you forgot to set */
.fixed-factor {
  display: inline-block; font-variant-numeric: tabular-nums;
  color: var(--text-secondary); font-size: 11.5px;
  border: 1px dashed var(--border); border-radius: 4px; padding: 1px 5px;
}

td.narrow, th.narrow { width: 64px; }
/* The point type is a select whose longest option is "ironmongery" — .narrow's
   64px cut it off. */
td.lib-type, th.lib-type { width: 122px; }

td.tiny, th.tiny { width: 40px; }
td.actions { white-space: nowrap; width: 70px; text-align: right; }

/* F&F editor swatch thumbnails — small, matching the quote-preview swatches.
   (The size is also set inline on each <img> so it holds even if an older
   app.css is cached.) */
td.ff-thumb { width: 76px; text-align: center; padding: 3px; }
td.ff-thumb img { max-height: 48px; max-width: 64px; border-radius: 3px;
                  background: #fff; vertical-align: middle; }

/* ── room editor layout ─────────────────────────────────────────────── */

.editor-layout { display: grid; grid-template-columns: 1fr 230px; gap: 18px;
                 align-items: start; }
#totals-panel { position: sticky; top: 16px; }
#totals-panel .panel { margin-bottom: 10px; }
.totals-row { display: flex; justify-content: space-between; padding: 3px 0; }
.totals-row.total { border-top: 1px solid var(--border-strong);
                    margin-top: 6px; padding-top: 8px; }

.elevation { margin-bottom: 20px; }
.elevation-head {
  display: flex; align-items: center; gap: 6px;
  background: var(--bg-raised);
  border: 1px solid var(--border-strong); border-bottom: none;
  border-radius: 4px 4px 0 0;
  padding: 5px 8px;
}
.elevation-head input.elev-name {
  background: transparent; border: none; font-weight: 600;
  letter-spacing: .04em; width: 280px;
}
/* set the factor (spec slot) for a whole wall at once */
.elev-slot { display: inline-flex; align-items: center; gap: 6px;
  margin-left: auto; font-size: 11px; color: var(--text-muted); }
.elev-slot > span { text-transform: uppercase; letter-spacing: .08em; }
.elev-slot select { padding: 3px 6px; height: 26px; font-size: 12px;
  min-width: 74px; }
/* per-elevation running total */
tr.elev-total td { border-top: 1px solid var(--border-strong);
  background: var(--bg-base); font-weight: 500; height: 30px; }
tr.elev-total td.muted { text-transform: uppercase; font-size: 10px;
  letter-spacing: .06em; }
/* the contingency pseudo-elevation: an elevation-styled block, dashed to read
   as "not a real wall" */
.contingency-elev table.grid { border-style: dashed; }
.contingency-elev .elevation-head { color: var(--text-muted); }
.contingency-elev input { background: var(--bg-input); }
/* per-line estimate surcharge: a compact % box + a note in a small dropdown,
   so a long reason has room and never runs over the grid column */
.surcharge-col { width: 96px; }
.surcharge-cell { white-space: nowrap; position: relative; }
.surcharge-pct-wrap { display: inline-flex; align-items: center; }
.surcharge-pct { width: 44px; text-align: right; }
.pct-sign { color: var(--text-muted); margin: 0 2px 0 3px; font-size: 11px; }
.note-pop { display: inline-block; margin-left: 4px; }
.note-pop > summary { list-style: none; cursor: pointer; font-size: 10.5px;
  color: var(--text-muted); padding: 2px 6px; border: 1px solid var(--border);
  border-radius: 10px; user-select: none; }
.note-pop > summary::-webkit-details-marker { display: none; }
.note-pop > summary.has { border-color: #E08A3C; color: #E7A567; }
.note-pop[open] > summary { border-color: var(--border-strong); }
.note-panel { position: absolute; right: 0; top: 100%; z-index: 40; width: 232px;
  margin-top: 5px; padding: 10px; text-align: left; white-space: normal;
  background: var(--bg-surface); border: 1px solid var(--border-strong);
  border-radius: 6px; box-shadow: 0 8px 24px rgba(0,0,0,.4); }
.note-panel label { display: block; font-size: 11px; color: var(--text-muted);
  margin-bottom: 5px; }
.note-panel textarea { width: 100%; resize: vertical; font-size: 12px; }
/* the orange badge that flags a line carrying a surcharge */
.pill-surcharge { display: inline-block; margin-top: 4px; padding: 1px 8px;
  border-radius: 10px; font-size: 9.5px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; background: #E08A3C; color: #2A2013; }
/* a value filled in for you (from another calculator) — read-only, not typed */
.autofilled { display: inline-block; padding: 3px 6px; border-radius: 3px;
  background: var(--bg-input); border: 1px dashed var(--border-strong);
  color: var(--text-muted); font-variant-numeric: tabular-nums; }
.elevation table.grid { background: var(--bg-surface);
  border: 1px solid var(--border); border-radius: 0 0 4px 4px; }

tr.entry-row td { background: var(--bg-input); }
/* the "add a line" row: box its fields so it clearly reads as where you start
   entering — an editable affordance, not a display row */
tr.entry-row td input, tr.entry-row td select {
  background: var(--bg-base); border: 1px solid var(--border);
  border-radius: 5px; height: 30px;
}
tr.entry-row td input:hover, tr.entry-row td select:hover,
tr.entry-row td input:focus, tr.entry-row td select:focus {
  border-color: var(--border-strong);
}

/* ── quote editor: compact summary rows + expandable detail ──────────── */

/* the summary line reads at a glance and never wraps into itself */
tr.qsummary td { vertical-align: middle; }
tr.qsummary.open td { background: var(--bg-hover); }
.qchev {
  font-size: 11px; color: var(--text-secondary); padding: 2px 4px; line-height: 1;
}
tr.qsummary.open .qchev { color: var(--accent); }
.qtitle { font-weight: 600; white-space: nowrap; overflow: hidden;
          text-overflow: ellipsis; max-width: 380px; }
.qsub { font-size: 11px; white-space: nowrap; overflow: hidden;
        text-overflow: ellipsis; max-width: 380px; }

/* status pill */
.pill { display: inline-block; font-size: 10px; text-transform: uppercase;
        letter-spacing: .04em; padding: 1px 7px; border-radius: 10px;
        border: 1px solid var(--border-strong); color: var(--text-muted); }
.pill-ok { color: var(--positive); border-color: var(--positive); }
.pill-warn { color: var(--warning); border-color: var(--warning); }

/* the expandable detail panel: a clean label/field grid, description last */
tr.qdetail > td { padding: 0; }
tr.qdetail:hover > td { background: inherit; }   /* no row-hover on the panel */
.qdetail-cell { background: var(--bg-input);
  border-left: 2px solid var(--accent); padding: 12px 16px 16px !important; }
.qdetail-grid { display: grid; grid-template-columns: 120px minmax(0, 460px);
  gap: 9px 14px; align-items: center; }
.qdetail-grid > label { color: var(--text-muted); font-size: 12px; }
.qdetail-grid input, .qdetail-grid select, .qdetail-grid textarea {
  width: 100%; background: var(--bg-base); border: 1px solid var(--border);
  border-radius: 5px; }
.qdetail-grid .full { grid-column: 1 / -1; }
.qdetail-grid .full > label { display: block; margin-bottom: 4px; }
.qdetail-grid textarea.qdesc { min-height: 66px; resize: vertical;
  line-height: 1.5; font: inherit; }
/* the generated half of a description: read-only, so it reads as settled
   rather than as a field somebody forgot to fill in */
.auto-desc { background: var(--bg-base); border: 1px solid var(--border);
  border-left: 2px solid var(--border-strong); border-radius: 5px;
  padding: 6px 9px; font-size: 12.5px; color: var(--text-secondary);
  line-height: 1.5; white-space: pre-wrap; }
.qcost-row, .qstatus-row { display: flex; align-items: center; gap: 10px;
  flex-wrap: wrap; }
.qcost-row input { width: 110px; }
.qstatus-row select { width: 130px; }
.qcode-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.qcode-row input { width: 160px; }
.qcode-row > div { flex-basis: 100%; }  /* the ✓ / not-found note on its own line */
.calc-primary { font-size: 11px; color: var(--accent); }
.tiny-note { font-size: 10px; color: var(--text-muted); }
/* semantic notes must beat the muted .tiny-note colour (declared later) */
.tiny-note.pos  { color: var(--positive); }
.tiny-note.warn { color: var(--warning); }

/* "Add a line" preset picker above the quote grid */
.add-preset { display: flex; margin: 0 0 12px; padding: 11px 14px;
  background: var(--bg-input); border: 1px solid var(--border); border-radius: 6px; }
.add-preset .inline-form { align-items: flex-end; gap: 12px; flex-wrap: wrap; }

/* accessories full-menu editor: chosen upgrades highlighted, dropped
   complimentary items dimmed so selections read at a glance */
tr.acc-on td { background: rgba(143, 166, 138, 0.10); }   /* sage tint = chosen */
tr.acc-off td strong { color: var(--text-muted); font-weight: 500; }
tr.acc-off td { opacity: 0.7; }
/* multi-line item rows: centre the qty/£ cells against the item block so the
   numbers sit level with their row rather than on the first text baseline */
#accessories-body table.grid td { vertical-align: middle; }

/* ── procurement ─────────────────────────────────────────────────────── */
.proc-summary { display: flex; gap: 18px; flex-wrap: wrap; margin: 10px 0 4px;
  padding: 10px 14px; background: var(--bg-surface);
  border: 1px solid var(--border-strong); border-radius: 8px; }
.proc-stat { color: var(--text-secondary); font-size: 12px; }
.proc-stat strong { color: var(--figure-total); font-size: 15px;
  font-variant-numeric: tabular-nums; }
.proc-stat-key strong { color: var(--positive); }

.proc-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px; }
.proc-card { display: block; text-decoration: none; color: var(--text-primary);
  background: var(--bg-surface); border: 1px solid var(--border-strong);
  border-radius: 10px; padding: 14px 16px; }
.proc-card:hover { background: var(--bg-hover); border-color: var(--accent); }
.proc-card-title { font-weight: 600; font-size: 15px; margin-bottom: 4px; }
.proc-card-stat { font-size: 12px; color: var(--text-secondary); margin-bottom: 8px; }
.proc-bar { height: 6px; background: var(--bg-input); border-radius: 3px; overflow: hidden; }
.proc-bar-fill { height: 100%; background: var(--positive); }

/* ── procurement: one card per item ─────────────────────────────────────
   Replaced a ten-column table. The table was legible if you already knew the
   column order and a wall if you did not, and a project manager working down
   thirty items had nothing separating one from the next.

   NB `.proc-card` above is a different thing -- the landing page's job card.
   The per-item card is `.proc-item-card`. */
/* The room heading, and it has to LEAD. The global h2 is 11px uppercase --
   the app's small section label -- and the supplier band under it was 11.5px,
   so the sub-header was literally larger than the thing it sat under and the
   hierarchy read backwards.
   Three clear steps now: the job title (h1.display, 34px), the room (15px,
   bone, ruled), the supplier (10.5px, muted). Still the app's own uppercase
   idiom rather than a new type style. */
h2.proc-room { font-size: 15px; letter-spacing: .1em;
  color: var(--figure-total); margin: 30px 0 12px;
  padding-bottom: 6px; border-bottom: 1px solid var(--border-strong); }
h2.proc-room:first-of-type { margin-top: 20px; }
/* the "· appliances" note and the progress count ride inside the heading and
   must not inherit its case or tracking */
h2.proc-room .muted { text-transform: none; letter-spacing: 0;
  font-weight: 400; font-size: 12.5px; }

.proc-list { display: flex; flex-direction: column; gap: 10px; }
.proc-list + .proc-supplier { margin-top: 18px; }

/* Who to order this handful from. A quiet band rather than a heading: the
   room is the heading, and the supplier is a divider inside it. */
.proc-supplier { display: flex; gap: 12px; align-items: baseline;
  justify-content: space-between; margin: 0 0 6px; padding: 0 2px 4px;
  border-bottom: 1px solid var(--border); }
.proc-supplier-name { font-size: 10.5px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-secondary); }
.proc-supplier-count { font-size: 11px; color: var(--text-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap; }

.proc-item-card {
  background: var(--bg-surface);
  border: 1px solid var(--border-strong);
  border-left: 3px solid var(--border-strong);
  border-radius: 8px;
  padding: 12px 14px;
}
.proc-item-card.has-notes { border-left-color: var(--warning); }
.proc-item-card.is-delivered { border-left-color: var(--positive);
  background: rgba(143, 166, 138, 0.05); }
.proc-item-card.is-delivered .proc-title { color: var(--positive); }

/* ── band 1: what is it ─────────────────────────────────────────────────── */
.proc-ic-head { display: flex; gap: 12px; align-items: flex-start; }
.proc-thumb { width: 58px; height: 58px; flex: none; object-fit: cover;
  border-radius: 5px; background: #fff; border: 1px solid var(--border); }
.proc-thumb-empty { background: var(--bg-input); border-style: dashed; }
.proc-item-body { min-width: 0; flex: 1 1 auto; }
.proc-title { font-weight: 600; font-size: 14px; line-height: 1.35; }
.proc-ref { display: inline-block; min-width: 1.4em; margin-right: 5px;
  color: var(--text-muted); font-weight: 400;
  font-variant-numeric: tabular-nums; }

/* the item's own detail typography. These rules predate the card layout and
   still apply to it unchanged -- the card changed the FRAME, not the way an
   item describes itself. */
.proc-link { text-decoration: none; }
.proc-meta { font-size: 11px; margin-top: 1px; }
.proc-code { font-family: var(--font-ui); color: var(--text-secondary);
  font-variant-numeric: tabular-nums; }
.proc-model { font-size: 12px; color: var(--text-primary); margin: 1px 0;
  font-variant-numeric: tabular-nums; }
.proc-prices { display: flex; gap: 12px; flex-wrap: wrap; margin: 3px 0 2px;
  font-size: 11px; color: var(--text-secondary); }
.proc-prices strong { color: var(--figure); font-variant-numeric: tabular-nums; }
.proc-desc { font-size: 11px; color: var(--text-muted); line-height: 1.4; }
.proc-attr { font-size: 11px; color: var(--text-secondary); line-height: 1.45; }
.proc-attr-k { color: var(--text-muted); }
.proc-components { font-size: 11px; margin-top: 3px; }
.proc-components summary { color: var(--accent); cursor: pointer; }
.proc-components ul { margin: 3px 0 0; padding-left: 16px;
  color: var(--text-secondary); }

/* the two figures, pinned right so they line up down the list */
.proc-figures { flex: none; display: flex; gap: 18px; text-align: right;
  padding-left: 10px; }
.proc-fig { display: flex; flex-direction: column; gap: 1px; }
.proc-fig .k { font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-muted); }
.proc-fig strong { font-size: 14px; font-variant-numeric: tabular-nums;
  color: var(--figure); }

/* ── band 2: where is it up to ──────────────────────────────────────────
   monday.com's pattern -- a solid filled block per stage, its name written
   in it, the whole block the click target -- in Krantz's palette, because
   BRAND.md says the semantic colours are muted and never saturated. The
   label carries the meaning; the fill just says done or not. */
.proc-ic-state { display: flex; gap: 14px; align-items: flex-end;
  flex-wrap: wrap; margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--border); }
.proc-statuses { display: flex; gap: 3px; flex: 1 1 380px; min-width: 260px; }

.proc-status {
  flex: 1 1 0; min-width: 0;
  height: 30px; padding: 0 6px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--bg-input);
  color: var(--text-muted);
  font: 500 11px/1 var(--font-ui, inherit);
  font-family: inherit;
  letter-spacing: .04em;
  cursor: pointer;
  transition: background .12s, color .12s, border-color .12s;
}
.proc-status-label { overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.proc-status.off:hover { background: var(--bg-hover);
  color: var(--text-secondary); border-color: var(--accent); }
.proc-status.on {
  background: var(--positive);
  border-color: var(--positive);
  /* the charcoal reads as ink on sage; bone on sage is too low a contrast */
  color: #26302A;
  font-weight: 600;
}
.proc-status.on:hover { filter: brightness(1.08); }
.proc-status:focus-visible { outline: 2px solid var(--accent);
  outline-offset: 1px; }

.proc-side { display: flex; gap: 12px; align-items: flex-end; flex: 0 1 auto; }
.proc-invoice-cell { display: flex; gap: 4px; align-items: center;
  white-space: nowrap; font-size: 12px; }
.proc-invoice-cell form { display: inline; }
.proc-upload { display: inline-flex; align-items: center; gap: 4px;
  height: 30px; padding: 0 10px; border: 1px solid var(--border-strong);
  border-radius: 4px; cursor: pointer; color: var(--text-secondary);
  font-size: 11.5px; white-space: nowrap; }
.proc-upload:hover { background: var(--bg-hover); color: var(--text-primary);
  border-color: var(--accent); }

.proc-loc-field { display: flex; flex-direction: column; gap: 2px; }
.proc-loc-field .k { font-size: 9.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-muted); }
.proc-loc-field input { width: 148px; height: 30px; }

/* ── band 3: what do I need to know ────────────────────────────────────── */
.proc-notes { display: block; margin-top: 10px; }
.proc-notes .k { display: block; font-size: 9.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-muted); margin-bottom: 3px; }
.proc-notes textarea {
  width: 100%; resize: vertical; min-height: 44px;
  font: inherit; font-size: 12.5px; line-height: 1.5;
  padding: 7px 9px;
  background: var(--bg-input); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 4px;
}
.proc-notes textarea:focus { outline: none; border-color: var(--accent); }
.proc-notes textarea::placeholder { color: var(--text-muted); }
/* written-in notes should be findable at a glance down a long list */
.proc-item-card.has-notes .proc-notes textarea { border-color: var(--warning);
  background: rgba(196, 166, 122, 0.07); }

@media (max-width: 900px) {
  .proc-ic-head { flex-wrap: wrap; }
  .proc-figures { padding-left: 0; }
  .proc-statuses { flex-basis: 100%; }
  .proc-side { flex-basis: 100%; }
}

.hint { color: var(--text-muted); font-size: 11px; margin: 6px 0 14px; }
kbd {
  background: var(--bg-raised); border: 1px solid var(--border-strong);
  border-radius: 3px; padding: 0 5px; font-size: 11px;
}

/* ── autocomplete ───────────────────────────────────────────────────── */

.ac-wrap { position: relative; }
.ac-list {
  position: absolute; z-index: 40; top: 100%; left: 0; min-width: 380px;
  background: var(--bg-surface);
  border: 1px solid var(--border-strong); border-radius: 4px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
  display: none; max-height: 300px; overflow-y: auto;
}
.ac-list.open { display: block; }
.ac-item {
  display: flex; gap: 10px; align-items: baseline;
  padding: 6px 10px; cursor: pointer;
  border-bottom: 1px solid var(--border);
}
.ac-item:last-child { border-bottom: none; }
.ac-item.active, .ac-item:hover { background: var(--bg-hover); }
.ac-code { font-weight: 600; min-width: 90px; }
.ac-desc { color: var(--text-secondary); flex: 1; }
.ac-meta { color: var(--text-muted); font-size: 11px; white-space: nowrap; }

/* ── job list ───────────────────────────────────────────────────────── */

.status-draft, .status-issued, .status-won, .status-lost {
  text-transform: capitalize; font-weight: 500; }
/* irreversible actions: outlined in clay, never a bare link. The solid button
   is deliberately the only saturated control in the app. */
.danger-zone { border-color: var(--danger); }
a.ghost-link-danger {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; margin-left: 4px;
  border: 1px solid var(--border); border-radius: 5px;
  color: var(--text-secondary); text-decoration: none !important;
  font-size: 13px; line-height: 1; vertical-align: middle;
}
a.ghost-link-danger:hover {
  color: var(--danger); border-color: var(--danger); background: var(--bg-hover);
}
button.danger-solid {
  background: var(--danger); color: #2B2A2E; border-color: var(--danger);
  font-weight: 600;
}
button.danger-solid:hover { background: #c98f8f; border-color: #c98f8f; }
button.danger-solid:focus { outline: 2px solid var(--accent); outline-offset: 2px; }

.status-draft { color: var(--text-secondary); }
.status-issued { color: var(--warning); }
.status-won { color: var(--positive); }
.status-lost { color: var(--danger); }

/* ── weekly focus board ─────────────────────────────────────────────────
   Laid out like the Monday board the design team already use: a row per
   project, each column a cell you change in place, and the status columns as
   solid filled blocks -- monday's pattern, Krantz's palette, for the reason
   set out in partials/procurement_row.html.

   WIDE, AND IT SCROLLS. Eleven columns will not fit a laptop, and squeezing
   them made every label truncate. So the columns get the width their contents
   need and the board scrolls sideways -- with the drag handle and the project
   name STUCK to the left as it does, because scrolling to Status and losing
   which project you are looking at is the one thing that makes a wide board
   useless.

   Three or four values per column, so the status cells are SELECTS filling
   their cell rather than buttons. `appearance: none` takes the arrow away so
   the cell reads as a block; it is still a select, so the keyboard and a
   screen reader get the real control.

   NO NOTES COLUMN and NO HANDOVER DEADLINE. Updates replaced the first (the
   old notes were moved onto the threads, not deleted); the estimator asked
   for the second to be left off. */
.wf-scroll { padding: 0; overflow-x: auto; overflow-y: visible; }
.wf-board { min-width: 1380px; }
.wf-board td { height: 46px; vertical-align: middle; }
.wf-board th { white-space: nowrap; }
.wf-board th.wf-updates-h  { width: 52px;  text-align: center; }
.wf-board th.wf-designer-h { width: 92px;  text-align: center; }
.wf-board th.wf-prio-h     { width: 140px; text-align: center; }
.wf-board th.wf-date-h     { width: 148px; text-align: center; }
.wf-board th.wf-check-h    { width: 100px; text-align: center; }
.wf-board th.wf-conf-h     { width: 152px; text-align: center; }
.wf-board th.wf-ver-h      { width: 86px;  text-align: center; }
.wf-board th.wf-stage-h    { width: 200px; text-align: center; }

/* ── the two columns that stay put ──────────────────────────────────────
   An opaque background is what makes them work: without it the scrolling
   columns slide visibly underneath. The right edge on the second is the
   seam, so it reads as a frozen pane rather than an overlap. */
.wf-stick-a, .wf-stick-b { position: sticky; z-index: 2;
  background: var(--bg-surface); }
.wf-stick-a { left: 0; width: 26px; }
.wf-stick-b { left: 26px; box-shadow: 8px 0 10px -8px rgba(0, 0, 0, .45); }
.wf-board thead .wf-stick-a, .wf-board thead .wf-stick-b { z-index: 3;
  background: var(--bg-raised); }
.wf-board tr:hover .wf-stick-a, .wf-board tr:hover .wf-stick-b {
  background: var(--bg-hover); }
/* the tinted rows need their tint on the frozen cells too, or the pane looks
   like it belongs to a different row */
.wf-row.wf-ready .wf-stick-a, .wf-row.wf-ready .wf-stick-b {
  background: #35373A; }
.wf-row.wf-done .wf-stick-a, .wf-row.wf-done .wf-stick-b {
  background: #313338; }

/* ── the project cell ───────────────────────────────────────────────────── */
.wf-name { min-width: 300px; }
.wf-title-input { font-size: 14.5px; font-weight: 600; width: 100%;
  background: transparent; border: none; padding: 3px 6px; border-radius: 4px;
  color: var(--text-primary); text-overflow: ellipsis; }
.wf-title-input:hover, .wf-title-input:focus { background: var(--bg-input); }
.wf-sub { display: flex; gap: 7px; align-items: center; flex-wrap: wrap;
  padding: 0 6px; font-size: 11px; color: var(--text-muted); }
.wf-chip { display: inline-flex; align-items: center; gap: 3px;
  padding: 1px 8px; border: 1px solid var(--border); border-radius: 10px;
  font-size: 10.5px; color: var(--text-secondary); text-decoration: none;
  white-space: nowrap; }
.wf-chip:hover { border-color: var(--accent); color: var(--text-primary);
  text-decoration: none; }
.wf-chip-x { background: none; border: none; color: var(--danger);
  cursor: pointer; font-size: 13px; line-height: 1; padding: 0 2px; }
.wf-row.wf-done .wf-title-input { color: var(--text-muted); }

/* ── designer avatar ────────────────────────────────────────────────────
   The avatar is what you read; the select sits invisibly over the whole cell
   so clicking the face opens the list. */
.wf-designer { text-align: center; padding: 0 !important; }
.wf-avatar-cell { position: relative; display: flex; align-items: center;
  justify-content: center; height: 46px; cursor: pointer; }
.wf-avatar-cell select { position: absolute; inset: 0; width: 100%;
  height: 100%; opacity: 0; cursor: pointer; }
.avatar-empty { background: var(--bg-input) !important;
  color: var(--text-muted) !important;
  border: 1px dashed var(--border-strong) !important; }

/* ── the status cells ───────────────────────────────────────────────────── */
.wf-cell { padding: 0 !important; }
.status-cell select {
  width: 100%; height: 46px; border: none; border-radius: 0;
  background: transparent; color: inherit;
  font: 600 12px/1 inherit; letter-spacing: .05em;
  text-align: center; text-align-last: center;
  padding: 0 10px; cursor: pointer;
  appearance: none; -webkit-appearance: none;
  /* the columns are wide enough now that this rarely fires -- but a long
     status on a narrow window should trail off rather than wrap a 46px cell */
  text-overflow: ellipsis; white-space: nowrap; overflow: hidden;
}
.status-cell select:focus-visible { outline: 2px solid var(--accent);
  outline-offset: -2px; }
.status-cell select option { background: var(--bg-surface);
  color: var(--text-primary); font-weight: 400; letter-spacing: 0; }

/* priority. Brass for urgent, sage for done, and the middle two stepped in
   opacity rather than given hues of their own -- BRAND.md allows three
   semantic colours and inventing a fourth for "medium" would be guessing. */
.prio-high     { background: rgba(196, 166, 122, .32); color: #E8D3AE; }
.prio-medium   { background: rgba(196, 166, 122, .17); color: var(--warning); }
.prio-low      { background: var(--bg-input); color: var(--text-secondary); }
.prio-complete { background: var(--positive); color: #23271F; }
.prio-none     { color: var(--text-muted); }

/* status */
.stage-design_in_progress  { background: rgba(196, 166, 122, .22); color: #E8D3AE; }
.stage-design_complete     { background: rgba(143, 166, 138, .24); color: #C4D6BF; }
.stage-floorplans_complete { background: rgba(143, 166, 138, .44); color: #DCE8D8; }
.stage-handed_over         { background: var(--positive); color: #23271F; }

/* meeting confirmed */
.conf-yes  { background: rgba(143, 166, 138, .32); color: #C4D6BF; }
.conf-no   { background: rgba(181, 127, 127, .24); color: #E0C0C0; }
.conf-none { color: var(--text-muted); }

.wf-board tr:hover td.status-cell { filter: brightness(1.1); }

/* ── the on/off cell, same control as the procurement cards ─────────────── */
.status-block { width: 100%; height: 46px; border: none; background: transparent;
  color: var(--text-muted); font: 600 12px/1 inherit; letter-spacing: .05em;
  cursor: pointer; }
.status-block.off:hover { background: var(--bg-hover);
  color: var(--text-secondary); }
.status-block.on { background: var(--positive); color: #23271F; }
.status-block:focus-visible { outline: 2px solid var(--accent);
  outline-offset: -2px; }

/* ── dates ──────────────────────────────────────────────────────────────── */
.wf-date input { width: 100%; height: 46px; background: transparent;
  border: none; color: var(--text-secondary); font: inherit; font-size: 12.5px;
  text-align: center; padding: 0 6px; }
.wf-date input:hover, .wf-date input:focus { background: var(--bg-input);
  color: var(--text-primary); }
/* a deadline that has gone past. The word is not available in a date cell, so
   the brass is working alone -- which BRAND.md would rather it did not. The
   inset bar and the cell's title are the other two signals. */
.wf-date.is-overdue input { color: var(--warning); font-weight: 600; }
.wf-date.is-overdue { box-shadow: inset 3px 0 0 var(--warning); }

/* ── version ────────────────────────────────────────────────────────────── */
.wf-version { text-align: center; }
.wf-ver { display: inline-block; padding: 2px 9px; border-radius: 10px;
  background: var(--bg-raised); border: 1px solid var(--border-strong);
  font-size: 11.5px; font-variant-numeric: tabular-nums;
  color: var(--text-primary); }

/* ── updates: the bubble and the panel ──────────────────────────────────
   monday.com's Updates, which the design team already use and rely on. The
   bubble carries the count; the panel is where the conversation happens. */
.wf-updates { text-align: center; padding: 0 !important; }
.wf-bubble { display: inline-flex; align-items: center; gap: 4px;
  background: none; border: none; cursor: pointer; padding: 5px 7px;
  border-radius: 6px; font: inherit; line-height: 1;
  color: var(--text-secondary); }
/* the icon is an inline SVG on currentColor -- see partials/icon_bubble.html
   for why it is not the emoji */
.ic-bubble { display: block; flex: none; }
.wf-bubble:hover { background: var(--bg-hover); }
.wf-bubble.is-empty { opacity: .34; }
.wf-bubble.is-empty:hover { opacity: 1; }
.wf-bubble-t { font-size: 10px; color: var(--text-muted);
  font-variant-numeric: tabular-nums; }
/* unread gets the brass AND the number -- never colour alone (BRAND.md) */
.wf-bubble-n { min-width: 15px; padding: 0 4px; border-radius: 8px;
  background: var(--warning); color: #2B2418; font-size: 10px;
  font-weight: 700; line-height: 15px;
  font-variant-numeric: tabular-nums; }
.wf-bubble.has-unread { color: var(--warning); }

.up-panel {
  position: fixed; right: 0; top: 0; bottom: 0; width: 430px; max-width: 92vw;
  z-index: 60; display: flex; flex-direction: column;
  background: var(--bg-surface);
  border-left: 1px solid var(--border-strong);
  box-shadow: -14px 0 34px rgba(0, 0, 0, .34);
}
.up-head { display: flex; align-items: flex-start; justify-content: space-between;
  gap: 10px; padding: 14px 16px; border-bottom: 1px solid var(--border);
  background: var(--bg-raised); }
.up-kicker { font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--text-muted); }
.up-title { font-size: 15px; font-weight: 600; color: var(--text-primary);
  margin-top: 2px; }
.up-close { background: none; border: none; color: var(--text-secondary);
  font-size: 22px; line-height: 1; cursor: pointer; padding: 0 4px; }
.up-close:hover { color: var(--text-primary); }

/* newest at the bottom, like a conversation. column-reverse would put it
   there for free but reverses the reading order for a screen reader, so the
   order is honest and the scroll is nudged instead. */
.up-thread { flex: 1 1 auto; overflow-y: auto; padding: 14px 16px;
  display: flex; flex-direction: column; gap: 14px; }
.up-msg { display: flex; gap: 10px; align-items: flex-start; }
.up-face { flex: none; }
.up-body { min-width: 0; flex: 1 1 auto; }
.up-meta { display: flex; gap: 8px; align-items: baseline; font-size: 11px;
  color: var(--text-muted); }
.up-meta strong { color: var(--text-primary); font-size: 12.5px;
  font-weight: 600; }
.up-when { font-variant-numeric: tabular-nums; }
.up-del { margin-left: auto; background: none; border: none;
  color: var(--text-muted); cursor: pointer; font-size: 13px; line-height: 1;
  padding: 0 3px; }
.up-del:hover { color: var(--danger); }
/* pre-line keeps the paragraphs somebody typed without letting markup in */
.up-text { white-space: pre-line; font-size: 13px; line-height: 1.55;
  color: var(--text-primary); margin-top: 2px;
  overflow-wrap: anywhere; }
.up-msg.is-mine .up-body { border-left: 2px solid var(--border-strong);
  padding-left: 9px; margin-left: -11px; }
.up-empty { color: var(--text-muted); font-size: 12.5px; line-height: 1.55;
  margin: 4px 0; }

.up-compose { border-top: 1px solid var(--border); padding: 12px 16px;
  background: var(--bg-base); }
.up-compose textarea { width: 100%; resize: vertical; min-height: 62px;
  font: inherit; font-size: 13px; line-height: 1.5; padding: 8px 10px;
  background: var(--bg-input); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 5px; }
.up-compose textarea:focus { outline: none; border-color: var(--accent); }
.up-compose-foot { display: flex; align-items: center;
  justify-content: space-between; gap: 10px; margin-top: 8px;
  font-size: 11px; }

@media (max-width: 620px) {
  .up-panel { width: 100%; border-left: none; }
}

/* ── notes (temporary; goes when Updates lands) ─────────────────────────── */
.wf-notes input { width: 100%; background: transparent; border: none;
  padding: 4px 6px; font-size: 12px; }
.wf-notes input:hover, .wf-notes input:focus { background: var(--bg-input); }

/* ── versions panel ─────────────────────────────────────────────────── */
.version-current { padding: 10px 12px; background: var(--bg-input);
  border-left: 2px solid var(--positive); border-radius: 4px; }
summary.version-archive { cursor: pointer; color: var(--text-secondary);
  font-size: 12px; padding: 4px 0; list-style-position: inside; }
summary.version-archive:hover { color: var(--accent-hover); }

/* ── additions & amends: chargeable-variation summary ───────────────── */
.amends-net { max-width: 440px; margin: 18px 0; padding: 12px 16px;
  background: var(--bg-surface); border: 1px solid var(--border-strong);
  border-radius: 8px; }
.amends-net .totals-row { padding: 4px 0; }

/* ── the home menu ─────────────────────────────────────────────────────────
   The front door. Quiet: one display-serif heading (BRAND.md allows the serif
   for a title, sparingly) and cards in --bg-surface. No gold on interactive
   chrome -- the accent is bone; brass stays reserved for the awaiting-price
   signal, which is why it appears on that figure and nowhere else here.
   ─────────────────────────────────────────────────────────────────────── */
.home-greeting { margin: 26px 0 22px; }
.home-hello {
  font-family: var(--font-display);
  font-size: 40px;
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: .01em;
  color: var(--text-primary);
  margin: 0;
}
.home-date {
  font-size: 13px;
  color: var(--text-muted);
  margin: 7px 0 0;
}

.home-branches {
  display: grid;
  /* one card sits at a readable width; a second lands beside it without any
     change here, which is the point of the grid */
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 14px;
  max-width: 860px;
}

.branch-card {
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 20px 22px 16px;
  text-decoration: none;
  color: inherit;
}
a.branch-card:hover {
  background: var(--bg-hover);
  border-color: var(--border-strong);
}
a.branch-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.branch-title {
  font-size: 17px;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0 0 6px;
}
.branch-blurb {
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-secondary);
  margin: 0 0 18px;
  flex: 1;
}
.branch-foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  border-top: 1px solid var(--border);
  padding-top: 12px;
}
.branch-stats { font-size: 12.5px; color: var(--text-muted); }
.branch-stats .figure { color: var(--text-primary); font-weight: 600; }
.branch-stats .figure.warn { color: var(--warning); }
.branch-sep { color: var(--border-strong); margin: 0 5px; }
.branch-go {
  font-size: 17px;
  color: var(--text-muted);
  line-height: 1;
}
a.branch-card:hover .branch-go { color: var(--accent-hover); }

.branch-card-soon { opacity: .55; }
.branch-card-soon .branch-title { color: var(--text-secondary); }

.home-note { font-size: 12px; margin: 20px 0 0; }

/* ── window navigation: Back, and the Menu link ─────────────────────────────
   There is no browser chrome around this app, so these are the only way to
   move backwards or reach the menu. Quiet, bone on hover -- no gold on
   interactive chrome (BRAND.md).
   ─────────────────────────────────────────────────────────────────────── */
.nav-back {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  margin-right: 2px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  line-height: 1;
  color: var(--text-secondary);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer;
  font-family: inherit;
}
.nav-back:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
  border-color: var(--border);
}
.nav-back:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* The menu sits a level above the section nav, so it reads as separate from
   the screens beside it rather than as another one of them. */
.topbar nav a.nav-menu {
  margin-right: 8px;
  padding-right: 14px;
  border-right: 1px solid var(--border-strong);
  border-radius: 6px 0 0 6px;
}

/* Read-only library cell: a member sees the value where an admin sees an
   input. Same alignment and size as the input it replaces, so the table does
   not reflow between the two roles. */
.ro { display: inline-block; padding: 3px 4px; color: var(--text-secondary);
  font-size: 12.5px; }
td.figure .ro, td.narrow .ro { display: block; text-align: right;
  font-variant-numeric: tabular-nums; }

/* ── "local data" ───────────────────────────────────────────────────────
   Shown in the topbar ONLY when this machine is not on the shared database,
   so the normal state says nothing at all. Clay, because it is a warning
   and not a decoration -- and the words carry it, never the colour alone
   (BRAND.md). */
.db-stamp { font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--danger); border: 1px solid var(--danger); border-radius: 10px;
  padding: 2px 9px; white-space: nowrap; cursor: help; }

/* A nav item you may see but not change. The words, not a colour alone
   (BRAND.md) -- and small, because it is a qualifier on a link, not a
   warning. */
.ro-tag { font-size: 9px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--text-muted); border: 1px solid var(--border-strong);
  border-radius: 8px; padding: 1px 5px; margin-left: 3px; vertical-align: 1px; }

/* ── the Access column on the Profiles screen ────────────────────────────
   Five areas per person, so a compact stack rather than five wide columns:
   the table already carries name, title, email, role, status and actions,
   and five more columns would push it off any screen. */
.access-cell { min-width: 210px; }
.access-grid { display: flex; flex-direction: column; gap: 2px; }
.access-row { display: grid; grid-template-columns: 84px 1fr; gap: 6px;
  align-items: center; }
.access-name { font-size: 11px; color: var(--text-secondary); }
/* `table.grid td select` above sets width: 100% and height: 31px, and at
   specificity (0,2,1) it outranks a bare `.access-grid select`. Five stacked
   pickers at 31px made the row tall enough to push the table wide, so match
   the specificity rather than fight it. */
table.grid td .access-grid select { font-size: 11.5px; padding: 2px 4px;
  height: auto; width: 100%; }
.access-grid button { margin-top: 5px; align-self: start; }

/* Approving a sign-up that asked for a retail partner login: the partner has
   to be chosen here, because a partner row without one reaches nothing. */
.approve-partner { display: flex; gap: 4px; align-items: center;
  margin-bottom: 4px; }
table.grid td .approve-partner select { font-size: 11.5px; padding: 2px 4px;
  height: auto; width: auto; min-width: 150px; }

/* ── The confirm dialog ─────────────────────────────────────────────────────
   Replaces window.confirm(), which in the desktop shell renders as a
   Microsoft Edge dialog: white, system-font, "127.0.0.1 says", and nothing
   to do with this app. Estimator, 2026-09-14: "can we change it to a pop up
   on the screen in the same style of the app".

   Dark chrome like every other working screen (BRAND.md) — this is app
   furniture, not client-facing output, so it takes --bg-surface and bone
   text and never the light quote palette. */

.kd-confirm-veil {
  position: fixed; inset: 0; z-index: 900;
  background: rgba(20, 19, 22, .62);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  /* A fade only — no scale or slide. A dialog that animates its way in
     delays the one thing the user is waiting to read. */
  animation: kd-confirm-veil-in .12s ease-out;
}
@keyframes kd-confirm-veil-in { from { opacity: 0 } to { opacity: 1 } }

.kd-confirm {
  background: var(--bg-surface);
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  box-shadow: 0 18px 48px rgba(0, 0, 0, .55);
  width: min(460px, 100%);
  padding: 22px 24px 18px;
  font-family: var(--font-ui);
  color: var(--text-primary);
}

.kd-confirm h2 {
  margin: 0 0 10px;
  font-family: var(--font-display);
  font-size: 21px; font-weight: 500; line-height: 1.25;
  color: var(--text-primary);
}

/* The paragraphs after the question — the consequence, usually. Secondary
   ink because the question is what must be read first. */
.kd-confirm p {
  margin: 0 0 10px;
  font-size: 13px; line-height: 1.5;
  color: var(--text-secondary);
}
.kd-confirm p:last-of-type { margin-bottom: 18px; }

.kd-confirm-actions {
  display: flex; gap: 8px; justify-content: flex-end; align-items: center;
}

/* Cancel sits left of the action and is the quieter of the two, but it is a
   real button with a real focus ring — it is the one people reach for when
   they have changed their mind mid-click. */
.kd-confirm-actions button { font-size: 13px; padding: 7px 16px; }

/* A destructive confirm gets the clay fill, matching .danger-solid
   elsewhere, so the button that deletes never looks like the button that
   saves. */
.kd-confirm.is-danger .kd-confirm-go {
  background: var(--danger); color: #2B2A2E; border-color: var(--danger);
}
.kd-confirm.is-danger .kd-confirm-go:hover {
  background: #c98f8f; border-color: #c98f8f;
}

@media (prefers-reduced-motion: reduce) {
  .kd-confirm-veil { animation: none; }
}

/* ── the retail partner catalogue picker ──────────────────────────────────
   Stage 11. Where a designer gets the code box, a partner gets this: one
   search field that grows into a result list and then a drawer. It replaces
   the entry row inside the elevation table, so it lives in a full-width cell
   and has to look like somewhere you start typing rather than a row of data.

   Nothing in here is a new colour. Same tokens as the rest of the app. */
tr.picker-row td { background: var(--bg-input); padding: 10px 12px; }

.picker-search {
  width: 100%; padding: 9px 12px; font-size: 13.5px;
  background: var(--bg-surface);
  border: 1px solid var(--border-strong); border-radius: 6px;
  color: var(--text-primary);
}
.picker-search::placeholder { color: var(--text-muted); }
.picker-search:focus { border-color: var(--accent); outline: none; }

.picker-note { margin: 9px 2px 0; font-size: 12px; color: var(--text-muted); }

/* results ------------------------------------------------------------- */
.picker-list { list-style: none; margin: 8px 0 0; padding: 0;
  max-height: 320px; overflow-y: auto;
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--bg-surface); }
.picker-list li + li { border-top: 1px solid var(--border); }
.picker-hit {
  display: flex; align-items: baseline; gap: 12px; width: 100%;
  padding: 9px 12px; text-align: left;
  background: none; border: 0; border-radius: 0;
  color: var(--text-primary); font-size: 13px; cursor: pointer;
}
.picker-hit:hover, .picker-hit:focus {
  background: var(--bg-hover); color: var(--accent-hover); outline: none; }
.picker-hit-name { flex: 1 1 auto; }
.picker-hit-meta { flex: 0 0 auto; font-size: 11.5px; color: var(--text-muted);
  font-variant-numeric: tabular-nums; }
.picker-hit-meta .dot { margin: 0 6px; }
.picker-hit-price { flex: 0 0 auto; min-width: 84px; text-align: right;
  font-size: 12px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums; }

/* recently used ------------------------------------------------------- */
.picker-chips { list-style: none; display: flex; flex-wrap: wrap; gap: 6px;
  margin: 6px 0 0; padding: 0; }
.picker-chip {
  padding: 5px 11px; font-size: 12px; cursor: pointer;
  background: var(--bg-surface); color: var(--text-secondary);
  border: 1px solid var(--border-strong); border-radius: 14px;
}
.picker-chip:hover { background: var(--bg-hover); color: var(--accent-hover);
  border-color: var(--accent); }

/* the drawer ---------------------------------------------------------- */
.picker-drawer { margin-top: 10px; padding: 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-strong); border-radius: 6px; }
.picker-drawer-head { display: flex; align-items: flex-start; gap: 10px; }
.picker-back { flex: 0 0 auto; padding: 2px 9px; cursor: pointer;
  background: none; border: 1px solid var(--border);
  color: var(--text-secondary); border-radius: 4px; }
.picker-back:hover { color: var(--accent-hover); background: var(--bg-hover); }
.picker-drawer-name { font-size: 14px; color: var(--text-primary); }
.picker-drawer-meta { font-size: 11.5px; color: var(--text-muted); margin-top: 2px;
  font-variant-numeric: tabular-nums; }
.picker-drawer-meta .dot { margin: 0 6px; }

.picker-form { display: flex; flex-wrap: wrap; align-items: flex-end;
  gap: 12px; margin-top: 12px; }
.picker-field { display: flex; flex-direction: column; gap: 3px; }
.picker-field > span { font-size: 10.5px; letter-spacing: .05em;
  text-transform: uppercase; color: var(--text-muted); }
.picker-field input, .picker-field select { width: 108px; }
.picker-qty input { width: 64px; }
.picker-static strong { padding: 7px 0; font-size: 13px;
  color: var(--text-secondary); font-variant-numeric: tabular-nums; }

/* the live price, and its working ------------------------------------- */
.picker-price { flex: 1 1 260px; min-width: 260px; }
.picker-priced { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.picker-figure strong { font-size: 19px; color: var(--figure-total);
  font-variant-numeric: tabular-nums; }
.picker-figure .muted { margin-left: 6px; font-size: 12px; }
.picker-working { flex: 1 1 220px; font-size: 11.5px; line-height: 1.5;
  color: var(--text-muted); }
.picker-add { flex: 0 0 auto; }
.pill-made { display: inline-block; margin-right: 6px; padding: 1px 8px;
  border-radius: 10px; font-size: 9.5px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; background: var(--warning); color: #2A2013; }

/* a refusal is a route, not a dead end: it reads as information, not alarm */
.picker-refusal { padding: 9px 11px; border-radius: 5px;
  background: var(--bg-input); border: 1px solid var(--border-strong); }
.picker-refusal-msg { margin: 0; font-size: 12.5px; line-height: 1.55;
  color: var(--text-secondary); }
.picker-refusal-alt { display: flex; flex-wrap: wrap; align-items: center;
  gap: 6px; margin: 8px 0 0; font-size: 11.5px; color: var(--text-muted); }
.picker-alt { padding: 3px 10px; font-size: 11.5px; cursor: pointer;
  background: var(--bg-surface); color: var(--text-primary);
  border: 1px solid var(--border-strong); border-radius: 12px;
  font-variant-numeric: tabular-nums; }
.picker-alt:hover { border-color: var(--accent); color: var(--accent-hover);
  background: var(--bg-hover); }

/* the bespoke form: one wide field for the description, the rest narrow */
.picker-bespoke .picker-wide { flex: 1 1 320px; }
.picker-bespoke .picker-wide input { width: 100%; }
/* the row just priced on the bespoke queue, so the eye finds its place again */
tr.just-saved td { background: var(--bg-hover); }
/* a bespoke line where a catalogue line shows its code */
.pill-bespoke { display: inline-block; padding: 2px 9px;
  border-radius: 10px; font-size: 9.5px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; background: var(--bg-raised);
  color: var(--text-secondary); border: 1px solid var(--border-strong); }
