/*
  FenceCalc Pro — visual system, design spec §2.

  The one rule that carries meaning rather than taste: a tinted background means you can
  change the thing. Pale blue = you type here. Pale tan = an override, blank means the auto
  figure stands. Beige = a result carried in from elsewhere. Untinted = calculated, and
  there is nothing to click. Nothing else in the product gets a background tint, because an
  estimator scanning for "what can I change?" is scanning for colour and that scan must
  never mislead.

  Fonts are named with fallbacks and never fetched. This app is used standing on remote WA
  sites with no signal; a webfont request that hangs would take the type with it.
*/

:root {
  --ink:   #14201F;
  --navy:  #1B4965;
  --deep:  #0E2A3B;
  --teal:  #8FD1E3;
  --tan:   #B99C6B;
  --steel: #51636B;
  --mute:  #7A8C93;
  --rust:  #A8532C;
  --ok:    #1B7A5A;

  --page:  #F5F1E9;
  --card:  #FFFFFF;
  --band:  #EDE7DB;
  --zebra: #F8F6F1;
  --input: #F7FBFC;  /* you type here */
  --over:  #FBF7EF;  /* an override */
  --alarm: #FDF4EE;

  --line:  rgba(20,32,31,0.14);
  --line-strong: rgba(20,32,31,0.22);

  --sans: "IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --head: "Big Shoulders Display", "IBM Plex Sans Condensed", var(--sans);
  /* The wordmark only. Archivo 900 is the brand's own letterform and is used for the
     product name in the masthead and nowhere else — a display face doing a second job
     stops being a signature. */
  --word: "Archivo", var(--sans);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font: 13px/1.45 var(--sans);
  -webkit-text-size-adjust: 100%;
}

/* every number, code and label is mono with tabular figures, so columns align */
.mono, .sheet, .data, input, select, .ref, .status, .toggle-sub {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

h2 {
  font: 800 30px/1 var(--head);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--deep);
  margin: 0;
}
.sub { color: var(--steel); font-size: 12px; margin: 6px 0 16px; }

/* ---------------------------------------------------------------- chrome */

.chrome {
  position: sticky;
  top: 0;
  /* Above the page, below the fixed save bar at 20 — the bar reports unsaved work and must
     never be covered by chrome the estimator is scrolling under. */
  z-index: 15;
}

.masthead {
  background: var(--deep);
  color: var(--page);
  padding: 10px 18px;
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
}
/* Mark and wordmark on one baseline. The mark is optical-centred against cap height
   rather than the line box, which is why it sits 1px high. */
.masthead-name { display: flex; align-items: center; gap: 10px; }
.masthead-name img { display: block; margin-top: -1px; }
.wordmark { font: 900 19px/1 var(--word); letter-spacing: -0.02em; color: var(--page); }
/* "Pro" in teal — the one place the accent carries meaning rather than decoration.
   No trademark symbol: Bevan holds an ASIC-registered business name, which is not a
   registered trademark, and the mockup's "™" would have asserted one on every screen. */
.wordmark span { color: var(--teal); }
.masthead-sub { font-family: var(--mono); font-size: 10px; color: var(--teal); opacity: 0.85; }

/* The rail sits on navy and is chrome, not content — it reads as part of the masthead
   rather than as the first row of the page. Values from the 8 August design brief. */
.tabs {
  display: flex;
  align-items: stretch;
  gap: 0;
  padding: 0 14px 0 10px;
  background: var(--deep);
  border-bottom: 1px solid rgba(143, 209, 227, 0.18);
  /* Deliberately NOT `overflow-x: auto` any more. Scrolling belongs to `.tab-group` so the
     totals and save control stay pinned; scrolling the whole rail took them away with it. */
}

/* Only the tabs scroll. `min-width: 0` is what makes it work — a flex child will not shrink
   below its content without it, so `overflow-x` alone leaves the rail over-wide and pushes
   the page into a horizontal scroll at laptop widths. */
.tab-group {
  display: flex;
  gap: 2px;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: thin;
}
.tab {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  background: none;
  border: 0;
  border-bottom: 3px solid transparent;
  color: #7E96A3;
  padding: 14px 16px 11px;
  min-height: 44px;          /* used in the field, on a phone */
  white-space: nowrap;
  cursor: pointer;
}
/* The screen number reads as an index, not a second label — dimmer than the name it
   precedes. The old `--tan` was picked for a cream rail and is close to unreadable on navy. */
.tab i { font-style: normal; color: #5E7C8C; margin-right: 5px; }
.tab:hover { color: var(--page); background: rgba(143, 209, 227, 0.07); }
.tab.is-active {
  color: var(--teal);
  border-bottom-color: var(--teal);
  background: rgba(143, 209, 227, 0.12);
}
.tab.is-active i { color: var(--teal); opacity: 0.7; }

/* The running total, pinned to the right of the rail. Outside `.tab-group`, so the tabs
   scroll underneath it rather than carrying it off-screen — which is the whole reason that
   group exists. `[hidden]` must beat the flex display, exactly as `.savebar[hidden]` does:
   `display:flex` on an element carrying the attribute wins over the UA stylesheet, and that
   cost a permanently visible save bar to learn once already. */
.rail-total { display: flex; align-items: center; gap: 14px; margin-left: auto;
  padding-left: 16px; white-space: nowrap; }
.rail-total[hidden] { display: none; }
.rt-cell { text-align: right; }
.rt-label { font-family: var(--mono); font-size: 8.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: #7E96A3; }
.rt-value { font-family: var(--mono); font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums; line-height: 1.15; }
/* Ex in teal, Inc in cream — the inc-GST figure is the one a client sees, so it carries the
   higher-contrast colour rather than the accent. */
.rt-ex { color: var(--teal); }
.rt-inc { color: var(--page); }
.rt-divider { width: 1px; align-self: stretch; margin: 6px 0;
  background: rgba(143, 209, 227, 0.25); }

/* ---------------------------------------------------------------- save modes (spec 06) */

/* Pushed to the right of the eleven tabs, on the same strip. `margin-left: auto` rather
   than a fixed position: the strip scrolls horizontally on a phone and the control has to
   scroll with it rather than sit on top of a tab. */
.savemode {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
  padding-left: 12px;
  white-space: nowrap;
}
.svm-mode {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: none;
  color: #7E96A3;
  border: 1px solid rgba(143, 209, 227, 0.22);
  border-radius: 2px;
  padding: 0 8px;
  min-height: 44px;
  cursor: pointer;
}
/* On the navy rail, the old navy-on-cream fill vanished into the ground and `--line`
   (ink at 14%) was invisible against it. Teal is the rail's own affordance colour. */
.svm-mode.is-on { background: rgba(143, 209, 227, 0.16); border-color: var(--teal);
  color: var(--teal); }
.save-chip {
  font-family: var(--mono);
  font-size: 9.5px;
  color: var(--ok);
  margin-left: 6px;
}
/* Rust, not green: the point of the chip in manual mode is that work is not stored yet. */
.save-chip.is-dirty { color: var(--rust); }

/* `display: flex` on an element that also carries the `hidden` attribute wins over the UA
   stylesheet's `[hidden] { display: none }` — author styles beat user-agent ones — so the
   bar sat on screen permanently, over every screen, claiming unsaved changes that did not
   exist. Caught by the e2e suite, invisible to every source-level check. */
.savebar[hidden] { display: none; }

.savebar {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: min(560px, calc(100vw - 36px));
  padding: 12px 14px;
  background: var(--deep);
  border: 1px solid var(--tan);
  border-radius: 2px;
  box-shadow: 0 6px 20px rgba(20, 32, 31, 0.28);
}
.savebar-text { font-size: 11px; color: var(--page); line-height: 1.45; }
.savebar-text strong { display: block; font-size: 11.5px; }
.savebar-text span {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--teal);
  overflow-wrap: anywhere;
}
.svm-btn {
  font-family: var(--mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  background: none;
  color: var(--page);
  border: 1px solid var(--line-strong);
  border-radius: 2px;
  padding: 0 12px;
  min-height: 44px;
  cursor: pointer;
}
.svm-btn:hover { border-color: var(--tan); }

/* ---------------------------------------------------------------- screen width policy
   Section 2 of the 8 August design brief. Three surface kinds, per-screen caps, **all
   centred** — nothing edge-to-edge, and a wide monitor gets balanced margins rather than a
   column pinned to the left.

   The caps were already right and matched the mockup's screen roots exactly; the centring
   was what was missing. At 1920 `main` sat hard against the left edge with 340px of dead
   space on the right, which is the shape of an application that has outgrown its window
   rather than one designed for it.

   Values read out of `FenceCalc Pro v2.dc.html`'s screen roots, not chosen from a range:
     documents      830   (03 Client_Quote, 08 Monthly_Report)
     forms         1080   (04 Pre_Send_Check)
                   1180   (05 Rules)
                   1240   (07 Time_Saved)
     tables        1320   (09 Price_Onboarding, 10 SSOT_Gates)
                   1580   (02 Material_Callup — the global cap)
     uncapped      00 Site_Markup, 01 Input_Quote, 06 Job_Tracker

   The last row is the finding worth keeping: the brief summarises working tables as "cap
   1600px", and the mockup does not. 02 is 1580, 09 and 10 are 1320, and 06 has no cap at
   all — its root is `padding: 20px 26px 70px` and nothing else. 01 is not a capped form
   either: it is a three-column grid (`minmax(320px,1fr) minmax(300px,0.95fr)
   minmax(400px,1.3fr)`) that is meant to use the window. Four disagreements with the
   brief's own summary, resolved in the mockup's favour on Bevan's instruction. */
main { padding: 18px; max-width: 1580px; margin-inline: auto; }
.screen { display: none; }
.screen.is-active { display: block; }

:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }

/* ---------------------------------------------------------------- cards */

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-top: 3px solid var(--navy);
  border-radius: 2px;
  margin-bottom: 16px;
}
.card-head {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--rust);
  padding: 10px 12px 0;
}
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 10px;
  padding: 12px;
}
label { display: block; font-size: 11px; color: var(--steel); }
.ref { color: var(--tan); font-size: 9.5px; margin-left: 5px; }

