/* Campaign desk. The Build Portal's design system, which follows the
   buildteam.com website (Oliver, 7 Oct 2026).

   Petrol blue #00517D carries the brand: the top bar, links, outlines and
   filled secondary buttons. The ONE next action on a screen is a black pill
   (.btn-action). There is no orange. A filled colour on a small pill means
   status and nothing else: green done, amber needs a look, red a problem,
   blue under way, grey to come. Poppins in three weights: 400 body, 500
   labels and buttons, 600 headings and figures. Buttons, inputs and chips
   are pills; inputs are grey with no border, so they always sit on white. */
:root {
  --brand: #00517d;
  --brand-dark: #003b5c;
  --tint: #e0eef5;
  --highlight: #eaf1f5;
  --primary: #000000;
  --navy: #0a142f;
  --ink: #1a1a1a;
  --muted: #616161;
  --soft: #6e6e6e;
  --surface: #f5f5f5;
  --field: #f0f0f0;
  --line: #e5e5e5;
  --card: #ffffff;
  --success: #17633f;
  --success-soft: #e6f4ec;
  --amber: #9a4e00;
  --amber-soft: #fdf3e4;
  --amber-line: #f3ddbd;
  --danger: #b3261e;
  --danger-soft: #fbeaea;
  --neutral: #4a4a4a;
  --neutral-soft: #ececec;
  --shadow-card: 0 4px 24px rgba(0, 81, 125, .07);
  --shadow-panel: 0 8px 28px rgba(0, 81, 125, .22);
  --shadow-bar: 0 2px 10px rgba(0, 81, 125, .25);
  --bar-height: 68px;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  /* Pale grey ground with a soft blue glow under the top bar. */
  background:
    radial-gradient(90% 460px at 50% 120px, rgba(0, 81, 125, .1), rgba(0, 81, 125, 0)) no-repeat,
    var(--surface);
  color: var(--ink);
  font: 15px/1.5 Poppins, "Segoe UI", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}