/* Push buttons for the two- and three-way job settings (B15/B16). A select hides its options
   until opened and takes two taps; these take one and show both choices at rest. The chosen
   one carries the navy fill the tab strip uses for "this is the active thing". */
.push { display: flex; gap: 4px; margin-top: 4px; }
.push-btn {
  flex: 1 1 auto;
  font-family: var(--mono); font-size: 11px;
  background: var(--input); color: var(--navy);
  border: 1px solid var(--line-strong); border-radius: 2px;
  padding: 0 10px; min-height: 32px; cursor: pointer;
}
.push-btn.is-on { background: var(--navy); border-color: var(--navy); color: var(--page); }
.push-btn:hover:not(.is-on) { border-color: var(--navy); }

/* Spec 09 §3 — SPACING OVERRIDE ACTIVE. Rust, because a changed spacing multiplies through
   every post count below it and a silent change is the thing being guarded against. It sits
   under the field it describes rather than in a status bar somewhere else on the screen. */
.flag {
  display: block;
  margin-top: 4px;
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--rust);
}

input, select {
  display: block;
  width: 100%;
  margin-top: 4px;
  background: var(--input);            /* you type here */
  border: 1px solid var(--line-strong);
  border-radius: 2px;
  padding: 6px 9px;
  font-size: 12px;
  color: var(--navy);
  min-height: 32px;
}
input[type="number"] { text-align: right; }

.note { font-size: 11px; color: var(--steel); padding: 0 12px 12px; margin: 0; }

.bar { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; }
.btn {
  background: var(--navy); color: #fff; border: 0; border-radius: 2px;
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase;
  padding: 0 16px; min-height: 44px; cursor: pointer;
}
.btn:hover { background: var(--deep); }
.status { font-size: 11px; color: var(--steel); }
.status.is-bad { color: var(--rust); }
.status.is-ok { color: var(--ok); }

.notbuilt {
  margin: 0 0 16px;
  padding: 14px 16px;
  background: var(--card);
  border: 1px solid var(--line);
  border-left: 3px solid var(--tan);
  border-radius: 2px;
  font-size: 12px;
  color: var(--steel);
}
.notbuilt code { font-family: var(--mono); font-size: 11px; color: var(--navy); }

.scroll { overflow-x: auto; }   /* wide tables scroll themselves, never the page */

/* ---------------------------------------------------------------- schedule */

table.data { width: 100%; border-collapse: collapse; font-size: 11.5px; }
table.data th {
  background: var(--navy); color: var(--page);
  font-size: 9.5px; letter-spacing: 0.07em; text-transform: uppercase;
  text-align: left; padding: 7px 9px; font-weight: 600;
}
table.data td { padding: 6px 9px; border-bottom: 1px solid var(--line); }
table.data tr:nth-child(even) td { background: var(--zebra); }
table.data td.num { text-align: right; }
table.data td.warn { color: var(--rust); }

/* The `merged` badge (spec §4.2). Inline beside the description, never a column of its own:
   it belongs to that one line, and a column would print blank on every line that did not
   merge. Tan is the reference colour throughout; rust means escalation put a post here. */
.badge {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 5px;
  border: 1px solid var(--tan);
  border-radius: 2px;
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--tan);
  white-space: nowrap;
}
.badge.is-escalated { border-color: var(--rust); color: var(--rust); background: var(--alarm); }

/* ---------------------------------------------------------------- the costing sheet */

/*
  A real grid: column letters across the top, row numbers down the left, a hairline on every
  cell. It is not styled to look designed — it is styled to look like the workbook, because
  that is what makes it trustworthy to the two people who use it.
*/
table.sheet {
  border-collapse: collapse;
  font-size: 11.5px;
  min-width: 900px;
}
table.sheet td, table.sheet th {
  border: 1px solid var(--line);
  padding: 3px 7px;
  height: 24px;
  vertical-align: middle;
  white-space: nowrap;
}
table.sheet th.rownum, table.sheet th.colhead {
  background: var(--band);
  color: var(--steel);
  font: 600 9.5px/1 var(--mono);
  text-align: center;
  width: 34px;
}
table.sheet th.colhead { height: 20px; }

tr.h-blank td, tr.h-blank th { height: 20px; }
tr.h-spacer td, tr.h-spacer th { height: 10px; padding: 0; }
tr.h-band td { height: 28px; }

/* the six cell kinds --------------------------------------------------- */

.k-label   { color: var(--ink); }
.k-bold    { color: var(--deep); font-weight: 600; }
.k-formula { color: var(--deep); text-align: right; }        /* calculated: no chrome */
.k-working { color: var(--deep); text-align: right; font-weight: 600; }
.k-sell    { color: var(--deep); text-align: right; font-weight: 700; font-size: 13.5px; }

.k-percent input { display: inline-block; width: calc(100% - 14px); }
.k-percent-unit { font-family: var(--mono); font-size: 11px; color: var(--steel); margin-left: 3px; }

.k-number input, .k-text input, .k-override input, .k-percent input {
  margin: 0; min-height: 20px; padding: 2px 5px; font-size: 11.5px;
  border: 1px solid var(--line-strong); border-radius: 2px;
}
.k-number input, .k-override input, .k-percent input { text-align: right; }
.k-text input { text-align: left; }
.k-number input, .k-percent input { background: var(--input); }   /* you type here */
.k-text   input { background: var(--input); }
.k-override input { background: var(--over); }  /* an override; blank = auto stands */
.k-override input::placeholder { color: var(--mute); font-style: normal; }

/* Hand-entered lines, under the grid rather than inside it — they have no workbook row.
   No tint anywhere in this block: it is read-only, and a tint promises otherwise. */
#sheet_manual { border-top: 1px solid var(--line-strong); margin-top: 14px; padding-top: 12px; }
.sheet-manual-head {
  font: 600 10px/1 var(--mono); letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--deep); margin-bottom: 4px;
}
.sheet-manual-why { font-size: 11px; color: var(--mute); margin: 0 0 10px; max-width: 640px; }
table.sheet-manual { border-collapse: collapse; font-size: 11.5px; width: 100%; }
table.sheet-manual th, table.sheet-manual td {
  border: 1px solid var(--line); padding: 3px 7px; height: 24px; text-align: left;
}
table.sheet-manual thead th {
  background: var(--band); color: var(--steel);
  font: 600 9.5px/1 var(--mono); letter-spacing: 0.05em; text-transform: uppercase;
}
table.sheet-manual .num { text-align: right; white-space: nowrap; }
table.sheet-manual tfoot th { text-align: right; color: var(--deep); font-weight: 600; }
table.sheet-manual tfoot td { text-align: right; color: var(--deep); font-weight: 700; }

.k-band {
  background: var(--band);
  font: 600 10px/1 var(--mono);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--deep);
}
.k-warning {
  background: var(--alarm);
  color: var(--rust);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.04em;
}


/* rust description = the gate width forced a post-size escalation */
.is-alert { color: var(--rust); }

/* a right-aligned label absorbs the empty cells to its left, as in Excel */
.spill { text-align: right; }

@media (max-width: 700px) {
  main { padding: 12px; }
  h2 { font-size: 24px; }
}

/* ---------------------------------------------------------------- client quote */

/*
  The document is a centred 830px sheet on the bone page — visibly a document, not an app
  screen. The screen heading sits outside it so it does not print.
*/
.cq-wording-tools { max-width: 830px; margin: 0 auto 18px; }

.cq-section {
  background: var(--card);
  border: 1px solid var(--line);
  border-left: 3px solid var(--navy);
  border-radius: 2px;
  margin-bottom: 10px;
  padding: 10px 12px;
}
.cq-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.cq-head h3 {
  font: 800 15px/1 var(--head);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--deep);
  margin: 0;
}
.cq-toggle {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase;
  background: none; border: 1px solid var(--line-strong); border-radius: 2px;
  color: var(--steel); padding: 0 10px; min-height: 44px; cursor: pointer;
}
.cq-toggle.is-open { background: var(--band); color: var(--deep); }

.cq-tools { border-top: 1px solid var(--line); margin-top: 8px; padding-top: 8px; }
.cq-step {
  display: block; font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--rust); margin-bottom: 3px;
}
.cq-pick { display: block; margin-bottom: 8px; }
.cq-preview-row { margin-bottom: 8px; }
.cq-preview {
  background: var(--band);              /* a result carried in, not something you type */
  border-radius: 2px;
  margin: 0;
  padding: 8px 10px;
  font-size: 12px;
  min-height: 34px;
  color: var(--ink);
}
.cq-copy {
  margin-top: 6px;
  font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em;
  background: none; border: 1px solid var(--line-strong); border-radius: 2px;
  color: var(--navy); padding: 0 10px; min-height: 44px; cursor: pointer;
}
.cq-final { display: block; }
.cq-final textarea {
  display: block; width: 100%; margin-top: 4px;
  background: var(--input);             /* you type here */
  border: 1px solid var(--line-strong); border-radius: 2px;
  padding: 6px 9px; font: 12px/1.45 var(--sans); color: var(--navy);
}

.cq-sheet {
  max-width: 830px;
  margin: 0 auto;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 26px 30px 30px;
}
/* The quote header — three bands, each two columns. **No width or height declaration
   anywhere**: the document runs to however many pages its content needs, and the print block
   is tested for exactly that. `minmax(0, 1fr)` rather than `1fr` so a long address wraps
   instead of pushing the grid wider than the page. */
.cq-band {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, auto); gap: 8px 24px;
  align-items: start; margin: 0 0 14px;
}
.cq-band-r { text-align: right; }
.cq-band p { margin: 0; font-size: 11.5px; line-height: 1.55; color: var(--steel); }
.cq-band-head {
  margin: 0 0 4px; font: 600 10px/1 var(--mono); letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--steel);
}
.cq-identity { padding-bottom: 12px; border-bottom: 1px solid var(--line); }
.cq-business {
  font: 700 18px/1.2 var(--head) !important; letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--ink) !important; margin-bottom: 4px !important;
}
.cq-band-r .cq-meta { grid-template-columns: auto auto; justify-content: end; margin: 0; }
.cq-scope { display: block; }
.cq-scope p { color: var(--ink); }

/* One column on a narrow screen. The right column stops being right-aligned there, because a
   right-aligned block under a left-aligned one reads as two unrelated things. */
@media (max-width: 620px) {
  .cq-band { grid-template-columns: minmax(0, 1fr); }
  .cq-band-r { text-align: left; }
  .cq-band-r .cq-meta { justify-content: start; }
}
.cq-sheet-head h3 {
  font: 800 26px/1 var(--head); letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--deep); margin: 0 0 10px;
}
.cq-meta { display: grid; grid-template-columns: auto 1fr; gap: 2px 12px; margin: 0 0 18px; }
.cq-meta dt { font-family: var(--mono); font-size: 10px; text-transform: uppercase;
              letter-spacing: 0.05em; color: var(--steel); }
.cq-meta dd { margin: 0; font-size: 12px; }

table.cq-lines { width: 100%; border-collapse: collapse; }
table.cq-lines th {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--steel); text-align: left; border-bottom: 1px solid var(--line-strong);
  padding: 6px 6px;
}
table.cq-lines td { padding: 7px 6px; vertical-align: top; font-size: 12.5px; }
table.cq-lines th.num, table.cq-lines td.num {
  text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums;
}
.cq-breakdown, .cq-wording { font-size: 11.5px; color: var(--steel); padding-top: 0 !important; }
.cq-breakdown { font-family: var(--mono); font-size: 10.5px; }

/* A section heading inside the lines table — one per fence type, per off-catalogue block, and
   the job-level block last. It reads as a divider rather than as a line item, because a row
   with no figures beside it would otherwise look like a line someone forgot to price. */
td.cq-page-head {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--deep); font-weight: 600;
  padding-top: 16px !important; padding-bottom: 4px !important;
  border-bottom: 1px solid var(--line);
}
table.cq-lines tbody tr:first-child td.cq-page-head { padding-top: 6px !important; }

.cq-totals {
  display: grid; grid-template-columns: 1fr auto; gap: 4px 16px;
  margin: 14px 0 0; padding-top: 10px; border-top: 1px solid var(--line-strong);
}
.cq-totals dt { font-size: 12.5px; text-align: right; }
.cq-totals dd {
  margin: 0; font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 12.5px; text-align: right;
}
.cq-totals .is-total { font-weight: 700; font-size: 14px; color: var(--deep); }

.cq-blocked {
  max-width: 830px; margin: 0 auto; padding: 14px 16px;
  background: var(--alarm); border: 1px solid var(--rust); border-radius: 2px;
  color: var(--rust); font-size: 12px;
}

/* ---------------------------------------------------------------- pre-send check */

.presend { max-width: 1080px; margin-inline: auto; }