h1 { font-size: 30px; line-height: 1.2; font-weight: 600; color: var(--navy); margin: 0; }
h2 { font-size: 18px; line-height: 1.35; font-weight: 600; color: var(--navy); margin: 0 0 10px; }
h3 { font-size: 15px; font-weight: 600; color: var(--navy); margin: 0 0 6px; }
p { margin: 0 0 12px; }
a { color: var(--brand); }
b, strong { font-weight: 600; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.num { font-variant-numeric: tabular-nums; font-weight: 500; color: var(--muted); }
.nowrap { white-space: nowrap; }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
button:not(:disabled), summary, label:has(> input[type="checkbox"]) { cursor: pointer; }

/* ---- Top bar ---- */
.top { position: sticky; top: 0; z-index: 40; background: var(--brand); color: #fff; }
/* The bar's shadow sits on a layer behind it rather than on the bar itself.
   A shadow on the sticky bar makes the browser draw everything in the bar
   with plain grey smoothing instead of ClearType, and the text goes soft. */
.top::after { content: ""; position: absolute; inset: 0; z-index: -1; box-shadow: var(--shadow-bar); pointer-events: none; }
/* The desk is used on a PC monitor, so the page runs nearly the full width of
   one; the cap only stops lines growing too long on a very large screen. */
.top-inner, .page { max-width: 1880px; margin: 0 auto; padding-left: 32px; padding-right: 32px; }
.top-inner { display: flex; align-items: center; gap: 20px; padding-top: 12px; padding-bottom: 12px; }
.brand { flex: none; display: block; }
.brand img { display: block; height: 28px; width: auto; }
.role { flex: none; border-radius: 4px; background: rgba(255, 255, 255, .15); padding: 3px 10px; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .025em; white-space: nowrap; }
/* Only the tabs scroll on a narrow window; the links on the right stay put. */
.tabs-wrap { flex: 1; min-width: 0; }
.tabs { display: flex; align-items: center; gap: 4px; width: fit-content; max-width: 100%; overflow-x: auto; scrollbar-width: none; border-radius: 999px; background: rgba(255, 255, 255, .1); padding: 4px; }
.tabs a {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; border-radius: 999px; padding: 7px 16px;
  font-size: 15px; line-height: 22px; font-weight: 500; color: #fff; text-decoration: none; transition: background-color .2s, color .2s;
}
.tabs a:hover { background: rgba(255, 255, 255, .1); color: #fff; }
.tabs a[aria-current] { background: #fff; color: var(--navy); }
.tabs a:focus-visible, .top-links a:focus-visible, .account summary:focus-visible, .brand:focus-visible { outline-color: #fff; }
/* How many are waiting: white on the bar, blue on the white pill. */
.count { min-width: 20px; border-radius: 999px; background: #fff; color: var(--navy); padding: 0 6px; font-size: 12px; line-height: 20px; font-weight: 600; text-align: center; font-variant-numeric: tabular-nums; }
.tabs .count { min-width: 20px; font-size: 12px; line-height: 20px; }
.tabs a[aria-current] .count { background: var(--brand); color: #fff; }
.top-links { flex: none; display: flex; align-items: center; gap: 20px; }
.top-links a { font-size: 14px; font-weight: 500; color: rgba(255, 255, 255, .8); text-decoration: none; white-space: nowrap; }
.top-links a:hover, .top-links a[aria-current] { color: #fff; }
.top-links a[aria-current] { text-decoration: underline; text-underline-offset: 4px; }
/* Whoever is signed in, at the far right: their picture, or their initials
   in a white circle, with a small menu under it. */
.avatar { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; object-fit: cover; background: #fff; color: var(--brand); font-size: 14px; font-weight: 600; letter-spacing: .02em; }
.account { flex: none; position: relative; }
.account summary { display: block; list-style: none; border-radius: 50%; padding: 2px; transition: box-shadow .15s; }
.account summary::-webkit-details-marker { display: none; }
.account summary:hover, .account[open] summary { box-shadow: 0 0 0 2px rgba(255, 255, 255, .6); }
.account-menu { position: absolute; top: calc(100% + 10px); right: 0; width: max-content; min-width: 220px; max-width: min(360px, calc(100vw - 32px)); padding: 8px; background: var(--card); border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow-panel); color: var(--ink); }
.account-who { margin: 0 0 6px; padding: 8px 12px 12px; border-bottom: 1px solid var(--line); font-size: 14px; overflow-wrap: anywhere; }
.account-menu a, .account-menu button { display: flex; align-items: center; width: 100%; min-height: 40px; padding: 0 12px; border: 0; border-radius: 10px; background: none; font: inherit; font-size: 14px; font-weight: 500; color: var(--navy); text-decoration: none; text-align: left; }
.account-menu a:hover, .account-menu button:hover, .account-menu a[aria-current] { background: var(--highlight); color: var(--brand); }

/* ---- Page furniture ---- */
.page { padding-top: 28px; padding-bottom: 80px; }
.head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px 24px; flex-wrap: wrap; margin-bottom: 20px; }
.lede { color: var(--muted); font-size: 14px; max-width: 78ch; }
.head .lede { margin: 4px 0 0; }
.hint { color: var(--muted); font-size: 13px; }
.eyebrow { display: block; font-size: 12px; line-height: 1.4; font-weight: 500; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.flash { background: var(--highlight); border-radius: 16px; padding: 12px 18px; font-size: 14px; font-weight: 500; color: var(--navy); }
.card, .panel { background: var(--card); border: 1px solid var(--line); border-radius: 24px; box-shadow: var(--shadow-card); }
.panel { padding: 24px; margin-bottom: 20px; }
.empty { background: var(--card); border: 1px solid var(--line); border-radius: 24px; box-shadow: var(--shadow-card); padding: 28px 24px; font-size: 14px; color: var(--muted); }
.empty b { display: block; margin-bottom: 2px; font-size: 16px; color: var(--navy); }
.notice { border-radius: 16px; padding: 14px 18px; margin-bottom: 16px; font-size: 14px; }
.notice ul { margin: 6px 0 12px; padding-left: 20px; }
.notice-warn { background: var(--amber-soft); border: 1px solid var(--amber-line); color: var(--ink); }
.notice-warn b { color: var(--amber); }
.notice-danger { background: var(--danger-soft); color: var(--danger); font-weight: 500; }

/* The data line under the Review heading: how fresh the list is. */
.fresh { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-top: 4px; font-size: 14px; color: var(--muted); }
.fresh.is-running #refresh-text::before {
  content: ""; display: inline-block; width: 8px; height: 8px; margin-right: 8px; border-radius: 50%;
  background: var(--brand); animation: pulse 1.2s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { .fresh.is-running #refresh-text::before { animation: none; } }

/* ---- Controls ---- */
/* Buttons are pills. A plain .btn is a filled petrol one, for the main jobs
   on a row or a form; .btn-quiet is the outline for everything else. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 44px; padding: 0 18px;
  font: inherit; font-size: 14px; line-height: 1.25; font-weight: 500; text-decoration: none; white-space: nowrap; cursor: pointer;
  border-radius: 999px; border: 1.5px solid var(--brand); background: var(--brand); color: #fff;
  transition: background-color .15s, color .15s, border-color .15s;
}
.btn:hover { background: var(--brand-dark); border-color: var(--brand-dark); }
.btn-quiet { background: #fff; color: var(--brand); }
.btn-quiet:hover { background: var(--brand); border-color: var(--brand); color: #fff; }
/* The one next action on a screen: black, and a size up. */
.btn-action { min-height: 48px; padding: 0 24px; font-size: 16px; background: var(--primary); border-color: var(--primary); }
.btn-action:hover { background: #262626; border-color: #262626; }
.btn-action .count { background: rgba(255, 255, 255, .2); color: #fff; }
.btn[disabled] { opacity: .5; cursor: default; }
.link { font: inherit; font-weight: 500; color: var(--brand); background: none; border: 0; padding: 0; cursor: pointer; text-decoration: none; }
.link:hover { text-decoration: underline; text-underline-offset: 3px; }
.link-stop { color: var(--danger); }
.ext::after { content: " \2197"; font-size: .9em; }
.inline { display: inline; }

/* Inputs are grey pills with no border. */
select, input[type="text"], input[type="search"], input[type="date"], input[type="number"], input[type="tel"], input[type="email"], input[type="password"], input:not([type]), textarea {
  /* Not "inherit": a field inside a label would take the label's weight. */
  font: 400 15px/1.5 Poppins, "Segoe UI", system-ui, sans-serif; letter-spacing: normal; text-transform: none;
  color: var(--ink); background: var(--field);
  height: 48px; padding: 0 18px; border: 0; border-radius: 999px; max-width: 100%;
}
select { padding-right: 12px; }
::placeholder { color: var(--muted); opacity: 1; }
textarea { width: 100%; height: auto; min-height: 96px; padding: 14px 18px; border-radius: 16px; resize: vertical; }
select:focus-visible, input:focus-visible, textarea:focus-visible { outline-offset: 0; }
.check { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; font-size: 14px; }
input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--brand); flex: none; cursor: pointer; }

/* A choice between a few lists under one tab: outline pills, the chosen one filled. */
.views { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.views a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 18px; border-radius: 999px; border: 1.5px solid var(--brand); background: #fff; font-size: 15px; font-weight: 500; color: var(--brand); text-decoration: none; transition: background-color .15s, color .15s; }
.views a:hover { background: var(--tint); }
.views a[aria-current] { background: var(--brand); color: #fff; }

/* Grey inputs need a white ground, so the filters are a card of their own. */
.filters { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; margin: 0 0 16px; padding: 16px 20px; background: var(--card); border: 1px solid var(--line); border-radius: 24px; box-shadow: var(--shadow-card); }
.filters label { display: flex; flex-direction: column; gap: 6px; font-size: 14px; font-weight: 500; color: var(--ink); }
.filters select { width: 164px; }
.filters select[name="weeks"] { width: 150px; }
.filters select[name="state"] { width: 270px; }
.filters .grow { flex: 1 1 180px; }
.filters .grow input { width: 100%; }
.filters .btn { min-height: 48px; }
.filters > .link { min-height: 48px; display: inline-flex; align-items: center; font-size: 14px; }
.panel .filters { margin: 0; padding: 0; border: 0; border-radius: 0; box-shadow: none; }
/* Which list and how it is narrowed, side by side when there is room. The
   pills line up with the fields inside the filter card. */
.toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0 16px; }
.toolbar .views { margin-bottom: 34px; }
.toolbar .filters { flex: 1 1 760px; }

/* A filled pill is a status, and nothing else. */
.chip { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 12px; line-height: 1.5; font-weight: 500; background: var(--neutral-soft); color: var(--neutral); text-decoration: none; white-space: nowrap; vertical-align: 1px; }
.chip-warn { background: var(--amber-soft); color: var(--amber); }
.chip-responded, .chip-quoted { background: var(--tint); color: var(--brand); }
.chip-won { background: var(--success-soft); color: var(--success); }
.chip-lost, .chip-returned, .chip-stop { background: var(--danger-soft); color: var(--danger); }
/* The borough, in its own colour, so a list can be read by area.
   app/boroughs.py picks the hue and which of three looks it takes: there
   are more boroughs than colours the eye can tell apart. Squarer than a
   status chip, so the two are not mistaken for each other. */
.borough { display: inline-block; margin-right: 6px; padding: 2px 9px; border-radius: 7px; font-size: 12px; line-height: 1.5; font-weight: 600; white-space: nowrap; vertical-align: 1px; }
.borough-tint { background: hsl(var(--hue) 85% 90%); color: hsl(var(--hue) 80% 23%); }
.borough-solid { background: hsl(var(--hue) 72% 28%); color: #fff; }
.borough-line { background: #fff; color: hsl(var(--hue) 80% 26%); box-shadow: inset 0 0 0 1.5px hsl(var(--hue) 65% 48%); }

/* ---- Lead list ---- */
/* Stays under the top bar while the list scrolls, so the buttons for the
   ticked leads are in reach from anywhere down the page. */
.listbar {
  position: sticky; top: calc(var(--bar-height) + 8px); z-index: 5;
  display: flex; flex-wrap: wrap; gap: 8px 20px; align-items: center; justify-content: space-between;
  min-height: 60px; margin-bottom: 10px; padding: 8px 10px 8px 22px;
  background: var(--card); border: 1px solid var(--line); border-radius: 999px; box-shadow: var(--shadow-card);
  font-size: 14px; color: var(--muted);
}
.listbar b { color: var(--navy); }
.listbar-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.listbar .check { padding-right: 12px; }
[data-bulk] .btn { gap: .3em; }
.leads { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.lead {
  display: grid; grid-template-columns: minmax(0, 1fr) 250px 150px; gap: 14px 22px; align-items: start;
  background: var(--card); border: 1px solid var(--line); border-radius: 24px; box-shadow: var(--shadow-card); padding: 20px 22px;
  transition: opacity .18s;
}
.lead:has(> .lead-check) { grid-template-columns: auto minmax(0, 1fr) 250px 150px; }
.lead-compact, .lead-followup { grid-template-columns: minmax(0, 1fr) auto; }
.lead-enquiry { grid-template-columns: minmax(0, 1fr) 300px; scroll-margin-top: calc(var(--bar-height) + 16px); }
.lead-enquiry .chip { margin-left: 6px; }
.lead-contact input { width: 100%; }
.lead-contact .btn { justify-self: start; }
.lead-followup:has(> .lead-check) { grid-template-columns: auto minmax(0, 1fr) auto; }
.lead.is-leaving { opacity: 0; }
.lead.is-drop { outline: 2px dashed var(--brand); outline-offset: -2px; background: var(--highlight); }
.lead-check { margin-top: 3px; }
.lead-addr { font-size: 16px; font-weight: 600; line-height: 1.35; color: var(--navy); }
.lead-addr-missing { color: var(--muted); font-weight: 500; }
.pc { font-weight: 500; color: var(--brand); white-space: nowrap; margin-left: 4px; }
.lead-meta { color: var(--muted); font-size: 13px; margin-top: 2px; }
.lead-agent { color: var(--muted); font-size: 13px; margin-top: 2px; }
.lead-agent b { font-weight: 500; color: var(--ink); }
.ref { font-family: ui-monospace, Consolas, monospace; font-size: 12px; overflow-wrap: anywhere; }
.lead-desc { margin: 8px 0 0; max-width: 80ch; font-size: 15px; overflow-wrap: anywhere; }
.lead-reason { margin: 8px 0 0; color: var(--amber); font-size: 14px; font-weight: 500; }
.lead-links { display: flex; flex-wrap: wrap; gap: 4px 20px; margin-top: 10px; font-size: 14px; }

/* What the letter will say: the work, the room and the figure. */
.lead-work { display: grid; gap: 14px; border-left: 1px solid var(--line); padding-left: 22px; align-self: stretch; align-content: start; }
.lead-work:empty { border: 0; }
.lead-work select, .lead-work input[type="text"] { width: 100%; }
.work-fixed { font-weight: 500; font-size: 14px; }
.field { display: grid; gap: 6px; }
.room[hidden] { display: none; }
.room-input { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.room-input input { width: 110px; }
.room .js-measure { justify-self: start; }
.room .hint { font-size: 12px; overflow-wrap: anywhere; }
.price { font-size: 13px; color: var(--muted); }
.price-figure { font-size: 20px; font-weight: 600; color: var(--navy); font-variant-numeric: tabular-nums; margin-right: 6px; }
.price-basis { display: block; }
.price-none { display: block; }
.price form { margin-top: 2px; display: block; }

.lead-actions { display: flex; flex-direction: column; gap: 8px; align-items: stretch; }
.lead-actions .link { text-align: center; font-size: 14px; }
.lead-actions form { display: contents; }

.record { display: flex; flex-wrap: wrap; gap: 8px; }
.record input[type="text"], .record input[type="tel"], .record input[type="email"] { flex: 1 1 160px; }
.record input[type="number"] { width: 150px; }
.history { margin: 8px 0 0; padding-left: 18px; font-size: 13px; color: var(--ink); }
.history .link { margin-left: 8px; }

.reasons { list-style: none; padding: 0; margin: 0 0 16px; display: flex; flex-wrap: wrap; gap: 8px; }
.reasons li { background: var(--card); border: 1px solid var(--line); border-radius: 999px; padding: 5px 14px; font-size: 13px; }
.pager { display: flex; gap: 16px; align-items: center; justify-content: center; margin-top: 24px; font-size: 14px; color: var(--muted); }

/* ---- Tables ---- */
.scroll { overflow-x: auto; margin-bottom: 20px; }
table.plain { border-collapse: collapse; width: 100%; font-size: 14px; }
table.plain th, table.plain td { text-align: left; padding: 14px 20px; border-top: 1px solid var(--line); vertical-align: middle; }
table.plain thead th { border-top: 0; font-size: 12px; font-weight: 500; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
table.plain tbody th { font-weight: 500; color: var(--navy); }
table.sent td { vertical-align: top; }
table.sent td:first-child { width: 44%; }
table.sent td:last-child { width: 300px; }
table.sent td:nth-child(n+2):nth-child(-n+5) { padding-top: 18px; }
.record-box summary { display: inline-flex; align-items: center; min-height: 40px; padding: 0 16px; border: 1.5px solid var(--brand); border-radius: 999px; background: #fff; font-size: 14px; font-weight: 500; color: var(--brand); white-space: nowrap; list-style: none; transition: background-color .15s, color .15s; }
.record-box summary::-webkit-details-marker { display: none; }
.record-box summary:hover, .record-box[open] summary { background: var(--brand); color: #fff; }
.record-box .record { margin: 12px 0 8px; max-width: 420px; }
.lead-main .record-box { margin-top: 12px; }
.lead-main .record-box .record { max-width: 640px; }
table.prices { width: auto; min-width: min(560px, 100%); }
.prices input { width: 130px; font-variant-numeric: tabular-nums; }

/* ---- To post ---- */
.print-group + .print-group { margin-top: 36px; }
.print-group h3 { margin: 24px 0 10px; }
.steps { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.step { display: flex; gap: 14px; background: var(--card); border: 1px solid var(--line); border-radius: 24px; box-shadow: var(--shadow-card); padding: 20px 22px; }
.step-n { flex: none; width: 32px; height: 32px; border-radius: 50%; background: var(--brand); color: #fff; font-size: 14px; font-weight: 600; display: grid; place-items: center; }
.step-body { display: grid; gap: 12px; align-content: start; min-width: 0; }
.step-body h3, .step-body p { margin: 0; }
.step-body h3 { font-size: 16px; line-height: 32px; }
.step-date { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 500; }
.step-actions { display: flex; flex-wrap: wrap; gap: 8px 18px; align-items: center; }
.step-actions .link { font-size: 14px; }
/* Postcards are written by hand off the screen, so what goes on each one is
   set large enough to read from where the card is being written. */
.write-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; margin-bottom: 12px; }
.write-head h3 { margin: 0; font-size: 16px; }
.write-progress { font-size: 14px; font-weight: 600; color: var(--success); }
.write-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.write-card {
  display: grid; grid-template-columns: auto minmax(0, 1.4fr) minmax(0, .8fr) minmax(0, 1.2fr) auto; gap: 14px 24px; align-items: start;
  background: var(--card); border: 1px solid var(--line); border-radius: 24px; box-shadow: var(--shadow-card); padding: 20px 22px;
  transition: opacity .18s;
}
.write-card p { margin: 0; }
.write-tick { display: grid; justify-items: center; gap: 4px; min-width: 44px; padding-top: 2px; }
.write-tick input { width: 26px; height: 26px; }
.write-big { font-size: 24px; line-height: 1.3; font-weight: 600; color: var(--navy); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.write-address { font-style: normal; font-size: 18px; line-height: 1.4; font-weight: 500; color: var(--ink); overflow-wrap: anywhere; }
.write-about { grid-column: 2 / -1; display: flex; flex-wrap: wrap; gap: 0 18px; padding-top: 10px; border-top: 1px solid var(--line); }
.write-about > * { margin-top: 0; }
/* Written: out of the way, but still readable to check against the card. */
.write-card:has(.js-written:checked) { opacity: .45; box-shadow: none; }
.write-posted { margin-top: 14px; }

/* ---- Sent letters ---- */
.totals { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; margin: 0 0 16px; }
.totals div { background: var(--card); border: 1px solid var(--line); border-radius: 24px; box-shadow: var(--shadow-card); padding: 16px 20px; }
.totals dt { font-size: 12px; line-height: 1.4; font-weight: 500; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.totals dd { margin: 4px 0 0; font-size: 26px; line-height: 1.2; font-weight: 600; color: var(--navy); font-variant-numeric: tabular-nums; }
.totals small { font-size: 13px; font-weight: 500; color: var(--success); }

/* ---- Setup ---- */
.stack { display: grid; gap: 14px; justify-items: start; }
.stack > .scroll, .stack > .boroughs { justify-self: stretch; margin: 0; }
.panel .hint { margin: 0; }
.more { margin-bottom: 12px; }
.more summary { padding: 6px 0; font-size: 14px; font-weight: 500; color: var(--brand); }
.more p, .more dl { font-size: 13px; color: var(--muted); max-width: 78ch; }
.boroughs { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 0 16px; }
.letter-setup { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; align-items: start; }
.letter-form { display: grid; gap: 16px; }
.letter-form label { display: grid; gap: 6px; font-size: 14px; font-weight: 500; color: var(--ink); }
.letter-form input[type="text"] { width: 100%; }
.letter-form h3 { margin: 12px 0 0; font-size: 16px; }
.letter-form .btn { justify-self: start; }
.more dl { display: grid; grid-template-columns: auto 1fr; gap: 4px 14px; margin: 0; }
.more dt { font-family: ui-monospace, Consolas, monospace; font-size: 12px; color: var(--ink); }
.more dd { margin: 0; }
/* The A4 sheet scaled down to fit beside the form, and kept in view while
   the form scrolls past it. */
.letter-preview { position: sticky; top: calc(var(--bar-height) + 12px); }
.letter-frame { background: var(--surface); padding: 12px; border-radius: 16px; overflow: auto; max-height: calc(100vh - 140px); }
.letter-frame .letter { zoom: .58; margin: 0 auto; box-shadow: 0 4px 24px rgba(0, 81, 125, .14); }
/* One sheet for each letter, named above it. */
.letter-frame .eyebrow { margin: 4px 4px 8px; }
.letter-frame .letter + .eyebrow { margin-top: 20px; }

/* Who can sign in: one row a person, with what can be done to their login. */
.logins { list-style: none; margin: 0 0 20px; padding: 0; }
.logins li { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; padding: 12px 0; border-top: 1px solid var(--line); }
.logins li:first-child { border-top: 0; }
.login-who { flex: 1 1 260px; font-weight: 500; color: var(--navy); overflow-wrap: anywhere; }
.login-who .chip { margin-left: 6px; }
.logins .more { margin: 0; }
.logins .more[open] { flex-basis: 100%; order: 3; }
.logins .more form { margin-top: 8px; }
#backup .btn { margin-bottom: 12px; }

/* ---- Results ---- */
.quiet { font-size: 15px; font-weight: 500; color: var(--muted); }
.results-note { max-width: 110ch; margin: 0 0 16px; }
.results { display: grid; gap: 20px; }
.results-table { padding: 22px 4px 4px; }
.results-table h2 { margin: 0 20px 6px; }
.results-table .scroll { margin: 0; }
/* Figures line up down the column; the group's name takes the room left over. */
table.figures td { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
table.figures thead th:not(:first-child) { text-align: right; white-space: nowrap; }
table.figures td, table.figures thead th:not(:first-child) { width: 1%; }
table.figures th, table.figures td { padding: 11px 10px; }
table.figures th:first-child { padding-left: 20px; }
table.figures td:last-child, table.figures thead th:last-child { padding-right: 20px; }
table.figures td.rate { font-weight: 600; color: var(--navy); padding-right: 6px; }
/* Too few letters behind it to be read as a rate. */
table.figures td.rate.is-thin { font-weight: 400; color: var(--soft); }
/* One colour, growing from the left: the bar says no more than the figure beside it. */
table.figures td.rate-bar { width: 96px; min-width: 72px; padding-left: 6px; text-align: left; }
.rate-bar span { display: block; height: 8px; min-width: 2px; border-radius: 0 4px 4px 0; background: var(--brand); }

/* ---- Signing in ---- */
.page.signin { display: grid; justify-items: center; padding-top: 12vh; }
.signin-card { display: grid; gap: 16px; width: 100%; max-width: 440px; padding: 32px; }
.signin-card .lede, .signin-card .notice { margin: 0; }
.signin-card .lede { margin-top: -12px; }
.signin-card label, .password-form label { display: grid; gap: 6px; font-size: 14px; font-weight: 500; color: var(--ink); }
.signin-card input { width: 100%; }
.signin-card .btn { margin-top: 4px; }
.password-form input { width: 320px; }

/* ---- Your settings ---- */
.settings { display: grid; grid-template-columns: repeat(2, minmax(0, 560px)); gap: 20px; align-items: start; }
.settings .panel { margin: 0; }
.picture-form { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 20px 28px; }
/* On a white card, so the circle is tinted where the bar's is white. */
.picture-now .avatar { width: 112px; height: 112px; background: var(--tint); font-size: 36px; }
.picture-form label { display: grid; gap: 6px; font-size: 14px; font-weight: 500; color: var(--ink); }
.picture-form input[type="file"] { max-width: 100%; font: inherit; font-weight: 400; }
.picture-form input[type="file"]::file-selector-button { min-height: 40px; margin-right: 12px; padding: 0 16px; border: 1.5px solid var(--brand); border-radius: 999px; background: #fff; font: inherit; font-weight: 500; color: var(--brand); cursor: pointer; }
.picture-remove { margin-top: 16px; font-size: 14px; }

/* ---- Measuring a room on a drawing ---- */
.measure {
  /* A plan is a wide sheet: the window takes the whole screen. */
  width: calc(100vw - 32px); height: calc(100vh - 32px); max-width: none; max-height: none;
  padding: 0; border: 0; border-radius: 24px; color: var(--ink); overflow: hidden; box-shadow: var(--shadow-panel);
}
.measure[open] { display: flex; flex-direction: column; }
.measure::backdrop { background: rgba(10, 20, 47, .5); }
.measure-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 16px 22px; border-bottom: 1px solid var(--line); }
.measure-head h2, .measure-head .hint { margin: 0; }
.measure-body { flex: 1; min-height: 0; display: grid; grid-template-columns: 350px minmax(0, 1fr); }
.measure-side { display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--line); }
.measure-steps { flex: 1; min-height: 0; overflow-y: auto; padding: 0 22px 16px; }
.measure-side h3 { margin-top: 20px; font-size: 16px; }
.measure-side .link { text-align: left; font-size: 14px; }
.measure-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 10px; font-size: 14px; }
.measure-row input { width: 104px; height: 44px; }
.measure-row .btn { min-height: 40px; padding: 0 16px; }
.measure-file { margin-bottom: 8px; }
.measure-file:focus-within { outline: 2px solid var(--brand); outline-offset: 2px; }
.measure-file-name { font-size: 14px; font-weight: 500; overflow-wrap: anywhere; }
.measure-note { font-size: 14px; font-weight: 500; margin: 10px 0 0; }
.measure-note:empty { display: none; }
/* Stays in view below the steps, however far they scroll. It is the one
   thing in the window waiting on the reader, so it sits on pale blue. */
.measure-result { display: grid; gap: 8px; justify-items: start; padding: 16px 22px 18px; background: var(--highlight); }
.measure-result p, .measure-result .measure-row { margin: 0; }
.measure-area { font-size: 16px; color: var(--muted); }
.measure-area b { font-size: 32px; font-weight: 600; color: var(--navy); font-variant-numeric: tabular-nums; }
.measure-stage { position: relative; min-height: 0; overflow: hidden; background: #8A96A6; touch-action: none; }
.measure-stage canvas { position: absolute; inset: 0; width: 100%; height: 100%; cursor: grab; outline-offset: -4px; }
.measure-stage[data-mode] canvas { cursor: crosshair; }
.measure-stage.is-over { outline: 4px dashed #fff; outline-offset: -12px; }
.measure-empty { position: absolute; inset: 0; margin: 0; display: grid; place-items: center; color: #fff; font-size: 18px; font-weight: 500; pointer-events: none; }
.measure-status { position: absolute; left: 50%; top: 16px; transform: translateX(-50%); margin: 0; padding: 8px 16px; border-radius: 999px; background: var(--card); font-size: 14px; font-weight: 500; box-shadow: var(--shadow-panel); }
/* Bottom left: a drawing's title block, with its scale, is usually bottom right. */
.measure-zoom { position: absolute; left: 14px; bottom: 14px; display: flex; gap: 6px; }
.measure-zoom .btn { min-width: 44px; padding: 0 14px; }

/* Seven tabs with their counts need about 1,450px at full size. On a narrower
   window the bar tightens, then drops its label, before the tabs scroll. */
@media (max-width: 1480px) {
  .top-inner, .top-links { gap: 14px; }
  .tabs a { padding: 7px 11px; font-size: 14px; }
}
@media (max-width: 1320px) { .role { display: none; } }
@media (max-width: 980px) {
  h1 { font-size: 26px; }
  .measure-body { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); }
  .measure-side { max-height: 46vh; border-right: 0; border-bottom: 1px solid var(--line); }
  .listbar { border-radius: 24px; }
  .lead, .lead:has(> .lead-check) { grid-template-columns: minmax(0, 1fr); }
  .lead:has(> .lead-check) { grid-template-columns: auto minmax(0, 1fr); }
  .lead:has(> .lead-check) > .lead-work, .lead:has(> .lead-check) > .lead-actions { grid-column: 2; }
  .lead-work { border-left: 0; padding-left: 0; border-top: 1px solid var(--line); padding-top: 14px; }
  .lead-work:empty { display: none; }
  .lead-actions { flex-direction: row; flex-wrap: wrap; align-items: center; }
  .lead-actions form { display: block; }
  .steps, .letter-setup, .settings { grid-template-columns: minmax(0, 1fr); }
  .write-card { grid-template-columns: auto minmax(0, 1fr); }
  .write-card > :not(.write-tick) { grid-column: 2; }
  .letter-preview { position: static; }
  .letter-frame { max-height: 900px; }
}
@media (max-width: 640px) {
  .top-inner, .page { padding-left: 16px; padding-right: 16px; }
  .brand { display: none; }
  .tabs a { padding: 8px 12px; }
  .picture-form { grid-template-columns: minmax(0, 1fr); }
  .letter-frame .letter { zoom: .42; }
}

/* Setup: the pictures printed on the second letter */
.letterhead { display: grid; gap: 12px; margin-bottom: 24px; }
.letterhead h3 { margin: 0; font-size: 16px; }
.letterhead .btn { justify-self: start; }
.letterhead-slots { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.letterhead-slots label { display: grid; gap: 8px; align-content: start; justify-items: start; font-size: 14px; font-weight: 500; }
.letterhead-slots img { max-height: 56px; max-width: 100%; }
.letterhead-slots input { max-width: 100%; }
@media (max-width: 900px) { .letterhead-slots { grid-template-columns: minmax(0, 1fr); } }

/* ---- Wide screens ----
   A monitor is far wider than it is tall, so height is what runs out. Where
   there is width to spare, what would stack down the page is laid across it:
   more of the work in view at once, less empty card, and less scrolling. The
   rules above remain the layout for a narrower window.

   Each page is picked out by what is on it (the toolbar on Review, #letter
   on Setup), not by a class on <main>, so these need nothing from the
   templates beyond what they already hold. */
@media (min-width: 1200px) {
  /* Results: two tables to a row. */
  .results { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
  /* Less air above the list, so the first rows start higher up the screen. */
  .page { padding-top: 20px; }
  .head { margin-bottom: 14px; }
  .filters { padding: 12px 18px; margin-bottom: 12px; }
  .filters select, .filters input { height: 44px; }
  .filters .btn, .filters > .link { min-height: 44px; }
  .toolbar .views { margin-bottom: 24px; }
  .listbar { min-height: 52px; margin-bottom: 8px; padding-top: 4px; padding-bottom: 4px; }

  /* Review: the fields for the letter sit beside the description, two by two. */
  .toolbar ~ .leads { gap: 10px; }
  .toolbar ~ .leads .lead { padding: 16px 22px; grid-template-columns: minmax(0, 1fr) minmax(430px, 44%) 150px; }
  .toolbar ~ .leads .lead:has(> .lead-check) { grid-template-columns: auto minmax(0, 1fr) minmax(430px, 44%) 150px; }
  .toolbar ~ .leads .lead-work { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 20px; grid-template-areas: "type name" "room fig"; }
  .toolbar ~ .leads .lead-work > :first-child { grid-area: type; }
  .toolbar ~ .leads .lead-work > .room { grid-area: room; }
  .toolbar ~ .leads .lead-work > div.field { grid-area: fig; }
  .toolbar ~ .leads .lead-work > form:nth-child(4) { grid-area: name; }
  /* A field that shares a row with a taller one keeps its own height. */
  .toolbar ~ .leads .lead-work > * { align-content: start; }
  .toolbar ~ .leads .lead-work select, .toolbar ~ .leads .lead-work input { height: 44px; }
  .toolbar ~ .leads .lead-work select { font-size: 14px; padding-left: 14px; }
  /* The room's size and the button to measure it share a line when they fit. */
  .toolbar ~ .leads .room { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
  .toolbar ~ .leads .room > .eyebrow, .toolbar ~ .leads .room > .hint { flex: 0 0 100%; }
  .toolbar ~ .leads .room-input input { width: 86px; padding: 0 14px; }
  .toolbar ~ .leads .room .js-measure { min-height: 40px; padding: 0 12px; font-size: 13px; }
  /* Where to find the surname is the same advice on every row, so it is
     shown for the row being typed in, not printed forty times down the page. */
  .toolbar ~ .leads .lead-work > form:nth-child(4) { position: relative; }
  .toolbar ~ .leads .lead-work > form:nth-child(4) > .hint {
    display: none; position: absolute; z-index: 6; top: 100%; left: 0; right: 0; margin-top: 6px;
    padding: 10px 14px; border-radius: 12px; background: var(--navy); color: #fff; box-shadow: var(--shadow-panel);
  }
  .toolbar ~ .leads .lead-work > form:nth-child(4):focus-within > .hint { display: block; }
  /* Who submitted it and the links to look it up share a line. */
  .toolbar ~ .leads .lead-agent { display: inline-block; margin-right: 18px; }
  .toolbar ~ .leads .lead-links { display: inline-flex; margin-top: 4px; }
  /* Nothing to fill in (set aside, or no work detected): the description keeps the room. */
  .toolbar ~ .leads .lead:has(.work-fixed), .toolbar ~ .leads .lead:has(> .lead-work:empty) { grid-template-columns: minmax(0, 1fr) 250px 150px; }
}
@media (min-width: 1400px) {
  /* Setup: the price table, and who can sign in under it, beside the letter. */
  .page:has(> #letter), .page:has(> .panel > form[action$="/do-not-mail"]) { display: grid; column-gap: 24px; grid-auto-flow: dense; align-items: start; }
  .page:has(> #letter) { grid-template-columns: minmax(0, 640px) minmax(0, 1fr); }
  .page:has(> #letter) > *, .page:has(> .panel > form[action$="/do-not-mail"]) > * { grid-column: 1 / -1; }
  .page:has(> #letter) > .setup-side { grid-column: 1; }
  .page:has(> #letter) > #letter { grid-column: 2; }
  /* Do not mail: the form to add an address stays beside the list. */
  .page:has(> .panel > form[action$="/do-not-mail"]) { grid-template-columns: 440px minmax(0, 1fr); }
  .page:has(> .panel > form[action$="/do-not-mail"]) > .panel { grid-column: 1; position: sticky; top: calc(var(--bar-height) + 16px); }
  .page:has(> .panel > form[action$="/do-not-mail"]) > .card, .page:has(> .panel > form[action$="/do-not-mail"]) > .empty { grid-column: 2; }
}
@media (min-width: 1500px) {
  /* Room for a whole borough, kind of work or firm's name in each filter. */
  .filters select, .filters select[name="weeks"], .filters select[name="state"] { width: 220px; }
  /* Short rows go two to a line, so the eye and the pointer travel less
     between an address and its buttons. */
  .leads:has(> .lead-followup), .leads:has(> .lead-compact) { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
  /* Sent letters: room to record a response without it wrapping. */
  table.sent td:last-child { width: 30%; }
  table.sent .record-box .record { max-width: 560px; }
  .page:has(table.sent) > h2 + .card { max-width: 860px; }
  /* Leads: the client's name, phone and email on one line beside the history. */
  .lead-enquiry { grid-template-columns: minmax(0, 1fr) minmax(0, 760px); }
  .lead-enquiry .lead-contact { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: 16px; }
  .lead-enquiry .lead-contact .btn { grid-column: 1; }
}
@media (min-width: 1600px) {
  /* Review: three columns of fields. The work and its figure; the room to
     measure; the name. */
  .toolbar ~ .leads .lead { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr) 150px; }
  .toolbar ~ .leads .lead:has(> .lead-check) { grid-template-columns: auto minmax(0, 5fr) minmax(0, 6fr) 150px; }
  .toolbar ~ .leads .lead-work { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: auto 1fr; grid-template-areas: "type room name" "fig room name"; }
  .toolbar ~ .leads .lead:has(.work-fixed), .toolbar ~ .leads .lead:has(> .lead-work:empty) { grid-template-columns: minmax(0, 1fr) 250px 150px; }
}
@media (min-width: 1800px) {
  /* Review on a full monitor: one line of fields, read left to right in the
     order the row is worked. What was submitted; the kind of work; the room
     to measure; the figure that gives; the name; then the decision. */
  .toolbar ~ .leads .lead { grid-template-columns: minmax(0, 4fr) minmax(0, 7fr) 150px; }
  .toolbar ~ .leads .lead:has(> .lead-check) { grid-template-columns: auto minmax(0, 4fr) minmax(0, 7fr) 150px; }
  .toolbar ~ .leads .lead-work { grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr) minmax(0, .9fr) minmax(0, 1fr); grid-template-rows: auto; grid-template-areas: "type room fig name"; }
  .toolbar ~ .leads .lead:has(.work-fixed), .toolbar ~ .leads .lead:has(> .lead-work:empty) { grid-template-columns: minmax(0, 1fr) 250px 150px; }
}