.ps-banner {
  background: var(--alarm); border: 1px solid var(--rust); border-radius: 2px;
  color: var(--rust); font: 700 12px/1 var(--mono); letter-spacing: 0.04em;
  padding: 12px 14px; margin-bottom: 12px;
}
.ps-banner.is-ok { background: #EFF6F2; border-color: var(--ok); color: var(--ok); }

.ps-list { background: var(--card); border: 1px solid var(--line); border-radius: 2px; }

.ps-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 12px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--line);
}
.ps-row:last-child { border-bottom: 0; }
/* A failing row takes the alarm ground so the eye lands on it without reading. */
.ps-row.is-bad { background: var(--alarm); }

.ps-name { font-size: 13px; color: var(--ink); font-weight: 600; }
.ps-cell {
  font-style: normal; font-family: var(--mono); font-size: 9.5px; color: var(--tan);
}
.ps-verdict {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.06em;
  color: var(--ok); text-align: right; white-space: nowrap;
}
.ps-row.is-bad .ps-verdict { color: var(--rust); }
/* The substance: the figures that produced the verdict, never a generic message. */
.ps-detail {
  grid-column: 1 / -1; margin: 0;
  font-family: var(--mono); font-size: 11px; color: var(--steel);
}
.ps-row.is-bad .ps-detail { color: var(--rust); }

/* ---------------------------------------------------------------- rules (05) */

.rules { max-width: 1180px; margin-inline: auto; }

.rules-block { margin-bottom: 24px; }
.rules-block h3 {
  font: 800 20px/1 var(--head); letter-spacing: 0.02em; text-transform: uppercase;
  color: var(--deep); margin: 0 0 4px;
}
.rules-sub { color: var(--steel); font-size: 12px; margin: 0 0 12px; max-width: 78ch; }

.rules-layers { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 12px; }
.rules-layer {
  background: var(--card); border: 1px solid var(--line); border-top: 3px solid var(--navy);
  border-radius: 2px; padding: 12px;
}
.rules-chip {
  display: inline-block; font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--page); background: var(--navy);
  border-radius: 2px; padding: 2px 6px;
}
.rules-layer h4, .rules-rule h4, .rules-source-row h4 {
  font: 600 13px/1.3 var(--sans); color: var(--deep); margin: 8px 0 4px;
}
.rules-what { font-size: 12px; color: var(--ink); margin: 0 0 8px; }
.rules-facts { margin: 0; padding-left: 16px; }
.rules-facts li { font-family: var(--mono); font-size: 10.5px; color: var(--steel); margin-bottom: 3px; }

.rules-rule, .rules-source-row {
  background: var(--card); border: 1px solid var(--line); border-left: 3px solid var(--tan);
  border-radius: 2px; padding: 10px 12px; margin-bottom: 8px;
}
.rules-rule h4 { margin-top: 0; }
.rules-statement { font-size: 12.5px; margin: 0 0 6px; color: var(--ink); }
.rules-because { font-size: 12px; margin: 0 0 6px; color: var(--steel); }
.rules-source, .rules-detail {
  font-family: var(--mono); font-size: 10px; color: var(--mute); margin: 0;
}

table.rules-truth { border-collapse: collapse; font-size: 11.5px; min-width: 720px; }
table.rules-truth th {
  background: var(--navy); color: var(--page); font-size: 9.5px; letter-spacing: 0.06em;
  text-transform: uppercase; text-align: left; padding: 7px 9px; font-weight: 600;
}
table.rules-truth td { padding: 6px 9px; border-bottom: 1px solid var(--line); }
table.rules-truth td.num {
  text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums;
}
/* A state that does nothing on this rail configuration. Not an error — a rule. */
table.rules-truth tr.is-inert td { background: var(--zebra); color: var(--mute); }
.rules-note { font-family: var(--mono); font-size: 10px; color: var(--mute); }

.rules-status {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--rust); border: 1px solid currentColor; border-radius: 2px; padding: 1px 5px;
}
.rules-status.is-live { color: var(--ok); }

/* ---------------------------------------------------------------- site markup (00) */

.sm-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.sm-chip {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.04em;
  background: var(--band); color: var(--steel);
  border: 1px solid var(--line); border-radius: 2px; padding: 6px 10px; white-space: nowrap;
}
.sm-chip.is-bad { background: var(--alarm); border-color: var(--rust); color: var(--rust); }

.sm-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 20px; padding-bottom: 70px;
}
@media (max-width: 900px) { .sm-grid { grid-template-columns: minmax(0, 1fr); } }

.sm-photobar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }

/* ---------------------------------------------------------------- the three plans */

/* Map, photo, blank — a switch between three equals, not a map with two fallbacks. The two
   pixel plans are the offline case and a remote site with no signal is normal here. */
.sm-plans { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.sm-plan {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.06em; text-transform: uppercase;
  background: var(--card); color: var(--steel);
  border: 1px solid var(--line-strong); border-radius: 2px;
  padding: 0 12px; min-height: 44px; cursor: pointer;
}
.sm-plan.is-on { background: var(--navy); border-color: var(--navy); color: var(--page); }
.sm-planwhy { font-size: 11px; color: var(--mute); margin-left: 4px; }

.sm-mapwrap { position: relative; }
.sm-map {
  height: 520px; min-height: 380px;
  border: 1px solid var(--line-strong); border-radius: 2px;
  background: var(--deep);
}
@media (max-width: 900px) { .sm-map { height: 60vh; } }
.sm-maphint { margin: 6px 0 0; font-size: 11px; color: var(--mute); }

/* The offline panel sits over the map where the imagery would be — not in a corner, and not
   as a toast that disappears. It is the answer to "why is this grey?", so it goes where the
   grey is, with the two plans that still work inside it. */
.sm-offline {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 500;
  max-width: min(420px, calc(100% - 32px));
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 18px;
  background: var(--deep);
  border: 1px solid var(--tan);
  border-radius: 2px;
  box-shadow: 0 6px 20px rgba(20, 32, 31, 0.35);
  text-align: center;
}
.sm-offline[hidden] { display: none; }
.sm-offline strong { color: var(--page); font-size: 12.5px; }
.sm-offline span { color: var(--teal); font-size: 11px; line-height: 1.5; }
.sm-offline-actions { display: flex; gap: 6px; justify-content: center; flex-wrap: wrap; }
.sm-offline .sm-plan { background: var(--card); }
.sm-imagery {
  margin: 10px 0 0; font-family: var(--mono); font-size: 9.5px; color: var(--mute);
}

.sm-findbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.sm-findbar input { flex: 1 1 220px; margin: 0; }
.sm-findnote { font-family: var(--mono); font-size: 10px; color: var(--mute); }
.sm-findnote.is-bad { color: var(--rust); }

/* Leaflet overlay furniture. The map is dark, so the labels are the bone ground reversed. */
.leaflet-container { background: var(--deep); font-family: var(--mono); }
.fc-pin { display: flex; flex-direction: column; align-items: center; }
.fc-pin b {
  font: 600 10px/1 var(--mono); color: #fff; padding: 3px 6px; border-radius: 2px;
  white-space: nowrap; box-shadow: 0 2px 6px rgba(14, 42, 59, 0.4);
}
.fc-pin i { width: 2px; height: 9px; }
.fc-vertex { border-radius: 50%; border: 2px solid var(--page); box-shadow: 0 1px 3px rgba(14,42,59,.5); }
.fc-post { width: 5px; height: 5px; border-radius: 50%; background: var(--teal); opacity: 0.9; }
.fc-seg {
  font: 600 10px/1 var(--mono); color: var(--deep); background: rgba(245, 241, 233, 0.94);
  padding: 3px 6px; border-radius: 2px; white-space: nowrap;
  box-shadow: 0 1px 4px rgba(14, 42, 59, 0.28);
}
.fc-live {
  font: 600 11px/1 var(--mono); color: #fff; background: var(--ok);
  padding: 4px 7px; border-radius: 2px; white-space: nowrap;
  box-shadow: 0 2px 8px rgba(14, 42, 59, 0.4);
}
.fc-live u { display: block; text-decoration: none; font-weight: 400; font-size: 9px; opacity: 0.8; margin-top: 2px; }
.fc-total {
  font: 700 11px/1 var(--mono); color: var(--teal); background: var(--deep);
  padding: 4px 8px; border-radius: 2px; white-space: nowrap;
  box-shadow: 0 2px 8px rgba(14, 42, 59, 0.45);
}
/* Labels must never eat a click meant for the map underneath. */
.leaflet-marker-icon.fc-nohit { pointer-events: none !important; }

/* Same load-bearing rule as the save bar: `display` on an element carrying the `hidden`
   attribute beats the UA stylesheet, so a hidden plan would stay on screen. */
.sm-mapwrap[hidden], .sm-canvas[hidden], .sm-photobar[hidden], .sm-findbar[hidden],
.sm-card[hidden] { display: none; }
.sm-what { font-size: 11px; color: var(--steel); margin-left: 6px; }
.sm-btn {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.04em;
  background: var(--card); border: 1px solid var(--line-strong); border-radius: 2px;
  color: var(--steel); padding: 0 10px; min-height: 44px; cursor: pointer;
}
.sm-btn.is-in { color: var(--ok); border-color: var(--ok); }
.sm-btn.is-out { color: var(--rust); border-color: var(--rust); }
.sm-btn.is-armed { background: var(--rust); border-color: var(--rust); color: #fff; }

/*
  THE ASPECT LOCK. Not cosmetic. Geometry is stored normalised 0-1 and measured in a fixed
  1180x700 space; if this element's display aspect diverged, x and y would scale differently
  and a vertical 20 m would measure short against an identical horizontal 20 m — silently,
  because the drawn overlay still follows the clicks. Do not replace with a fixed height.
*/
.sm-canvas {
  position: relative; width: 100%; aspect-ratio: 1180 / 700;
  overflow: hidden; border: 1px solid var(--line-strong); border-radius: 2px;
  background: var(--band);
  background-image:
    linear-gradient(to right, rgba(20,32,31,0.07) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(20,32,31,0.07) 1px, transparent 1px);
  background-size: 40px 40px;
  touch-action: none;
}
.sm-canvas[data-tool="calibrate"] { cursor: crosshair; }
.sm-layer {
  position: absolute; inset: 0; transform-origin: 0 0;
  background-size: contain; background-repeat: no-repeat; background-position: center;
}
.sm-svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.sm-vertex { cursor: pointer; }
.sm-vertex:hover { fill: #C0392B; }
.sm-pins { position: absolute; inset: 0; }

.sm-blank {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 6px; text-align: center; padding: 20px;
}
.sm-blank strong { font: 800 20px/1 var(--head); text-transform: uppercase; color: var(--steel); }
.sm-blank span { font-size: 12px; color: var(--mute); max-width: 46ch; }

/* A pin is anchored at its point with translate(-50%,-100%) on a 2px stem, so the stem tip
   is the location — like a real map pin. Minimum 46px hit area: used in a paddock. */
.sm-pin {
  position: absolute; transform: translate(-50%, -100%);
  background: none; border: 0; padding: 0 8px 8px; cursor: pointer; min-width: 46px; min-height: 46px;
  display: flex; flex-direction: column; align-items: center;
}
.sm-pin-flag {
  font-family: var(--mono); font-size: 11px; color: #fff;
  border-radius: 2px; padding: 3px 6px; white-space: nowrap;
}
.sm-pin-flag i { font-style: normal; opacity: 0.7; margin-left: 5px; }
.sm-pin-stem { width: 2px; height: 14px; }

.sm-tools { display: flex; gap: 6px; flex-wrap: wrap; margin: 10px 0 0; align-items: center; }
.sm-tool {
  font-family: var(--mono); font-size: 10.5px; background: var(--card); color: var(--steel);
  border: 1px solid var(--line-strong); border-radius: 2px; padding: 0 10px;
  min-height: 44px; cursor: pointer;
}
.sm-tool.is-on { color: #fff; border-color: transparent; }
.sm-toolright { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; }

.sm-layer-chip {
  font-family: var(--mono); font-size: 10px; background: var(--card); color: var(--steel);
  border: 1px solid var(--line-strong); border-radius: 2px; padding: 0 10px;
  min-height: 44px; cursor: pointer;
}
.sm-layer-chip.is-on { background: var(--navy); border-color: var(--navy); color: var(--page); }

.sm-preview { font-family: var(--mono); font-size: 11px; color: var(--ok); margin: 10px 0 2px; }
.sm-hint { font-size: 11px; color: var(--mute); margin: 0; }
.sm-warn {
  background: var(--alarm); border: 1px solid var(--rust); border-radius: 2px;
  color: var(--rust); font-size: 11.5px; padding: 8px 10px; margin: 8px 0;
}

.sm-card { border-top-color: var(--navy); }
.sm-runs { border-top-color: var(--ok); }
.sm-cardbody { padding: 10px 12px 12px; display: grid; gap: 8px; }
.sm-note { font-size: 11px; color: var(--steel); margin: 0; }
.sm-cond { font-family: var(--mono); font-size: 11px; color: var(--rust); margin: 2px 0; }
.sm-scalestate { font-family: var(--mono); font-size: 11px; margin: 0; }
.sm-scalestate.is-ok { color: var(--ok); }
.sm-scalestate.is-bad { color: var(--rust); }

.sm-run { display: grid; gap: 4px; padding: 8px; border: 1px solid var(--line); border-radius: 2px; margin-bottom: 6px; }
.sm-run.is-active { background: var(--band); }
.sm-runname, .sm-runnote { margin: 0; }
.sm-runlen { font-family: var(--mono); font-size: 11px; text-align: right; color: var(--deep); }
.sm-runactions { display: flex; gap: 4px; flex-wrap: wrap; align-items: center; }
.sm-runcount { font-family: var(--mono); font-size: 10px; color: var(--mute); }
.sm-runtotal { font-family: var(--mono); font-size: 11px; color: var(--tan); margin: 4px 0 0; }

.sm-confirm { background: var(--band); border-radius: 2px; padding: 12px; margin-bottom: 12px; }
.sm-status { font-size: 11.5px; margin: 0 0 8px; color: var(--steel); }
.sm-status.is-ok { color: var(--ok); }
.sm-status.is-bad { color: var(--rust); }
.sm-tally { display: grid; grid-template-columns: 1fr auto; gap: 2px 10px; margin: 0 0 10px; }
.sm-tally dt { font-size: 11.5px; color: var(--steel); }
.sm-tally dd { margin: 0; font-family: var(--mono); font-size: 11.5px; text-align: right; }
.sm-action {
  width: 100%; min-height: 46px; border: 0; border-radius: 2px; cursor: pointer;
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.05em; color: #fff;
  background: var(--mute);
}
.sm-action.is-bad { background: var(--rust); }
.sm-action.is-ok { background: var(--ok); }
.sm-action:disabled { cursor: default; opacity: 0.6; }

.sm-jobdata {
  background: var(--deep); color: var(--page); border-radius: 2px;
  padding: 12px; font-size: 11.5px;
}

/* ---------------------------------------------------------------- job tracker (06) */

.jt-bar { display: flex; gap: 14px; align-items: flex-end; flex-wrap: wrap; margin-bottom: 14px; }
.jt-bar label { font-size: 11px; }
.jt-bar input, .jt-bar select { width: auto; min-width: 150px; }

.jt-tiles {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 10px; margin-bottom: 12px;
}
.jt-tile {
  background: var(--card); border: 1px solid var(--line); border-top: 3px solid var(--navy);
  border-radius: 2px; padding: 10px 12px; display: grid; gap: 3px;
}
.jt-tile.is-ok { border-top-color: var(--ok); }
.jt-tile.is-bad { border-top-color: var(--rust); }
.jt-tile-label {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--steel);
}
.jt-tile-value {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 17px; color: var(--deep);
}
.jt-tile-note { font-size: 10.5px; color: var(--mute); }

.jt-alerts { display: grid; gap: 8px; margin-bottom: 14px; }
.jt-alert {
  border-radius: 2px; padding: 9px 12px; font-size: 11.5px; border: 1px solid var(--line);
}
/* A friendly all-clear when zero, a count and a warning when not. */
.jt-alert.is-ok { background: #EFF6F2; border-color: var(--ok); color: var(--ok); }
.jt-alert.is-bad { background: var(--alarm); border-color: var(--rust); color: var(--rust); }

.jt-formactions { display: flex; align-items: center; gap: 12px; padding: 0 12px 12px; }
.jt-note { font-size: 11px; color: var(--rust); }

table.jt-table { min-width: 1080px; }
table.jt-table td { padding: 4px 6px; }
table.jt-table input, table.jt-table select {
  margin: 0; min-height: 30px; padding: 4px 6px; font-size: 11.5px; width: 100%;
}
table.jt-table tr.is-overdue td:first-child { box-shadow: inset 3px 0 0 var(--rust); }
.jt-empty { color: var(--mute); font-size: 12px; text-align: center; padding: 18px !important; }

/* ------------------------------------------------ time saved (07) & report (08) */

.ts { max-width: 1240px; margin-inline: auto; }
.ts-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; }
.ts-tile {
  background: var(--card); border: 1px solid var(--line); border-top: 3px solid var(--ok);
  border-radius: 2px; padding: 12px; display: grid; gap: 3px;
}
.ts-tile-label {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--steel);
}
.ts-tile-value {
  font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 19px; color: var(--deep);
}
.ts-tile-note { font-size: 10.5px; color: var(--mute); }

/* The formula is the credibility metric, so it is shown beside the figures it produced. */
.ts-working {
  background: var(--band); border-radius: 2px; padding: 12px; margin: 12px 0;
}
.ts-formula {
  font-family: var(--mono); font-size: 12px; color: var(--deep); margin: 0 0 4px;
}
.ts-assume { font-size: 11.5px; color: var(--steel); margin: 8px 0 0; }
table.ts-table { width: 100%; }

/* The report's letterhead. Same shape as the client quote's identity band — line one is the
   business name — because they are the same fact on two documents. */
.mr-letterhead { margin: 0 0 14px; padding-bottom: 10px; border-bottom: 1px solid var(--line); }
.mr-letterhead p { margin: 0; font-size: 11px; line-height: 1.5; color: var(--steel); }
.mr-business {
  font: 700 16px/1.2 var(--head); letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--ink) !important; margin-bottom: 3px !important;
}

.mr-sheet {
  max-width: 830px; margin: 0 auto; background: var(--card);
  border: 1px solid var(--line); border-radius: 2px; padding: 26px 30px 30px;
}
.mr-head h3 {
  font: 800 26px/1 var(--head); letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--deep); margin: 0 0 4px;
}
.mr-period { font-family: var(--mono); font-size: 11px; color: var(--steel); margin: 0 0 18px; }
.mr-glance, .mr-section { margin-bottom: 20px; }
.mr-glance h4, .mr-section h4 {
  font: 600 13px/1.3 var(--sans); color: var(--deep); margin: 0 0 8px;
  border-bottom: 1px solid var(--line-strong); padding-bottom: 4px;
}
.mr-figures { display: grid; grid-template-columns: 1fr auto; gap: 3px 16px; margin: 0; }
.mr-figures dt { font-size: 12.5px; color: var(--ink); }
.mr-figures dd {
  margin: 0; font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 12.5px; text-align: right; color: var(--deep);
}
table.mr-table { width: 100%; border-collapse: collapse; }
table.mr-table th {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--steel); text-align: left; padding: 5px 6px;
  border-bottom: 1px solid var(--line);
}
table.mr-table td { padding: 6px; font-size: 12px; border-bottom: 1px solid var(--line); }
table.mr-table th.num, table.mr-table td.num {
  text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums;
}
.mr-none { font-size: 12px; color: var(--mute); margin: 0; }

/* ------------------------------------------- price onboarding (09) & gates (10) */

.screen#s09, .screen#s10 { max-width: 1320px; margin-inline: auto; }

/* The centrepiece. It gets the strongest treatment on the screen because it is the actual
   mechanic: change one number, every line from that supplier re-prices. */
.po-supplier-panel {
  background: var(--navy); border-top: 4px solid var(--tan); border-radius: 2px;
  padding: 14px 16px; margin-bottom: 12px; color: var(--page);
}
.po-supplier-panel h3 {
  font: 800 18px/1 var(--head); letter-spacing: 0.03em; text-transform: uppercase; margin: 0 0 4px;
}
.po-supplier-why { font-size: 11.5px; color: var(--teal); margin: 0 0 12px; max-width: 76ch; }
.po-supplier-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.po-supplier { display: grid; gap: 3px; }
.po-supplier-name {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--page);
}
.po-supplier-count { font-family: var(--mono); font-size: 9.5px; color: var(--teal); }

.po-note {
  background: var(--card); border: 1px solid var(--line); border-left: 3px solid var(--tan);
  border-radius: 2px; padding: 10px 12px; margin-bottom: 12px;
  font-size: 11.5px; color: var(--steel);
}
.po-bar { display: flex; gap: 14px; align-items: flex-end; flex-wrap: wrap; margin-bottom: 10px; }
.po-bar label { font-size: 11px; flex: 1 1 260px; }
.po-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
.po-tab {
  font-family: var(--mono); font-size: 10.5px; background: var(--card); color: var(--steel);
  border: 1px solid var(--line-strong); border-radius: 2px; padding: 0 10px;
  min-height: 44px; cursor: pointer;
}
.po-tab.is-on { background: var(--navy); border-color: var(--navy); color: var(--page); }
.po-badge {
  font-style: normal; font-size: 9px; color: var(--rust); background: var(--alarm);
  border-radius: 2px; padding: 1px 4px; margin-left: 6px;
}
.po-tab.is-on .po-badge { color: var(--rust); }

table.po-table { min-width: 1080px; }
table.po-table td { padding: 5px 6px; vertical-align: top; }
table.po-table td.mono { font-family: var(--mono); font-size: 10.5px; }
table.po-table input { margin: 0; min-height: 30px; padding: 4px 6px; font-size: 11.5px; }
/* Never $0, never null — say what is missing, with the field right there. */
.po-missing { display: block; font-family: var(--mono); font-size: 9.5px; color: var(--rust); }
.po-overridden { display: block; font-family: var(--mono); font-size: 9.5px; color: var(--tan); }

.sg-filters { display: grid; gap: 6px; margin-bottom: 12px; }
.sg-chiprow { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.sg-chiplabel {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--steel); min-width: 74px;
}
.sg-chip {
  font-family: var(--mono); font-size: 10.5px; background: var(--card); color: var(--steel);
  border: 1px solid var(--line-strong); border-radius: 2px; padding: 0 10px;
  min-height: 44px; cursor: pointer;
}
.sg-chip.is-on { background: var(--navy); border-color: var(--navy); color: var(--page); }

.sg-header { margin-bottom: 10px; }
.sg-header h3 {
  font: 800 19px/1 var(--head); letter-spacing: 0.02em; text-transform: uppercase;
  color: var(--deep); margin: 0 0 3px;
}
.sg-count { font-family: var(--mono); font-size: 11px; color: var(--steel); margin: 0 0 3px; }
/* A20 — a retired grade is stated, not silent. */
.sg-filternote { font-size: 11px; color: var(--tan); margin: 0; }

table.sg-table { min-width: 1000px; }
.sg-cell { vertical-align: top; padding: 6px !important; min-width: 130px; }
.sg-cell input { margin: 0; min-height: 28px; padding: 3px 5px; font-size: 11px; }
.sg-cell.is-emph { background: var(--zebra); }
.sg-live { display: block; font-family: var(--mono); font-size: 9.5px; color: var(--ok); }
.sg-missing { display: block; font-family: var(--mono); font-size: 9.5px; color: var(--rust); }
.sg-meta { display: block; font-family: var(--mono); font-size: 9px; color: var(--mute); }
.sg-cell.is-nopricy { background: var(--alarm); }
/* Not made: inert and hatched. A product that does not exist is not a pricing gap. */
.sg-cell.is-notmade {
  color: var(--mute); font-family: var(--mono); font-size: 10px; text-align: center;
  background: repeating-linear-gradient(45deg, transparent, transparent 5px,
              rgba(20,32,31,0.05) 5px, rgba(20,32,31,0.05) 10px);
}
.sg-legend { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.sg-key {
  font-family: var(--mono); font-size: 10px; color: var(--steel);
  border: 1px solid var(--line); border-radius: 2px; padding: 4px 8px;
}
.sg-key.is-nopricy { background: var(--alarm); color: var(--rust); border-color: var(--rust); }
.sg-key.is-notmade { color: var(--mute); }

/* ------------------------------------------------- no job linked yet (screen 02)
   Rust, like every other "this needs your attention" state. It disappears the moment a job
   exists rather than becoming standing furniture. */

.jobless {
  border: 1px solid var(--rust); border-radius: 2px;
  background: var(--alarm); padding: 12px; margin: 12px 0 0;
}
.jobless[hidden] { display: none; }
.jobless-why { margin: 0 0 10px; font-size: 12.5px; color: var(--ink); max-width: 62ch; }
.jobless-note {
  margin-left: 10px; font-size: 11px; color: var(--steel); font-family: var(--mono);
}


/* ------------------------------------------------- on-site quantity correction (screen 02)
   Tan, like every override cell on the costing sheet, and for the same reason: the colour
   promises "you can change this, and empty means the calculated figure stands". */

td.adjust { white-space: nowrap; }
.adjust-qty, .adjust-why {
  background: var(--tanfill, #F3ECDD); border: 1px solid var(--tan);
  border-radius: 2px; font-family: var(--mono); font-size: 11px;
  padding: 3px 4px; margin: 0;
}
.adjust-qty { width: 58px; text-align: right; }
.adjust-why { width: 82px; margin-left: 4px; }
.adjust-qty::placeholder { color: var(--mute); }
td.adjust.is-adjusted { border-left: 2px solid var(--tan); }


/* ---------------------------------------------------------------- manual call-up rows */

.manual { border-top: 1px solid var(--line); padding: 12px; }
.manual-head {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--rust); margin-bottom: 8px;
}
.manual-row {
  display: grid;
  grid-template-columns: minmax(0, 3fr) 72px 66px 90px 78px 128px 32px;
  gap: 6px; margin-bottom: 6px; align-items: center;
}
@media (max-width: 700px) { .manual-row { grid-template-columns: minmax(0, 1fr); } }
.manual-row input { margin: 0; }
/* The margin column is an override: blank means the job margin stands. Deliberately the same
   tint as `.adjust-qty` below rather than the costing sheet's `--over` — both overrides live
   on screen 02 and sit inches apart, so they should promise the same thing in the same colour.
   The placeholder shows the job margin it defaults to, which is what a tan cell does. */
.manual-row input.is-ov { background: var(--tanfill, #F3ECDD); border-color: var(--tan); }
.manual-row input.is-ov::placeholder { color: var(--mute); font-style: italic; }
/* What the override did, beside the field that did it. Tan text rather than a tan fill — it
   is a *result*, not something you can type into, and the two must not look alike. Empty when
   no margin is typed, so an un-overridden row stays quiet. */
.cq-terms { margin-top: 18px; border-top: 1px solid var(--line); padding-top: 12px; }
.cq-terms h4 {
  margin: 0 0 6px; font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--steel); font-weight: 600;
}
/* `pre-wall` so a multi-clause block keeps the line breaks the estimator typed — terms are
   read clause by clause and reflowing them into one paragraph makes them unreadable. */
.cq-terms p { margin: 0; font-size: 11px; line-height: 1.5; white-space: pre-wrap; }

.manual-effect {
  font-family: var(--mono); font-size: 10.5px; color: var(--tan);
  text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.manual-drop {
  background: none; border: 1px solid var(--line); border-radius: 2px;
  color: var(--rust); font-family: var(--mono); font-size: 11px;
  padding: 8px 6px; cursor: pointer;
}
.manual-why { font-size: 11px; color: var(--mute); margin: 8px 0 0; }

/* Which mode the job is in. A note, never a hidden control: the fields below still work, and
   typing in one is how a hand-priced job becomes a mixed one. */
.mode-note {
  margin: 0 0 12px; padding: 7px 10px; font-size: 11.5px; line-height: 1.5;
  color: var(--deep); background: var(--band); border-left: 3px solid var(--tan);
  border-radius: 2px;
}
/* Quietened, not disabled — the difference is the whole ruling. */
.card.is-unused .grid { opacity: 0.55; }
.card.is-leading { border-color: var(--tan); }
.card.is-leading .card-head { color: var(--ink); }

/* Which of the two hand-entry surfaces you are on. The mechanism cannot tell an extra item
   from a whole hand-priced fence — they are the same line type — so a person has to. */
.manual-which {
  margin: 0 0 10px; font-size: 11px; line-height: 1.5; color: var(--steel); max-width: 680px;
}

/* An off-catalogue block. Boxed, because it is a parcel of work rather than a row — the
   visual difference is what stops it being read as another "add material row". */
.oc-block {
  border: 1px solid var(--line-strong); border-radius: 2px;
  padding: 10px 12px 12px; margin-bottom: 10px; background: var(--card);
}
.oc-head { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.oc-name {
  flex: 1; font: 600 13px/1.3 var(--body); padding: 5px 8px;
  border: 1px solid var(--line-strong); border-radius: 2px; background: var(--input);
}
.manual-total {
  margin-left: 10px; font-family: var(--mono); font-size: 11.5px;
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.manual-total[hidden] { display: none; }


/* ------------------------------------------------- business identity editor (screen 06)
   Deliberately plain. This edits what appears on documents; it is not a theming panel, and
   nothing here is allowed to change how the application itself looks. */

.co-foot { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 0 12px 12px; }
.co-logo-state { font-family: var(--mono); font-size: 11px; color: var(--steel); }
.co-state { width: 100%; margin: 6px 0 0; font-size: 11.5px; }
.co-state.is-bad { color: var(--rust); }
.co-state.is-ok { color: var(--ok); }
.co-state.is-warn { color: var(--tan); }


/* ------------------------------------------------- saved quotes (screen 01) */

.sq-panel {
  display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap;
  padding: 0 12px 12px; border-bottom: 1px solid var(--line);
}
.sq-panel[hidden] { display: none; }
.sq-open { font-family: var(--mono); font-size: 11px; color: var(--steel); }
#sq_table tr.is-open { background: var(--band); }


.co-terms { padding: 0 12px 4px; }
/* The offer sits under the field it fills, not beside the Save controls: it is a way of
   filling this box, not a second way of saving the record. */
.co-terms-offer { display: flex; align-items: baseline; gap: 10px; margin-top: 6px; }
.co-terms-offer .ref { flex: 1; line-height: 1.45; }
.co-terms textarea {
  width: 100%; font-family: var(--mono); font-size: 11.5px;
  background: var(--input); border: 1px solid var(--line-strong); border-radius: 2px;
  padding: 6px; resize: vertical;
}

/* ------------------------------------------------- purchase orders (screen 02) */

.po-panel {
  display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap;
  padding: 0 12px 12px; border-bottom: 1px solid var(--line);
}
.po-panel[hidden] { display: none; }
.po-preview {
  margin: 0; padding: 12px; overflow-x: auto;
  font-family: var(--mono); font-size: 11px; line-height: 1.4;
  background: var(--zebra); border-top: 1px solid var(--line);
}
.po-preview[hidden] { display: none; }
#po_table tr.is-cancelled td { color: var(--mute); text-decoration: line-through; }

/* ------------------------------------------------- extra fence types (screen 01) */

.run-row {
  display: grid;
  grid-template-columns: minmax(0, 2fr) repeat(7, minmax(0, 1fr)) 32px;
  gap: 6px; padding: 0 12px 8px; align-items: end;
}
@media (max-width: 900px) { .run-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.run-row label { font-size: 10px; }
.run-why { font-size: 11px; color: var(--mute); margin: 0; padding: 0 12px 12px; }
#run_add { margin: 0 12px 12px; }
/* The fence-type name heading a block of schedule or sheet rows. */
th.run-head {
  text-align: left; background: var(--band); color: var(--deep);
  font-family: var(--head); font-size: 15px; letter-spacing: 0.03em;
  text-transform: uppercase; padding: 8px 10px;
}

/* ------------------------------------------------- variations (screen 03) */

.var-panel {
  display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap;
  padding: 0 12px 12px; border-bottom: 1px solid var(--line);
}
.var-panel[hidden] { display: none; }
.var-panel label:first-child { flex: 1 1 320px; }
.var-state { font-family: var(--mono); font-size: 11px; color: var(--steel); }
/* Two figures side by side, because they are two facts. Never one. */
.var-totals {
  display: flex; gap: 24px; flex-wrap: wrap;
  padding: 12px; border-top: 1px solid var(--line);
  font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 12px;
}
.var-totals[hidden] { display: none; }
.var-totals b { display: block; font-size: 10px; color: var(--steel); font-weight: 600; }
#var_table tr.is-proposed td { color: var(--steel); }

/* Where to go and fix a failing pre-send row. Rust like the row itself, indented under the
   detail so it reads as the next step rather than as more of the problem. */
.ps-where {
  grid-column: 2 / -1; margin: 2px 0 0;
  font-family: var(--mono); font-size: 11px; color: var(--rust);
}

/* ---------------------------------------------------------------- print
   Keep this block LAST. Two tests slice the stylesheet from `@media print` to the end of
   the file, so anything appended below is read as though it were inside it — which is how
   a `min-height` on a manual row failed a test about print extents. */

@media print {
  [data-print-hide] { display: none !important; }
  /* Every screen's standfirst is an explanation written for the estimator — "The document the
     client receives", "what it costs", "a read-only view of Job Tracker". None of it is
     addressed to whoever receives the printed page, so none of it prints. */
  p.sub { display: none !important; }
  body { background: #fff; }
  .scroll { overflow: visible !important; }   /* never clip a costing column */
  .card { break-inside: auto; }
  table.sheet tr { break-inside: avoid; }
  /* No height or width declaration anywhere in this block, deliberately: the document runs
     to however many pages its content needs. The workbook pinned Client_Quote to A1:D82 and
     Material_Callup to A1:G114 with content already past row 120, so quotes with several
     gates and variations were being cut off. No fixed area, no manual scaling.

     The wording scaffolding is excluded here as well as being hidden by default. Two
     mechanisms, because "someone will remember to collapse it" is not a control. */
  .cq-sheet { max-width: none; border: 0; padding: 0; }
  /* The report prints as its sheet, and to however many pages it needs. */
  .mr-sheet { max-width: none; border: 0; padding: 0; }
  .mr-section { break-inside: auto; }
  table.mr-table tr { break-inside: avoid; }
  .cq-wording-tools { display: none !important; }
  table.cq-lines thead { display: table-header-group; }
  .cq-totals { break-inside: avoid; }
  [data-print-row] { break-inside: avoid; }

  /* A row and the note that explains it are two <tr>s, and were free to land on different
     pages. Only rows that have a note are marked, because `break-after: avoid` on every row
     would tell the print engine never to break the table. */
  [data-keep-with-next] { break-after: avoid; }

  /* The terms are prose and may break across pages — what must not happen is the heading
     stranded alone at the foot of one. `orphans`/`widows` keep at least two lines of a clause
     together, so a single trailing line never starts a page on its own. */
  .cq-terms { break-inside: auto; }
  .cq-terms h4 { break-after: avoid; }
  .cq-terms p { orphans: 2; widows: 2; }
  .cq-sheet-head { break-after: avoid; }
  table.cq-lines tbody { orphans: 2; widows: 2; }
}

/* ---------------------------------------------------------------- costing summary */

/*
  Spec 09 §4. Three columns under one rust band. All three share the same format — heading,
  one-line grey subtitle, white bordered box, label + mono value rows, navy total bar — so
  the eye can compare them without re-reading the labels.

  The priced-lines status is the only surviving colour in the whole block. That is deliberate:
  one signal, unmissable, instead of a screen of competing tints.
*/
.summary { margin-bottom: 16px; }

.sum-band {
  background: var(--alarm);
  border: 1px solid var(--rust);
  border-radius: 2px 2px 0 0;
  color: var(--rust);
  font: 700 11px/1 var(--mono);
  letter-spacing: 0.05em;
  padding: 10px 12px;
}

.sum-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 14px;
  padding: 14px;
  background: var(--card);
  border: 1px solid var(--line);
  border-top: 0;
  border-radius: 0 0 2px 2px;
}

.sum-col h3 {
  font: 800 17px/1 var(--head);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--deep);
  margin: 0;
}
.sum-col h3 i { font-style: normal; color: var(--tan); margin-right: 4px; }
.sum-sub { color: var(--steel); font-size: 11px; margin: 4px 0 8px; }

.sum-body {
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 4px 0;
}
.sum-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
  align-items: baseline;
  padding: 5px 10px;
}
.sum-label { font-size: 12.5px; color: var(--ink); }
.sum-value {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  color: var(--deep);
  text-align: right;
}
.sum-detail {
  grid-column: 1 / -1;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--mute);
}
.sum-value.is-ok, .sum-detail.is-ok { color: var(--ok); }
.sum-value.is-bad, .sum-detail.is-bad { color: var(--rust); }

.sum-bar {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  background: var(--navy);
  color: var(--page);
  border-radius: 2px;
  margin-top: 8px;
  padding: 9px 10px;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 12.5px;
  font-weight: 600;
}

/* Who is signed in, top right of the masthead. `sign-out` is a real button rather than a
   link: it performs an action and does not navigate to a resource. */
.masthead-who { margin-left: auto; display: flex; align-items: center; gap: 12px; }
.masthead-who .who { font-family: var(--mono); font-size: 10px; color: var(--teal); opacity: 0.85; }
.masthead-who .sign-out { font-family: var(--mono); font-size: 10px; letter-spacing: .06em;
  text-transform: uppercase; background: none; color: var(--teal); border: 1px solid currentColor;
  border-radius: 2px; padding: 4px 9px; cursor: pointer; opacity: .8; }
.masthead-who .sign-out:hover { opacity: 1; }
