/* Northern Drone app — dark brand UI (deliberately single-look) */

:root {
  /* Tokens matched to northerndrone.com styles.css */
  --bg: #0b0c0e;            /* --ink on the site: page plane */
  --surface: #17191c;       /* card / chart surface — lifted for real separation from --bg */
  --surface-2: #22262b;     /* hover / raised */
  --border: rgba(255, 255, 255, 0.14);
  --ink: #f0f2f4;           /* --light */
  --ink-2: #9aa0a8;         /* --body */
  --ink-text: #d4d8dc;      /* --text */
  --ink-muted: #8b929c;     /* --muted (WCAG AA on both bg and card) */
  --ink-faint: #5c636b;     /* decorative only — not for text */
  --grid: #23272b;
  --gold: #e9a826;          /* site --gold (UI accent) */
  --gold-deep: #c8881a;     /* site --gold2 */
  --series-1: #C98500;      /* validated chart gold */
  --series-2: #3987E5;
  --series-3: #199E70;
  --good: #0CA30C;
  --r: 4px;                 /* site corner radius */
  --serif: "DM Serif Display", Georgia, serif;
  --logo-serif: "EB Garamond", Georgia, serif;
  --sans: "DM Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", monospace;

  /* Type scale. Five small sizes instead of the twenty-odd that had crept in:
     every secondary figure, label and hint sits on one of these. */
  --fs-label: 0.68rem;      /* column headings, KPI labels, badges */
  --fs-xs: 0.74rem;         /* timestamps, hints, counts */
  --fs-sm: 0.8rem;          /* secondary text, form labels */
  --fs-md: 0.85rem;         /* tables, buttons, notices */
  --fs-base: 0.9rem;        /* copy inside cards */

  --border-soft: rgba(255, 255, 255, 0.07);   /* row separators, inner rules */
  --bad: #e05030;
  --ctl-h: 34px;            /* one height for buttons, selects and inputs in a row */

  /* Native controls (selects, date pickers, scrollbars) render dark too. */
  color-scheme: dark;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  scrollbar-color: #3a3f46 transparent;
}

a { color: var(--gold); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---------- Header ---------- */

.topbar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 28px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  position: sticky;
  top: 0;
  z-index: 10;
}

.brand-mark {
  height: 34px; width: auto; object-fit: contain; flex: none;
}

.brand-name {
  font-family: var(--logo-serif);
  font-style: italic;
  font-size: 1.25rem;
  letter-spacing: 0.05em;
  color: var(--gold);
  white-space: nowrap;
}

.topbar .sub {
  color: var(--ink-muted);
  font-family: var(--mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  margin-top: 3px;
}

.topbar .spacer { flex: 1; }

.topbar form { margin: 0; }

/* ---------- Buttons ----------
   One system: the same height, padding, type and corner on every button, in
   three weights. Gold is the one thing to do on a page, ghost is everything
   else, danger is ghost that turns red when you reach for it. */
.btn-ghost, .btn-gold, .btn-danger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: var(--ctl-h);
  padding: 6px 14px;
  border-radius: var(--r);
  font-family: var(--sans);
  font-size: var(--fs-md);
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.btn-ghost {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--ink-2);
}
.btn-ghost:hover { border-color: rgba(255, 255, 255, 0.3); background: var(--surface-2); color: var(--ink); text-decoration: none; }
.btn-sm { min-height: 28px; padding: 3px 10px; font-size: var(--fs-sm); }

/* ---------- Layout ---------- */

.wrap { max-width: 1200px; margin: 0 auto; padding: 26px 28px 60px; }

.page-head {
  display: flex;
  align-items: baseline;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}

.page-head h1 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.7rem;
  margin: 0;
}

.range-picker { display: flex; gap: 6px; margin-left: auto; }

.range-picker button {
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--ink-2);
  border-radius: var(--r);
  padding: 6px 14px;
  font-family: var(--mono);
  font-size: var(--fs-sm);
  cursor: pointer;
}
.range-picker button:hover { color: var(--ink); border-color: var(--gold-deep); }
.range-picker button.active {
  color: #0b0c0e;
  background: var(--gold);
  border-color: var(--gold);
  font-weight: 500;
}

/* ---------- KPI tiles ---------- */

.kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
  margin-bottom: 22px;
}

.kpi {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 14px 16px;
}

/* A KPI that goes somewhere. Same tile, but it says so on hover — a figure
   that tells you to chase something should be the way you get there. */
a.kpi {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.12s ease, background 0.12s ease;
}
a.kpi:hover,
a.kpi:focus-visible {
  border-color: var(--gold);
  background: var(--surface-2, var(--surface));
}

.kpi .label {
  color: var(--ink-muted);
  font-family: var(--mono);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.kpi .value {
  font-size: 1.6rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  margin-top: 4px;
  line-height: 1.2;
}

.kpi .value small { font-size: var(--fs-base); color: var(--ink-2); font-weight: 400; }

/* ---------- Cards / widgets ---------- */

.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

@media (max-width: 900px) { .grid { grid-template-columns: 1fr; } }

.card {
  background: var(--surface);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: var(--r);
  padding: 18px 20px;
  min-width: 0;
}

.card.full { grid-column: 1 / -1; }

.card h2 {
  font-family: var(--sans);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: -0.005em;
  margin: 0 0 10px;
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
/* A heading with a sub-line under it hands the spacing to the sub-line. */
.card h2:has(+ .card-sub) { margin-bottom: 2px; }

.card .card-sub {
  color: var(--ink-muted);
  font-size: var(--fs-sm);
  margin-bottom: 12px;
}

.chart-box { position: relative; height: 240px; }

/* ---------- Tables ---------- */

.data-table { width: 100%; border-collapse: collapse; font-size: var(--fs-md); }
.data-table th {
  text-align: left;
  color: var(--ink-muted);
  font-family: var(--mono);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 400;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  vertical-align: bottom;
}
.data-table td {
  padding: 9px 10px;
  border-bottom: 1px solid var(--border-soft);
  color: var(--ink-text);
  vertical-align: middle;
  /* break-word, not anywhere: only break a word that cannot fit at all.
     "anywhere" was splitting long words to make columns as narrow as
     possible. */
  overflow-wrap: break-word;
}
.data-table td.num {
  font-family: var(--mono); text-align: right; color: var(--ink);
  font-variant-numeric: tabular-nums;
  /* A figure must never break. $10500.00 wrapped to "$1050" above "0.00"
     reads as a different, much smaller number. Let the column widen. */
  overflow-wrap: normal;
  word-break: keep-all;
}
.data-table th.num { text-align: right; }
.data-table thead th { position: sticky; top: 63px; background: var(--surface); z-index: 2; }
/* A row jumped to by its anchor lands below the sticky header and the
   sticky column headings, not under them. */
.data-table tbody tr[id] { scroll-margin-top: 120px; }
.data-table tbody tr:hover td { background: rgba(255, 255, 255, 0.03); }
/* The last row of a table in a card ends at the card, not at one more rule. */
.card > .data-table > tbody > tr:last-child > td,
.card > .data-table:last-child tbody tr:last-child td { border-bottom: none; }
.data-table td a:not(.btn-ghost):not(.btn-gold):not(.badge) { font-weight: 500; }
/* A text column with many break points (project name over customer) is the
   one the browser squeezes first; hold it open. */
.data-table td.col-wide { min-width: 170px; }

/* ---------- Empty states ---------- */

.empty-state {
  text-align: center;
  padding: 32px 16px 28px;
  color: var(--ink-2);
  font-size: var(--fs-base);
  border: 1px dashed var(--border);
  border-radius: var(--r);
}
.empty-state .glyph { font-size: 1.4rem; display: block; margin-bottom: 8px; color: var(--gold-deep); opacity: 0.8; }
.empty-state .btn-gold, .empty-state .btn-ghost { margin-top: 12px; }

/* ---------- Focus visibility (keyboard nav on dark bg) ---------- */

a:focus-visible, button:focus-visible, select:focus-visible,
input:focus-visible, textarea:focus-visible, summary:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

/* ---------- Notices ---------- */

.notice {
  border: 1px dashed var(--border);
  border-radius: var(--r);
  padding: 16px 18px;
  color: var(--ink-muted);
  font-size: var(--fs-md);
  background: var(--surface);
}

.notice strong { color: var(--ink-2); }

/* One treatment for "this needs attention", in three severities, so a pilot
   missing a certificate and a job that loses money read as the same kind of
   thing. They used to be near-identical boxes built by hand: the money
   warning through .notice, the compliance one through an inline
   border-color:#e05030 on the same element. Same intent, two implementations,
   and only one of them followed a theme change. Solid rather than dashed,
   because a flagged box is a statement, not a placeholder. */
.notice-bad, .notice-warn, .notice-good { border-style: solid; }
.notice-bad { border-color: rgba(224, 80, 48, 0.65); }
.notice-warn { border-color: rgba(233, 168, 38, 0.5); }
.notice-good { border-color: rgba(12, 163, 12, 0.4); }

.freshness {
  margin-top: 22px;
  color: var(--ink-muted);
  font-family: var(--mono);
  font-size: var(--fs-xs);
}

/* ---------- Login ---------- */

.login-shell {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
}

.login-card {
  width: 100%;
  max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 34px 32px;
  text-align: center;
}

.login-card .brand-lockup { width: 190px; max-width: 70%; margin: 0 auto 6px; display: block; }

.login-card h1 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.5rem;
  margin: 0 0 2px;
}

.login-card .sub {
  color: var(--ink-muted);
  font-family: var(--mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  margin-bottom: 24px;
}

.login-card label {
  display: block;
  text-align: left;
  color: var(--ink-2);
  font-size: var(--fs-sm);
  margin: 14px 0 5px;
}

.login-card input[type="text"],
.login-card input[type="password"] {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r);
  color: var(--ink);
  padding: 10px 12px;
  font-family: var(--sans);
  font-size: 0.95rem;
}
.login-card input:focus { outline: 2px solid var(--gold-deep); outline-offset: 1px; border-color: transparent; }

.btn-primary {
  width: 100%;
  margin-top: 22px;
  background: var(--gold);
  border: none;
  border-radius: var(--r);
  color: #0b0c0e;
  font-family: var(--sans);
  font-weight: 700;
  font-size: 0.95rem;
  padding: 11px;
  cursor: pointer;
}
.btn-primary:hover { background: var(--gold-deep); }

.errorlist { list-style: none; padding: 0; margin: 0 0 6px; color: #E66767; font-size: var(--fs-md); }

/* ---------- Top navigation ---------- */

.topnav { display: flex; gap: 4px; margin-left: 18px; }
.topnav a {
  color: var(--ink-2);
  font-size: var(--fs-base);
  padding: 6px 12px;
  border-radius: var(--r);
  text-decoration: none;
}
.topnav a:hover { color: var(--ink); background: var(--surface-2); text-decoration: none; }
.topnav a.on { color: var(--gold); background: var(--surface-2); box-shadow: inset 0 -2px 0 var(--gold); }

/* Grouped dropdowns */
.nav-group { position: relative; }
.nav-group > summary {
  list-style: none; cursor: pointer;
  color: var(--ink-2); font-size: var(--fs-base);
  padding: 6px 12px; border-radius: var(--r);
  display: flex; align-items: center; gap: 5px;
  user-select: none;
}
.nav-group > summary::-webkit-details-marker { display: none; }
.nav-group > summary::after {
  content: ""; width: 7px; height: 7px; margin-top: -3px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg); opacity: 0.7;
}
.nav-group[open] > summary::after { transform: rotate(225deg); margin-top: 3px; }
.nav-group > summary:hover { color: var(--ink); background: var(--surface-2); }
.nav-group.on > summary { color: var(--gold); background: var(--surface-2); box-shadow: inset 0 -2px 0 var(--gold); }
.nav-menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 40;
  min-width: 160px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 6px; padding: 6px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
}
.nav-menu a {
  display: block; padding: 8px 12px; border-radius: var(--r);
  color: var(--ink-text); font-size: var(--fs-base);
  /* "Business expenses" wrapped onto two lines inside a 160px menu and read
     as two separate items. A menu entry is one line or it is not one item. */
  white-space: nowrap;
}
.nav-menu a:hover { background: rgba(255, 255, 255, 0.06); text-decoration: none; }
.nav-menu a.on { color: var(--gold); }

/* The menu grew from five items to eight when Sales, Revenue, Company and
   Marketing replaced one nine-item "Money". On a 1280 or 1366 laptop that no
   longer fits beside the brand and the buttons, and the last group would have
   dropped off the right-hand edge with nothing to say it was there. Below
   1400px the bar becomes two rows: brand and buttons on top, the whole menu
   underneath, still one line, nothing hidden. */
@media (min-width: 901px) and (max-width: 1399px) {
  .topbar { flex-wrap: wrap; row-gap: 8px; padding: 12px 20px; }
  .topnav { order: 10; flex-basis: 100%; margin-left: 0; }
}
/* Not overflow:auto on the bar. `overflow-x: auto` forces `overflow-y` to
   auto as well, and every dropdown would be clipped to the height of the
   header — the menus would open into a 34px slot. The bar wraps instead. */
.topnav { min-width: 0; flex-wrap: wrap; row-gap: 4px; }

/* Hamburger + off-canvas drawer (mobile) */
.hamburger {
  display: none; background: none; border: 1px solid var(--border); border-radius: var(--r);
  width: 40px; height: 40px; align-items: center; justify-content: center;
  color: var(--ink-2); cursor: pointer; flex: none;
}
.hamburger:hover { color: var(--ink); border-color: var(--gold-deep); }
.search-btn {
  display: none; background: none; border: 1px solid var(--border); border-radius: var(--r);
  width: 40px; height: 40px; align-items: center; justify-content: center;
  color: var(--ink-2); cursor: pointer; flex: none; font-size: 1rem;
}
.drawer-overlay {
  position: fixed; inset: 0; background: rgba(0, 0, 0, 0.55); z-index: 50;
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
}
.drawer-overlay.open { opacity: 1; pointer-events: auto; }
.mobile-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(320px, 86vw); z-index: 51;
  background: var(--surface); border-left: 1px solid var(--border);
  transform: translateX(100%); transition: transform 0.22s ease;
  display: flex; flex-direction: column; overflow-y: auto;
}
.mobile-drawer.open { transform: translateX(0); }
/* Without this a drag inside the drawer chains to the page behind it, which
   is what "slide right and the screen moves" is. */
.mobile-drawer { overscroll-behavior: contain; touch-action: pan-y; }
/* The page itself is pinned while the drawer is open; see the drawer script.
   Keeping the offset here means the page does not jump back to the top. */
body.drawer-open { position: fixed; width: 100%; overflow: hidden; }
.drawer-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; border-bottom: 1px solid var(--border);
}
.drawer-header .brand-name { font-size: 1.05rem; }
.drawer-close {
  background: none; border: 1px solid var(--border); border-radius: var(--r);
  width: 36px; height: 36px; color: var(--ink-2); cursor: pointer; font-size: 1rem;
}
.drawer-section { padding: 12px 16px; border-bottom: 1px solid var(--border); }
.drawer-label {
  font-family: var(--mono); font-size: var(--fs-label); letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-muted); margin-bottom: 4px;
}
.drawer-section a, .drawer-section button.drawer-item {
  display: flex; align-items: center; width: 100%;
  min-height: 44px; padding: 0 8px; border-radius: var(--r);
  color: var(--ink-text); font-size: 0.95rem; text-decoration: none;
  background: none; border: none; font-family: var(--sans); cursor: pointer; text-align: left;
}
.drawer-section a:hover { background: var(--surface-2); text-decoration: none; }
/* A group you open rather than scroll past. The chevron says which way it
   goes; the label is the tap target, sized for a thumb rather than a cursor. */
.drawer-group > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center;
  justify-content: space-between; gap: 8px; padding: 6px 0; margin-bottom: 2px;
}
.drawer-group > summary::-webkit-details-marker { display: none; }
.drawer-group > summary::after {
  content: "\203A"; transform: rotate(90deg); transition: transform 0.15s;
  color: var(--ink-muted); font-size: 1.1rem; line-height: 1;
}
.drawer-group[open] > summary::after { transform: rotate(-90deg); }
.drawer-group[open] > summary { color: var(--gold); }
.drawer-section a.on { color: var(--gold); font-weight: 600; }

/* ---------- Leads ---------- */

/* ---------- Badges ----------
   One shape for every status chip: a pill with a faint wash of its own
   colour, so a row of them reads as colour first and words second. The
   colour classes below only set color and border-color. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--mono);
  font-size: var(--fs-label);
  font-weight: 500;
  line-height: 1.4;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 2px 9px;
  border-radius: 999px;
  border: 1px solid var(--border);
  color: var(--ink-2);
  background: color-mix(in srgb, currentColor 9%, transparent);
  vertical-align: middle;
  /* A pill broken over two lines reads as a box with a word missing. */
  white-space: nowrap;
}
.badge-quote { color: var(--gold); border-color: var(--gold-deep); }
.badge-pilot { color: #3ba8d4; border-color: rgba(59,168,212,0.5); }
.badge-svc { color: var(--ink-2); }
.badge-closed { color: var(--ink-muted); border-color: var(--border); }

.lead-row.status-new td { background: rgba(233,168,38,0.04); }
.lead-row td { vertical-align: top; }

.status-select {
  background: var(--bg);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: var(--r);
  font-family: var(--sans);
  font-size: var(--fs-md);
  padding: 5px 8px;
}
.status-select:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px rgba(233, 168, 38, 0.18); }

/* Checkboxes and radios opt out of the full-width form input sizing. This used
   to be repeated as an inline style on every one of them. */
input[type="checkbox"], input[type="radio"] { width: auto; }

/* A wrapper for a checkbox that has no text beside it. Same size as the box on
   a mouse; a thumb-sized target on a touchscreen (see the touch block below). */
.cb-hit { display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }

/* ---------- CRM ---------- */

.btn-gold {
  background: var(--gold);
  color: #0b0c0e;
  border: 1px solid var(--gold);
  font-weight: 600;
}
.btn-gold:hover { background: var(--gold-deep); border-color: var(--gold-deep); text-decoration: none; }
.btn-gold:disabled, .btn-ghost:disabled { opacity: 0.55; cursor: default; }

.page-head .btn-gold { margin-left: auto; }

.filter-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
/* The hidden attribute wins over every display rule above and below: a
   flex row marked hidden (the uploader's Start/Clear before anything is
   picked, a form field that does not apply) was still showing. */
[hidden] { display: none !important; }
/* A filter bar with three or more controls lays out as a grid: the search
   box on its own line, the dropdowns in even columns under it, the buttons
   together at the end — instead of a row that wraps wherever it runs out.
   The same rule on every list page, so they all read alike. */
form.filter-row[method="get"]:has(select ~ select) {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 8px; align-items: center;
}
form.filter-row[method="get"]:has(select ~ select) > .search-input { grid-column: 1 / -1; width: 100%; min-width: 0; }
form.filter-row[method="get"]:has(select ~ select) > select { width: 100%; min-width: 0; max-width: none; }
form.filter-row[method="get"]:has(select ~ select) > .btn-ghost,
form.filter-row[method="get"]:has(select ~ select) > .btn-gold { justify-self: start; }
form.filter-row[method="get"]:has(select ~ select) > .filter-actions { display: flex; gap: 8px; align-items: center; }
/* What the list adds up to, in one quiet strip under the filters. */
.stat-strip {
  display: flex; flex-wrap: wrap; gap: 6px 18px; align-items: center;
  margin: 0 0 12px; padding: 9px 12px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r);
  font-size: var(--fs-md); color: var(--ink-2);
}
.stat-strip strong { color: var(--ink); }
.stat-strip .stat-actions { margin-left: auto; display: flex; gap: 8px 14px; flex-wrap: wrap; align-items: center; }
.stat-strip form { margin: 0; }
.stat-strip .btn-ghost { font-size: var(--fs-xs); padding: 5px 10px; min-height: 0; }
@media (max-width: 768px) {
  .stat-strip .stat-actions { margin-left: 0; width: 100%; }
}
.search-input {
  flex: 1; min-width: 200px;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--r);
  color: var(--ink); padding: 8px 12px; font-family: var(--sans); font-size: var(--fs-base);
}
.search-input:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px rgba(233, 168, 38, 0.18); }
/* A short field in a row — a rate, a reference, a date — sized by class so
   the phone block below can widen it, which an inline width never let it. */
.input-short { flex: 0 0 120px; min-width: 120px; }
.input-shorter { flex: 0 0 90px; min-width: 90px; }
input[type="date"].input-short { flex-basis: 170px; min-width: 170px; }

/* The jobs board's status badge is a <button> (it becomes the dropdown when
   clicked): it keeps the badge's look, not the browser's grey button fill. */
button.status-badge {
  cursor: pointer; appearance: none; -webkit-appearance: none;
  font-family: var(--mono); font-size: var(--fs-label); text-transform: uppercase; letter-spacing: 0.06em;
}
button.status-badge:hover, button.status-badge:focus-visible { border-color: var(--gold); outline: none; }
/* The dropdown sits over the badge instead of pushing the column wider. */
.status-pick { position: relative; display: inline-block; }
.status-pick .status-live { position: absolute; left: 0; top: 50%; transform: translateY(-50%); z-index: 20; min-width: 170px; white-space: nowrap; }
.badge-active { color: var(--good); border-color: rgba(67,176,107,0.5); }
.badge-on_hold { color: var(--gold); border-color: rgba(233,168,38,0.5); }        /* a project paused */
.badge-complete { color: var(--ink-muted); border-color: var(--border); }          /* a project done */
/* The same three severities the notice boxes use, on a badge. */
.badge-bad { color: #e05030; border-color: rgba(224, 80, 48, 0.6); }
.badge-warn { color: var(--gold); border-color: rgba(233, 168, 38, 0.5); }

/* ---------------------------------------------------------------------------
   A job's state, at a glance.
   Ten job statuses all rendered in the same grey pill, so a board of thirty
   jobs was thirty identical chips you had to read one word at a time. The
   colours are the ones the job map already uses, so a pin and a row agree:
     gold   waiting on somebody
     blue   under way
     teal   flown, ours now
     green  finished and paid
     red    came back
     muted  cancelled
--------------------------------------------------------------------------- */
.badge-job-assigned   { color: var(--gold); border-color: var(--gold-deep); }
.badge-job-accepted,
.badge-job-in_progress { color: var(--series-2); border-color: rgba(57,135,229,0.55); }
.badge-job-captured,
.badge-job-submitted  { color: var(--series-3); border-color: rgba(25,158,112,0.55); }
.badge-job-approved,
.badge-job-ready_pay  { color: var(--series-3); border-color: rgba(25,158,112,0.55); }
.badge-job-paid       { color: var(--good); border-color: rgba(12,163,12,0.55); }
.badge-job-rejected   { color: #e05030; border-color: rgba(224,80,48,0.6); }
.badge-job-cancelled  { color: var(--ink-muted); border-color: var(--border); }
.badge-prospect { color: var(--gold); border-color: var(--gold-deep); }
.badge-past { color: var(--ink-muted); }
.badge-inactive { color: var(--ink-muted); border-style: dashed; }
.badge-lost { color: #e05030; border-color: rgba(224, 80, 48, 0.5); }

.inv-row.inv-overdue td { background: rgba(224,80,48,0.07); }
.inv-row.inv-paid td .status-select { color: var(--good); }

.stacked-form .form-field { margin-bottom: 12px; }
.stacked-form label { display: block; color: var(--ink-2); font-size: var(--fs-sm); margin-bottom: 4px; }
.stacked-form input, .stacked-form select, .stacked-form textarea {
  width: 100%; background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--r); color: var(--ink); padding: 8px 12px;
  font-family: var(--sans); font-size: var(--fs-base);
}
.stacked-form input:focus, .stacked-form select:focus, .stacked-form textarea:focus {
  outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px rgba(233, 168, 38, 0.18);
}
/* The rule above stretched a checkbox to the full width of the form and
   gave it a text box's border: a 900px-wide outlined bar with a tiny tick
   in the middle, beside "Save it anyway". A tick box is a tick box. */
.stacked-form input[type="checkbox"]:not(.svc-card input),
.stacked-form input[type="radio"]:not(.svc-card input) {
  width: 18px; height: 18px; padding: 0; border: 0; background: none; flex: 0 0 auto;
  accent-color: var(--gold); margin: 0;
}
.stacked-form label:has(> input[type="checkbox"]) { display: flex; align-items: center; gap: 8px; color: var(--ink); font-size: var(--fs-base); }
.field-error { color: #e05030; font-size: var(--fs-sm); margin-top: 3px; }

/* Messages float over the top of whatever page comes next, one under the
   other, over the menu bar if that is where they land: nothing on the page
   moves to make room for them, and each one closes. */
.flash-stack {
  position: fixed; top: 12px; right: 16px; z-index: 60;
  width: min(560px, calc(100vw - 32px));
  display: flex; flex-direction: column; gap: 8px; pointer-events: none;
}
.flash-stack .flash {
  pointer-events: auto; margin: 0; display: flex; gap: 10px; align-items: flex-start;
  background: var(--surface); box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  animation: flash-in 0.2s ease-out; transition: opacity 0.25s, transform 0.25s;
}
.flash-stack .flash-text { flex: 1; }
.flash-x {
  background: none; border: none; color: var(--ink-muted); cursor: pointer;
  font-size: 1.15rem; line-height: 1; padding: 0 2px; margin: -2px -4px 0 0;
}
.flash-x:hover { color: var(--ink); }
.flash.flash-out { opacity: 0; transform: translateY(-6px); }
@keyframes flash-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@media (max-width: 768px) { .flash-stack { top: 8px; right: 8px; width: calc(100vw - 16px); } }
.flash { margin-bottom: 14px; border-style: solid; }
.flash-success { border-color: rgba(67,176,107,0.5); color: var(--ink-2); }
.flash-error { border-color: rgba(224,80,48,0.6); color: var(--ink-2); }
/* A warning is not a confirmation. "Saved at a loss" and "their paperwork
   isn't in order" were rendering in the same dashed grey as "Saved." */
.flash-warning { border-color: var(--gold-deep); color: var(--ink-2); }
.flash-info { border-color: rgba(57,135,229,.55); color: var(--ink-2); }
.flash { font-size: 0.95rem; color: var(--ink); }
.flash strong { color: var(--ink); }

/* ---------- Notes ---------- */

.notes-list { display: flex; flex-direction: column; gap: 10px; max-height: 420px; overflow-y: auto; }
.note-item { border-left: 2px solid var(--gold-deep); padding: 4px 12px; }
.note-time { color: var(--ink-muted); font-family: var(--mono); font-size: var(--fs-label); }
.note-text { color: var(--ink-text); font-size: var(--fs-base); white-space: pre-line; }

.badge-outreach { color: #b48ce6; border-color: rgba(180,140,230,0.5); }
.btn-danger { background: transparent; border: 1px solid var(--border); color: var(--ink-2); }
.btn-danger:hover { border-color: var(--bad); color: var(--bad); background: rgba(224, 80, 48, 0.08); text-decoration: none; }

.lead-row.status-won td { background: rgba(67,176,107,0.05); }
.lead-row.status-lost td, .lead-row.status-archived td { opacity: 0.55; }

/* ---------- Costs ---------- */

.sub-inactive td { opacity: 0.5; }
.sub-inactive td a { color: var(--ink-muted); }
.net-pos { color: var(--good); }
.net-neg { color: #e05030; }

/* ---------- Command palette (Ctrl/Cmd+K) ---------- */

.palette-overlay {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(0, 0, 0, 0.55);
  display: none;
  padding: 12vh 16px 0;
}
.palette-overlay.open { display: block; }
.palette {
  max-width: 560px; margin: 0 auto;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 6px; overflow: hidden;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.6);
}
.palette input {
  width: 100%; border: none; border-bottom: 1px solid var(--border);
  background: var(--surface); color: var(--ink);
  font-family: var(--sans); font-size: 1rem; padding: 14px 16px;
}
.palette input:focus { outline: none; }
.palette-results { max-height: 46vh; overflow-y: auto; }
.palette-results a {
  display: flex; gap: 10px; align-items: baseline;
  padding: 9px 16px; color: var(--ink-text); font-size: var(--fs-base);
  text-decoration: none;
}
.palette-results a .kind {
  font-family: var(--mono); font-size: var(--fs-label); text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--ink-muted); min-width: 74px;
}
.palette-results a .extra { color: var(--ink-muted); font-size: var(--fs-sm); margin-left: auto; }
.palette-results a:hover, .palette-results a.sel { background: var(--surface-2); text-decoration: none; }
.palette-hint {
  padding: 8px 16px; color: var(--ink-muted);
  font-family: var(--mono); font-size: var(--fs-label);
  border-top: 1px solid var(--border);
}
.kbd-hint {
  border: 1px solid var(--border); border-radius: 3px;
  font-family: var(--mono); font-size: var(--fs-label);
  color: var(--ink-muted); padding: 2px 6px; cursor: pointer;
  background: none;
}
.kbd-hint:hover { color: var(--ink); border-color: var(--gold-deep); }

.invite-link { width: 280px; max-width: 100%; }
@media (max-width: 700px) { .invite-link { width: 100%; } .data-table.stack td[data-label=""]::before { content: none; } }

/* ---------- Profitability groups (Reports) ---------- */

.fin-group { border: 1px solid var(--border); border-radius: var(--r); margin-bottom: 8px; }
.fin-group > summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 12px 14px;
}
.fin-group > summary::-webkit-details-marker { display: none; }
.fin-group > summary::before {
  content: ""; width: 7px; height: 7px; flex: none;
  border-right: 1.5px solid var(--ink-muted); border-bottom: 1.5px solid var(--ink-muted);
  transform: rotate(-45deg); transition: transform 0.15s ease;
}
.fin-group[open] > summary::before { transform: rotate(45deg); }
.fin-group > summary:hover { background: rgba(255, 255, 255, 0.02); }
.fin-name { font-weight: 700; color: var(--ink); }
.fin-count { color: var(--ink-muted); font-size: var(--fs-xs); font-weight: 400; margin-left: 8px; }
.fin-figs { display: flex; gap: 22px; margin-left: auto; flex-wrap: wrap; }
.fin-fig { font-family: var(--mono); font-size: var(--fs-md); color: var(--ink); font-variant-numeric: tabular-nums; }
.fin-fig .fin-label {
  display: block; color: var(--ink-muted); font-size: 0.6rem;
  text-transform: uppercase; letter-spacing: 0.1em;
}
.fin-group > table, .fin-group .data-table { padding: 0 14px; }
.fin-group .data-table { width: calc(100% - 28px); margin-left: 14px !important; }
.fin-group .data-table thead th { position: static; }
@media (max-width: 768px) {
  .fin-figs { gap: 14px; margin-left: 21px; width: 100%; }
  .fin-group .data-table { width: calc(100% - 16px); margin-left: 8px !important; }
}

/* ---------- KPI number alignment ---------- */

.kpi .value { font-variant-numeric: tabular-nums lining-nums; }

/* ---------- Metrics widgets loading state (htmx range swaps) ---------- */

#widgets.htmx-request { opacity: 0.45; transition: opacity 0.15s ease; }

/* ---------- Wide numeric grids: scroll + sticky first column ---------- */

.wide-grid-wrap { overflow-x: auto; scrollbar-width: thin; }
.wide-grid th:first-child, .wide-grid td:first-child {
  position: sticky; left: 0; z-index: 1;
  background: var(--surface);
}

/* ---------- Mobile ---------- */

@media (max-width: 900px) {
  .topnav { display: none; }
  .hamburger { display: flex; }
  .search-btn { display: flex; }
  .kbd-hint { display: none; }
  .topbar { padding: 10px 12px; }
  .topbar .sub { display: none; }
  .brand-mark { height: 28px; }
  .topbar .desktop-only { display: none; }   /* Admin/Sign out live in the drawer */
}

@media (min-width: 901px) {
  .drawer-overlay, .mobile-drawer { display: none; }
}

@media (max-width: 768px) {
  body { overflow-x: clip; }
  .wrap { padding: 16px 12px 48px; }
  .card { padding: 14px 14px; }
  /* Only cards holding something that can be wide get a scroll container. It
     used to be every card, which gave a KPI tile with one number in it a
     scrollbar and a rubber-band to go with it. Tables stay in the list even
     when they stack: .stack only stacks below 700px, so between 701 and 768
     a stacked table is still a wide table. Where content fits, no scrollbar
     appears anyway. */
  .card:not(.stack-card):has(table),
  .card:not(.stack-card):has(.pipeline),
  .card:not(.stack-card):has(pre) { overflow-x: auto; }
  .data-table thead th { position: static; }
  .page-head { margin-bottom: 14px; }
  .kpi-row { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
  /* Two tiles across a 390px phone leaves about 144px of room, and a figure
     like $52,650.00 wants 157px at the desktop size. Shrink the number rather
     than let it push into the padding. */
  .kpi .value { font-size: 1.45rem; }
  /* Filter chip rows (Leads, Metrics ranges) wrap instead of running off screen */
  .range-picker { flex-wrap: wrap; margin-left: 0; row-gap: 6px; width: 100%; }
  .range-picker button { padding: 6px 10px; font-size: var(--fs-xs); }
  .filter-row .search-input { min-width: 140px; }
  /* Five dropdowns one under the other filled a phone screen before the
     list began. Two to a row halves that. */
  form.filter-row[method="get"]:has(select ~ select) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  form.filter-row[method="get"]:has(select ~ select) > .filter-actions { grid-column: 1 / -1; }
  .card { padding: 14px 12px; }
}

/* Stacked label:value tables — rows become cards, no sideways scroll.
   Applies only to tables marked .stack whose cells carry data-label. */
@media (max-width: 700px) {
  .data-table.stack { min-width: 0; }
  .data-table.stack thead { display: none; }
  .data-table.stack, .data-table.stack tbody,
  .data-table.stack tr, .data-table.stack td { display: block; width: 100%; }
  .data-table.stack tbody tr {
    border: 1px solid var(--border); border-radius: var(--r);
    margin-bottom: 10px; padding: 4px 10px;
    background: rgba(255, 255, 255, 0.015);
  }
  .data-table.stack td {
    display: flex; justify-content: space-between; align-items: center; gap: 12px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05); padding: 8px 2px;
    /* break-word, not anywhere: "anywhere" lets the browser count a word's
       narrowest possible break when it sizes the flex item, which snapped
       "FlyGuys" into "FlyGuy" and a lonely "s". This only breaks a word that
       genuinely cannot fit. */
    text-align: right; overflow-wrap: break-word;
  }
  .data-table.stack td:last-child { border-bottom: none; }
  .data-table.stack td.num { text-align: right; }
  .data-table.stack td::before {
    content: attr(data-label);
    color: var(--ink-muted); font-family: var(--mono);
    font-size: var(--fs-label); font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.06em;
    text-align: left; flex-shrink: 0;
  }
  .data-table.stack td:not([data-label])::before { content: none; }

  /* A flex cell drops <br> on the floor — its text runs become separate flex
     items and sit side by side, so "project name / customer" collapsed onto
     one line. Cells that hold only text go back to being blocks with the
     label pinned beside them, which is what the desktop table looks like.
     Cells with a control in them keep the flex layout, which sizes those
     properly. */
  .data-table.stack td[data-label]:not(:has(form)):not(:has(select)):not(:has(input)):not(:has(button)) {
    display: block;
    position: relative;
    padding: 8px 2px 8px 38%;
    min-height: 34px;
  }
  .data-table.stack td[data-label]:not(:has(form)):not(:has(select)):not(:has(input)):not(:has(button))::before {
    position: absolute;
    left: 2px;
    top: 10px;
    width: 34%;
  }
  .data-table.stack tbody tr:hover td { background: none; }

  /* Two-column label/value tables: keep both columns on screen, wrap long values. */
  .data-table.kv td:first-child { width: 34% !important; min-width: 0; }
  .data-table.kv td { overflow-wrap: break-word; }
}

/* ---------------------------------------------------------------------------
   Schedule calendar
   A month grid where each cell is a day and each chip is a job, colour-keyed
   by service line. Scrolls horizontally on narrow screens rather than
   squeezing seven columns into a phone.
--------------------------------------------------------------------------- */
.cal-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-bottom: 12px;
}
.cal-nav { display: flex; align-items: center; gap: 6px; }
.cal-nav .btn-ghost { padding: 5px 11px; text-decoration: none; }
.cal-title { font-size: 1.05rem; color: var(--ink); min-width: 148px; text-align: center; }
.cal-filters { display: flex; gap: 8px; flex-wrap: wrap; margin-left: auto; }

.cal-summary {
  display: flex; gap: 16px; flex-wrap: wrap; align-items: center;
  color: var(--ink-muted); font-size: var(--fs-md); margin-bottom: 10px;
}
.cal-alert { color: var(--gold); }

.cal-legend { display: flex; gap: 10px 14px; flex-wrap: wrap; margin-bottom: 12px; }
.cal-key {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-xs); color: var(--ink-muted);
}
.cal-key i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }

.cal-scroll { overflow-x: auto; }


.cal { width: 100%; border-collapse: collapse; table-layout: fixed; min-width: 720px; }
.cal th {
  font-family: var(--mono); font-size: var(--fs-label); letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--ink-muted); font-weight: 600;
  padding: 6px 8px; text-align: left; border-bottom: 1px solid var(--border);
}
.cal-cell {
  vertical-align: top; height: 108px; width: 14.28%;
  border: 1px solid rgba(255, 255, 255, 0.07);
  padding: 5px 5px 7px; background: transparent;
}
.cal-cell.out { opacity: 0.38; }
.cal-cell.today { background: rgba(233, 168, 38, 0.06); border-color: var(--gold); }
.cal-cell.clash { background: rgba(208, 70, 59, 0.07); }

.cal-day { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
.cal-num {
  font-family: var(--mono); font-size: var(--fs-xs); color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.cal-cell.today .cal-num { color: var(--gold); font-weight: 700; }
.cal-clash { font-size: var(--fs-xs); color: var(--gold); }

.cal-job {
  display: block; text-decoration: none; margin-bottom: 3px;
  padding: 3px 6px; border-left: 3px solid var(--svc, var(--ink-muted));
  background: rgba(255, 255, 255, 0.04); border-radius: 2px;
  overflow: hidden;
}
.cal-open { color: inherit; text-decoration: none; }
.cal-open:hover { color: var(--gold); text-decoration: underline; }
.cal-job:hover { background: rgba(255, 255, 255, 0.09); }
.cal-job-title {
  /* Two lines, not one chopped one: the end of a title is where the acreage,
     crop or field number lives. The tooltip carries the whole thing. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  font-size: var(--fs-xs); color: var(--ink); line-height: 1.25;
  overflow: hidden; overflow-wrap: anywhere;
}
.cal-job-sub {
  display: block; font-size: var(--fs-label); color: var(--ink-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ---------------------------------------------------------------------------
   The month on a phone
   Seven columns of job chips needs 720px, and dragging that sideways inside a
   card that also scrolls is how you end up pushing the whole page around. At
   this width the grid keeps its shape but drops to day numbers and a dot per
   job, colour-keyed the same way. Tap a day to see what's on it.
--------------------------------------------------------------------------- */
@media (max-width: 700px) {
  .cal-scroll { overflow-x: visible; }
  .cal { min-width: 0; }
  .cal th { font-size: 0.58rem; padding: 4px 2px; text-align: center; }
  .cal-cell { height: auto; min-height: 58px; padding: 4px 2px; }
  .cal-day { justify-content: center; gap: 3px; margin-bottom: 3px; }
  .cal-num { font-size: var(--fs-xs); }
  /* Each job becomes a dot in its service colour, and the dots stop being
     targets — at 9px they never were. The day number is the button. */
  .cal-job {
    display: block; width: 9px; height: 9px; padding: 0; margin: 0;
    border-radius: 50%; border: none; overflow: hidden;
    background: var(--svc, var(--series-1));
    pointer-events: none;
  }
  .cal-job-title, .cal-job-sub { display: none; }
  .cal-dots { display: flex; flex-wrap: wrap; justify-content: center; gap: 3px; }
  .cal-more { font-size: 0.6rem; text-align: center; display: block; padding: 2px 0; }
  .cal-cell a.cal-open {
    display: flex; align-items: center; justify-content: center;
    min-height: 34px; min-width: 34px; font-weight: 600; color: var(--gold);
  }
}


.sched-cols {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 16px; margin-top: 16px;
}

@media (max-width: 768px) {
  .cal-filters { margin-left: 0; width: 100%; }
  .cal-cell { height: 92px; }
}

/* Pre-flight briefing panel on the job page */
.brief-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px; margin-top: 10px;
}
.brief-box { border: 1px solid var(--border); border-radius: 3px; padding: 12px 14px; }
.brief-box .h {
  font-family: var(--mono); font-size: var(--fs-label); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-muted); display: block; margin-bottom: 5px;
}
.brief-box .v { color: var(--ink); font-size: 1.02rem; }
.brief-box .d { color: var(--ink-muted); font-size: var(--fs-sm); margin-top: 4px; display: block; }
.brief-box.clear { border-left: 3px solid var(--good); }
.brief-box.ok { border-left: 3px solid var(--good); }
.brief-box.tight { border-left: 3px solid var(--gold); }
.brief-box.blocked { border-left: 3px solid #e05030; }
.brief-flags { margin-top: 8px; display: flex; gap: 6px; flex-wrap: wrap; }

/* Address suggestion combobox */
.addr-wrap { position: relative; }
.addr-list {
  position: absolute; left: 0; right: 0; top: calc(100% + 2px); z-index: 40;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 3px; max-height: 260px; overflow-y: auto;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.35);
}
.addr-list:empty { display: none; }
.addr-item {
  display: block; width: 100%; text-align: left; background: none;
  border: none; border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  color: var(--ink-2); font: inherit; font-size: var(--fs-md);
  padding: 8px 11px; cursor: pointer;
}
.addr-item:last-child { border-bottom: none; }
.addr-item:hover, .addr-item[aria-selected="true"] { background: rgba(233, 168, 38, 0.13); color: var(--ink); }

/* Two-factor setup and recovery codes */
.tfa-setup { display: flex; gap: 20px; flex-wrap: wrap; margin-top: 14px; align-items: flex-start; }
.tfa-qr {
  width: 176px; height: 176px; flex: none; padding: 8px;
  border: 1px solid var(--border); border-radius: var(--r); background: #0b0c0e;
}
.tfa-qr svg { width: 100%; height: 100%; display: block; }
.tfa-steps { flex: 1; min-width: 240px; }
.tfa-key {
  display: inline-block; margin-top: 4px; padding: 4px 8px;
  font-family: var(--mono); font-size: var(--fs-md); color: var(--gold);
  background: rgba(255, 255, 255, 0.05); border-radius: 3px;
  overflow-wrap: anywhere;
}
.recovery-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: 8px; margin-top: 12px;
}
.recovery-code {
  font-family: var(--mono); font-size: var(--fs-base); color: var(--ink);
  background: rgba(255, 255, 255, 0.05); border: 1px solid var(--border);
  border-radius: 3px; padding: 7px 9px; text-align: center;
  letter-spacing: 0.04em;
}
.cal-more {
  display: block; font-size: var(--fs-label); color: var(--gold);
  padding: 2px 6px; text-decoration: none;
}
.cal-more:hover { text-decoration: underline; }

/* ---------------------------------------------------------------------------
   Hourly work: the clock
--------------------------------------------------------------------------- */

/* Correcting a time entry, opened from its own row in the timecard. A form
   inside a table cell has no width of its own, so it is lifted out of the
   cell's flow and given one. On the stacked mobile table the cell is already
   a full-width block, so it just fills it. */
.te-edit > summary { list-style: none; }
.te-edit > summary::-webkit-details-marker { display: none; }
.te-edit[open] > summary { border-color: var(--gold); color: var(--gold); }
.te-edit-form {
  position: absolute;
  z-index: 5;
  right: 0;
  margin-top: 8px;
  width: min(420px, calc(100vw - 48px));
  background: var(--surface-2);
  border: 1px solid var(--gold-deep);
  border-radius: var(--r);
  padding: 14px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  text-align: left;
}
.timecard td:last-child { position: relative; }
@media (max-width: 768px) {
  .te-edit-form { position: static; width: 100%; box-shadow: none; }
}

.clock-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px; margin: 14px 0;
}
.clock-face {
  border: 1px solid var(--border); border-radius: var(--r);
  padding: 12px 14px; min-width: 0;
}
.clock-face.running { border-color: var(--gold); background: rgba(233, 168, 38, 0.06); }
.clock-label {
  display: block; font-family: var(--mono); font-size: var(--fs-label);
  letter-spacing: 0.11em; text-transform: uppercase; color: var(--ink-muted);
}
.clock-value {
  display: block; margin-top: 4px; font-family: var(--mono);
  font-size: 1.45rem; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums; overflow-wrap: normal;
}
.clock-face.running .clock-value { color: var(--gold); }
.clock-value small { font-size: var(--fs-sm); color: var(--ink-muted); font-weight: 400; }
.clock-sub {
  display: block; margin-top: 3px; font-size: var(--fs-xs); color: var(--ink-muted);
}

.clock-actions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.btn-start, .btn-stop {
  font-family: var(--sans); font-size: 0.95rem; font-weight: 600;
  border-radius: var(--r); padding: 11px 22px; cursor: pointer;
  border: 1px solid transparent;
}
.btn-start { background: var(--good); color: #fff; }
.btn-start:hover { filter: brightness(1.12); }
.btn-stop { background: #e05030; color: #fff; }
.btn-stop:hover { filter: brightness(1.12); }
.clock-warn { color: var(--gold); font-size: var(--fs-md); }

/* "You're on the clock" banner, portal + jobs board */
.oncall-banner {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  border: 1px solid var(--gold); border-radius: var(--r);
  background: rgba(233, 168, 38, 0.08);
  padding: 12px 16px; margin-bottom: 16px;
}
.oncall-banner .dot {
  width: 9px; height: 9px; border-radius: 50%; background: var(--gold);
  flex: none; animation: oncall-pulse 2s ease-in-out infinite;
}
@keyframes oncall-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
@media (prefers-reduced-motion: reduce) { .oncall-banner .dot { animation: none; } }
.oncall-banner .elapsed {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  color: var(--gold); font-weight: 600;
}

/* ---------------------------------------------------------------------------
   Pilot portal: offers, photos, expenses, earnings statement
--------------------------------------------------------------------------- */
.offer {
  display: flex; gap: 16px; flex-wrap: wrap; align-items: flex-start;
  padding: 14px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
.offer:last-child { border-bottom: none; }
.offer-main { flex: 1; min-width: 220px; }
.offer-meta { color: var(--ink-muted); font-size: var(--fs-md); margin-top: 3px; }
.offer-pay {
  font-family: var(--mono); font-size: 1.15rem; color: var(--gold);
  font-weight: 600; margin-top: 6px;
}
.offer-msg { color: var(--ink-2); font-size: var(--fs-md); margin-top: 6px; font-style: italic; }
.offer-actions { display: flex; flex-direction: column; gap: 8px; min-width: 150px; }
.offer-pass {
  cursor: pointer; color: var(--ink-muted); font-size: var(--fs-md);
  text-align: center; padding: 6px;
}
.offer-pass:hover { color: var(--ink-2); }

.photo-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px; margin-top: 12px;
}
.photo-tile {
  display: block; text-decoration: none; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: var(--r);
  background: rgba(255, 255, 255, 0.03);
}
.photo-tile:hover { border-color: var(--gold); text-decoration: none; }
.photo-stage {
  display: block; font-family: var(--mono); font-size: var(--fs-label);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--gold);
}
.photo-name {
  display: block; margin-top: 4px; color: var(--ink); font-size: var(--fs-md);
  overflow-wrap: anywhere;
}
.photo-meta { display: block; margin-top: 3px; color: var(--ink-muted); font-size: var(--fs-xs); }

.exp-tabs { display: flex; gap: 6px; flex-wrap: wrap; }
.exp-tab {
  background: none; border: 1px solid var(--border); color: var(--ink-2);
  border-radius: var(--r); padding: 7px 14px; font-family: var(--sans);
  font-size: var(--fs-md); cursor: pointer;
}
.exp-tab.on { background: var(--gold); border-color: var(--gold); color: #0b0c0e; font-weight: 600; }

/* Earnings statement */
.statement-head {
  display: flex; gap: 16px; flex-wrap: wrap; align-items: flex-start;
  justify-content: space-between; padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.statement-who { font-family: var(--serif); font-size: 1.3rem; color: var(--ink); }
.statement-actions {
  display: flex; gap: 12px; flex-wrap: wrap; align-items: center;
  margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--border);
}

/* Month bars on the statement — a shape, not a chart library */
.bars {
  display: flex; gap: 6px; align-items: flex-end;
  height: 110px; margin: 4px 0 20px; overflow-x: auto; padding-bottom: 4px;
}
.bar-col { display: flex; flex-direction: column; align-items: center; gap: 5px; min-width: 30px; flex: 1; }
.bar-track { flex: 1; width: 100%; display: flex; align-items: flex-end; }
.bar-fill {
  width: 100%; background: var(--series-1); border-radius: 2px 2px 0 0;
  min-height: 2px;
}
.bar-label {
  font-family: var(--mono); font-size: var(--fs-label); color: var(--ink-muted);
  text-transform: uppercase; letter-spacing: 0.06em;
}

@media print {
  .topbar, .mobile-drawer, .drawer-overlay, .statement-actions,
  .page-head a, .palette-overlay { display: none !important; }
  body { background: #fff; color: #000; }
  .card, .kpi, .notice { border-color: #ccc; background: #fff; }
  .statement-who, .data-table td.num, .kpi .value { color: #000 !important; }
}
.offer-picker {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 6px; margin-top: 4px;
}
.offer-pick {
  display: flex; align-items: center; gap: 7px;
  border: 1px solid var(--border); border-radius: var(--r);
  padding: 8px 10px; font-size: var(--fs-md); color: var(--ink-2); cursor: pointer;
}
.offer-pick:hover { border-color: var(--gold); }
.offer-pick input { width: auto; margin: 0; }

/* Manual time entry: day + two clock times, laid out to be tapped */
.time-entry {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px; align-items: end;
}
.te-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.te-field label {
  font-family: var(--mono); font-size: 0.63rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-muted);
}
.te-field input, .te-field select {
  background: var(--bg); border: 1px solid var(--border); color: var(--ink);
  border-radius: var(--r); padding: 10px 11px; font-family: var(--sans);
  font-size: 0.95rem; width: 100%; min-width: 0;
}
.te-field input:focus { outline: 2px solid var(--gold-deep); }
.te-total span {
  font-family: var(--mono); font-size: var(--fs-base); color: var(--gold);
  padding: 10px 0; font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
   Manager: work queue, delivery pipeline, capacity, scorecards
--------------------------------------------------------------------------- */
.attention {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 12px; margin-bottom: 20px;
}
.att-card {
  border: 1px solid var(--border); border-radius: var(--r);
  background: var(--surface); padding: 14px 16px;
}
.att-card.urgent { border-color: rgba(224, 80, 48, 0.45); }
.att-n {
  font-family: var(--mono); font-size: 1.7rem; font-weight: 700;
  color: var(--gold); line-height: 1; display: block;
}
.att-card.urgent .att-n { color: #e05030; }
.att-l { display: block; margin-top: 3px; color: var(--ink-2); font-size: var(--fs-md); }
.att-list { margin-top: 9px; display: flex; flex-direction: column; gap: 4px; }
.att-list a {
  font-size: var(--fs-sm); color: var(--ink-2); display: flex;
  justify-content: space-between; gap: 8px; overflow-wrap: anywhere;
}
.att-list a:hover { color: var(--ink); }
.att-late { font-family: var(--mono); color: var(--gold); flex: none; font-size: var(--fs-xs); }
.att-more { display: inline-block; margin-top: 9px; font-size: var(--fs-sm); }
.att-list a.att-stack { display: block; }
.att-why { display: block; color: var(--ink-muted); font-size: var(--fs-xs); }
.nowrap { white-space: nowrap; }
/* A field nobody filled in: quiet, not a loud dash down the whole column. */
.not-set { color: var(--ink-muted); opacity: 0.7; font-size: 0.8em; font-style: italic; }

.bucket-head { display: flex; align-items: center; gap: 10px; }
.bucket-count {
  font-family: var(--mono); font-size: var(--fs-sm); color: var(--ink-muted);
  border: 1px solid var(--border); border-radius: 10px; padding: 1px 9px;
}
.queue-bucket.urgent .bucket-count { color: #e05030; border-color: rgba(224, 80, 48, 0.45); }
.queue-bucket.now .bucket-count { color: var(--gold); border-color: rgba(233, 168, 38, 0.45); }

/* Delivery pipeline board */
.pipeline {
  display: grid; grid-template-columns: repeat(5, minmax(190px, 1fr));
  gap: 10px; overflow-x: auto; padding-bottom: 6px;
}
.pipe-col { min-width: 190px; }
.pipe-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 7px 10px; border-bottom: 2px solid var(--border); margin-bottom: 9px;
}
.pipe-col.rework .pipe-head { border-bottom-color: #e05030; }
.pipe-col.delivered .pipe-head { border-bottom-color: var(--good); }
.pipe-col.qc .pipe-head { border-bottom-color: var(--gold); }
.pipe-title {
  font-family: var(--mono); font-size: var(--fs-label); letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--ink-muted);
}
.pipe-count { font-family: var(--mono); font-size: var(--fs-xs); color: var(--ink); }
.pipe-card {
  border: 1px solid var(--border); border-radius: var(--r);
  background: rgba(255, 255, 255, 0.03); padding: 10px 11px; margin-bottom: 8px;
}
.pipe-card.late { border-color: rgba(224, 80, 48, 0.5); }
.pipe-job { display: block; color: var(--ink); font-size: var(--fs-md); overflow-wrap: anywhere; }
.pipe-meta { color: var(--ink-muted); font-size: var(--fs-xs); margin-top: 2px; overflow-wrap: anywhere; }
.pipe-foot {
  display: flex; justify-content: space-between; gap: 8px; margin-top: 7px;
  font-size: var(--fs-xs); color: var(--ink-muted); flex-wrap: wrap;
}
.pipe-late { color: #e05030; }
.pipe-move { margin-top: 8px; }
.pipe-move .status-select { width: 100%; }
.pipe-empty {
  color: var(--ink-muted); font-size: var(--fs-xs); padding: 12px 10px;
  border: 1px dashed var(--border); border-radius: var(--r); text-align: center;
}

/* Capacity grid */
.cap-scroll { overflow-x: auto; margin-top: 12px; }
.cap { width: 100%; border-collapse: collapse; min-width: 760px; }
.cap th {
  padding: 7px 8px; text-align: left; border-bottom: 1px solid var(--border);
  vertical-align: bottom;
}
.cap th.now { background: rgba(233, 168, 38, 0.07); }
.cap-week {
  display: block; font-family: var(--mono); font-size: var(--fs-xs); color: var(--ink);
}
.cap-sub {
  display: block; font-family: var(--mono); font-size: 0.6rem; color: var(--ink-muted);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.cap-name { width: 150px; font-size: var(--fs-md); padding: 9px 8px; }
.cap-cell {
  padding: 9px 8px; border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  vertical-align: middle; min-width: 74px;
}
.cap-bar {
  height: 7px; background: rgba(255, 255, 255, 0.07); border-radius: 4px; overflow: hidden;
}
.cap-fill { height: 100%; background: var(--series-1); }
.cap-cell.over .cap-fill { background: #e05030; }
.cap-days {
  display: block; margin-top: 3px; font-family: var(--mono); font-size: var(--fs-label);
  color: var(--ink-muted); font-variant-numeric: tabular-nums;
}
.cap-free { color: var(--ink-faint); }
.cap-unassigned {
  display: block; margin-top: 2px; font-family: var(--mono);
  font-size: var(--fs-label); color: var(--gold);
}
.cap tfoot td { border-top: 2px solid var(--border); color: var(--ink); }
.cap tfoot .cap-cell.tight strong { color: var(--gold); }
.cap tfoot .cap-cell.full strong { color: #e05030; }

@media (max-width: 700px) {
  .pipeline { grid-template-columns: repeat(5, 78vw); }
}

/* ---------------------------------------------------------------------------
   Portal header on a phone
   The pilot/client bar has no hamburger to absorb its buttons, so Password and
   Sign out were pressed hard against the right edge — two pixels past it, in
   fact. The spacer becomes a full-width line break instead of a flex filler,
   dropping the nav and buttons onto their own row. It also brings back the
   portal nav link, which the 900px rule that hides .topnav was swallowing.
--------------------------------------------------------------------------- */
@media (max-width: 640px) {
  .topbar.portal-top { flex-wrap: wrap; row-gap: 9px; gap: 10px; }
  .topbar.portal-top .spacer { flex: 0 0 100%; height: 0; }
  .topbar.portal-top .topnav { display: flex; order: 3; }
  .topbar.portal-top .btn-ghost { order: 4; }
  .topbar.portal-top form { order: 5; }
}

/* ---------------------------------------------------------------------------
   Touch targets
   Apple and Google both put the minimum comfortable tap target near 44px.
   Several controls were rendering at 21-30px: status dropdowns, the "+ Add..."
   expanders, checkboxes and the small ghost buttons in table rows. On a mouse
   they are fine; on a thumb they are a coin toss. These rules apply on narrow
   screens and on any coarse pointer, so a tablet or a touchscreen laptop gets
   them too without changing the desktop layout.
--------------------------------------------------------------------------- */
@media (max-width: 768px), (pointer: coarse) {
  select.status-select,
  .filter-row select,
  .filter-row input:not([type="checkbox"]):not([type="radio"]),
  .filter-row .search-input {
    min-height: 44px;
    padding-top: 10px;
    padding-bottom: 10px;
  }

  /* A dropdown is as wide as its longest option, and a customer list holds
     names like "Great River Energy Transmission & Distribution Cooperative".
     Left alone the control ran off the card and had to be scrolled to. */
  .filter-row select,
  .filter-row .search-input,
  .input-short,
  .input-shorter,
  input[type="date"].input-short {
    flex: 1 1 100%;
    width: 100%;
    max-width: 100%;
  }

  /* "+ Add invoice", "+ Start a project", "+ Log time that wasn't clocked" */
  details:not(.nav-group) > summary {
    min-height: 44px;
    display: flex;
    align-items: center;
  }
  .fin-group > summary { min-height: 44px; }

  /* A 13px checkbox is smaller than the pad of a finger. */
  input[type="checkbox"], input[type="radio"],
  .stacked-form input[type="checkbox"]:not(.svc-card input),
  .stacked-form input[type="radio"]:not(.svc-card input) {
    width: 24px;
    height: 24px;
    accent-color: var(--gold);
  }
  /* A label wrapping a checkbox becomes the tap target. Cards that lay out
     their own contents opt out — turning one into a flex row puts the name
     and the description side by side. */
  label:has(> input[type="checkbox"]):not(.svc-card),
  label:has(> input[type="radio"]):not(.svc-card) {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    min-height: 44px;
  }
  .svc-card { padding-left: 44px; min-height: 56px; }
  .svc-card input[type="radio"] { left: 12px; top: 15px; }

  /* Assign / Remove / ✕ in table rows, and the metrics range chips. */
  .btn-ghost, .btn-gold, .range-picker button, button.btn-danger {
    min-height: 44px;
    padding-top: 10px;
    padding-bottom: 10px;
  }
  .topbar .btn-ghost { min-height: 40px; }

  /* Job links inside the delivery pipeline cards. */
  .pipe-job { display: flex; align-items: center; min-height: 40px; }

  /* Standalone "go somewhere" links that sit alone on their own line. Inside a
     sentence a link is as tall as the line and that is fine; on its own it is
     a button in all but name and needs the height of one. */
  .att-more {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* The month arrows on the schedule are a single character wide. */
  .cal-bar .btn-ghost { min-width: 44px; text-align: center; }

  .cb-hit { min-width: 44px; min-height: 44px; margin: -10px; }

  /* iOS Safari zooms the whole page in when you tap a field whose text is
     under 16px, and it does not zoom back out afterwards. Body text is 15px
     and every control sized off it, so filling in any form on an iPhone left
     the page magnified and scrolled sideways — the single most-felt thing in
     the app on a phone, and three lines of CSS. 16px exactly: the threshold,
     not a redesign. */
  input:not([type="checkbox"]):not([type="radio"]),
  select,
  textarea {
    font-size: 16px;
  }
}

/* ---------------------------------------------------------------------------
   Client portal — projects, links, deliverables
   The customer's page has one job: show them where their data is and when
   the rest of it is coming.
--------------------------------------------------------------------------- */
.proj {
  border: 1px solid var(--border); border-radius: var(--r);
  padding: 14px 16px; margin-bottom: 14px;
  background: rgba(255, 255, 255, 0.015);
}
.proj:last-child { margin-bottom: 0; }
.proj-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
}
.proj-name { color: var(--ink); font-size: 1.02rem; }
.proj-code {
  margin-left: 8px; font-family: var(--mono); font-size: var(--fs-xs);
  color: var(--ink-muted);
}
.proj-sub { color: var(--ink-muted); font-size: var(--fs-md); margin-top: 3px; }
.proj-empty {
  margin-top: 10px; padding: 12px 10px; text-align: center;
  border: 1px dashed var(--border); border-radius: var(--r);
  color: var(--ink-muted); font-size: var(--fs-sm);
}

/* The link tiles. Big enough to be the obvious thing on the page, because
   for most customers they are the whole reason they signed in. */
.link-row {
  display: grid; gap: 10px; margin-top: 12px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.link-tile {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; text-decoration: none;
  border: 1px solid var(--gold-deep); border-radius: var(--r);
  background: rgba(233, 168, 38, 0.06);
  transition: background 0.15s ease, border-color 0.15s ease;
  min-height: 56px;
}
.link-tile:hover { background: rgba(233, 168, 38, 0.12); border-color: var(--gold); }
.link-glyph { color: var(--gold); font-size: 1.25rem; line-height: 1; flex: 0 0 auto; }
.link-body { min-width: 0; }
.link-label {
  display: block; color: var(--ink); font-size: var(--fs-base); font-weight: 500;
  overflow-wrap: break-word;
}
.link-note {
  display: block; color: var(--ink-muted); font-size: var(--fs-xs); margin-top: 2px;
  overflow-wrap: break-word;
}
.dl-link { font-size: var(--fs-xs); }

.embed-card { padding: 0; overflow: hidden; }
.embed-fallback {
  padding: 10px 14px; color: var(--ink-muted); font-size: var(--fs-sm);
  border-bottom: 1px solid var(--border);
}
.embed-frame {
  display: block; width: 100%; height: 72vh; min-height: 420px;
  border: 0; background: var(--bg);
}

/* The staff-side shelf of links under each project row. */
.link-shelf td {
  border-bottom: 1px solid var(--border);
  padding-top: 2px; padding-bottom: 10px;
}
.chip-link {
  display: inline-flex; align-items: center; gap: 7px;
  margin: 0 8px 6px 0; padding: 4px 8px;
  border: 1px solid var(--border); border-radius: var(--r);
  background: rgba(255, 255, 255, 0.02); font-size: var(--fs-sm);
}
.chip-link a { color: var(--gold); text-decoration: none; }
/* A chip that submits something: the same shape, on the page colour. */
button.chip-link { background: var(--bg); color: var(--ink-2); cursor: pointer; font-family: var(--sans); }
button.chip-link:hover { border-color: var(--gold); color: var(--ink); }
button.chip-link:disabled { opacity: 0.5; cursor: default; }
.chip-link a:hover { text-decoration: underline; }
.chip-meta { color: var(--ink-muted); font-size: var(--fs-xs); font-family: var(--mono); }
.chip-x {
  background: none; border: none; color: var(--ink-muted);
  cursor: pointer; font-size: var(--fs-sm); padding: 0 2px; line-height: 1;
}
.chip-x:hover { color: #e05030; }

/* The shelf is a full-width strip under a project row, not a label:value
   pair. Left in the stacked table's two-column layout it squeezed the kind
   dropdown down to twenty-six pixels wide. */
@media (max-width: 700px) {
  .data-table.stack tbody tr.link-shelf { border-top: none; margin-top: -10px; }
  .data-table.stack .link-shelf td,
  .link-shelf td[data-label] {
    display: block !important;
    padding: 4px 2px 8px !important;
    text-align: left !important;
  }
  .data-table.stack .link-shelf td::before { content: none !important; }
  /* Three things competing for 340px turns a link name into a column of
     syllables. Give the name its own line and let the host and the remove
     button share the one below it. */
  .link-shelf .chip-link {
    display: flex; width: 100%; margin-right: 0; flex-wrap: wrap;
    row-gap: 2px; padding: 8px 10px;
  }
  .link-shelf .chip-link a { flex: 1 1 100%; min-width: 0; overflow-wrap: break-word; }
  .link-shelf .chip-link .chip-meta { flex: 1 1 auto; }
  .link-shelf .chip-link form { margin-left: auto; }
  /* Every other chip on a phone (the invoice filters, "Not clear to fly")
     stays a chip; this rule used to stretch all of them to full width. */
}

@media (max-width: 768px), (pointer: coarse) {
  .chip-x { min-width: 40px; min-height: 40px; font-size: 0.95rem; }
  .link-add > summary { min-height: 44px; display: flex; align-items: center; }
}
.link-add > summary {
  cursor: pointer; color: var(--gold); font-size: var(--fs-sm);
  display: inline-block; list-style: none;
}
.link-add > summary::-webkit-details-marker { display: none; }
.field-hint {
  display: block; margin-top: 3px; color: var(--ink-muted); font-size: var(--fs-xs);
}
.share-toggle {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--fs-xs); color: var(--ink-2); cursor: pointer;
}
.share-toggle input:checked + span { color: var(--good); }

/* ---------------------------------------------------------------------------
   "Ask us for something"
   Six service lines as cards rather than a dropdown, so a customer can see
   what each one actually is — and so the last card, the one for work that
   doesn't fit a category, reads as a real option rather than a leftover.
--------------------------------------------------------------------------- */
.svc-grid {
  display: grid; gap: 10px; margin-bottom: 16px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.svc-card {
  display: block; position: relative; cursor: pointer;
  padding: 12px 14px 12px 38px;
  border: 1px solid var(--border); border-radius: var(--r);
  background: rgba(255, 255, 255, 0.015);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.svc-card:hover { border-color: var(--gold-deep); }
.svc-card input[type="radio"] {
  position: absolute; left: 13px; top: 14px; margin: 0;
  width: 18px; height: 18px; padding: 0;
  accent-color: var(--gold);
}
.svc-card:has(input:checked) {
  border-color: var(--gold); background: rgba(233, 168, 38, 0.07);
}
.svc-card:has(input:focus-visible) { outline: 2px solid var(--gold-deep); outline-offset: 2px; }
.svc-name { display: block; color: var(--ink); font-size: var(--fs-base); font-weight: 500; }
.svc-blurb {
  display: block; margin-top: 4px; color: var(--ink-muted);
  font-size: var(--fs-sm); line-height: 1.45;
}
/* The catch-all sits apart from the six: same weight, different edge. */
.svc-card.svc-open { border-style: dashed; }
.svc-card.svc-open:has(input:checked) { border-style: solid; }

.ask-grid {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.ask-grid .ask-wide { grid-column: 1 / -1; }
.ask-grid .form-field { margin: 0 0 0 0; }
/* The unit picker beside "about how big" sizes to its content, not the row. */
#ask-unit { width: auto; }
.ask-past { margin-top: 22px; border-top: 1px solid var(--border); padding-top: 14px; }
.ask-past h3 {
  font-family: var(--sans); font-size: var(--fs-xs); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--ink-muted); margin: 0 0 8px;
}

/* ---------------------------------------------------------------------------
   Quote acceptance
--------------------------------------------------------------------------- */
.quote-total {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-top: 16px; padding-top: 12px; border-top: 2px solid var(--border);
  font-size: 1.05rem; color: var(--ink-2);
}
.quote-total strong {
  font-family: var(--mono); font-size: 1.5rem; color: var(--gold);
  font-variant-numeric: tabular-nums; overflow-wrap: normal;
}
.badge-accepted { color: var(--good); border-color: rgba(12, 163, 12, 0.5); }

.sig-block {
  border-left: 2px solid var(--good); padding: 6px 14px; margin-top: 6px;
}
.sig-name {
  font-family: var(--logo-serif), Georgia, serif; font-style: italic;
  font-size: 1.5rem; color: var(--ink);
}
.sig-title { color: var(--ink-2); font-size: var(--fs-md); margin-top: 2px; }
.sig-meta {
  color: var(--ink-muted); font-family: var(--mono); font-size: var(--fs-xs);
  margin-top: 6px;
}
.sig-agree {
  display: flex !important; align-items: flex-start; gap: 10px;
  color: var(--ink-2); font-size: var(--fs-md); line-height: 1.5;
}
.sig-agree input { width: auto !important; margin-top: 2px; flex: 0 0 auto; }
.decline-box { margin-top: 18px; }
.decline-box > summary {
  cursor: pointer; color: var(--ink-muted); font-size: var(--fs-md);
}
.share-link {
  font-family: var(--mono); font-size: var(--fs-xs); color: var(--ink-muted);
  overflow-wrap: anywhere;
}

/* Maps. Fixed heights because a Leaflet container with no height renders
   nothing at all, and a customer would just see a gap. */
.site-map {
  height: 380px; margin-top: 12px;
  border: 1px solid var(--border); border-radius: var(--r);
  background: var(--bg);
}
/* Leaflet stacks its panes and controls at z-index 400-1000 inside the map,
   which put the map over the sticky header as the page scrolled. Each map is
   its own stacking context, so those numbers never leave the box. */
.site-map, .job-map, .leaflet-container { position: relative; z-index: 0; isolation: isolate; }
.draw-map {
  height: 320px; margin-top: 4px;
  border: 1px solid var(--border); border-radius: var(--r);
  background: var(--bg);
}
.draw-bar {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 8px;
}
/* Leaflet's own popups and controls, in the dark palette. Leaflet's
   stylesheet loads after this one, so every selector here carries one more
   step of specificity than the rule it is replacing — otherwise the tie goes
   to whichever loaded last, which is not us. The map's own background matters
   more than it looks: when tiles can't load, a dark panel reads as an empty
   map and Leaflet's default grey reads as a broken page. */
div.leaflet-container { background: #10131a; font-family: var(--sans); }
.leaflet-container .leaflet-popup-content-wrapper,
.leaflet-container .leaflet-popup-tip {
  background: var(--surface); color: var(--ink-2);
  border: 1px solid var(--border);
}
.leaflet-container .leaflet-popup-content { font-size: var(--fs-md); line-height: 1.5; }
.leaflet-container .leaflet-popup-content strong { color: var(--ink); }
.leaflet-container a.leaflet-popup-close-button { color: var(--ink-muted); }
.leaflet-container .leaflet-bar a,
.leaflet-container .leaflet-bar a:hover {
  background: var(--surface); color: var(--ink-2); border-bottom-color: var(--border);
}
.leaflet-container .leaflet-control-attribution {
  background: rgba(11, 12, 14, 0.78); color: var(--ink-muted); font-size: var(--fs-label);
}
.leaflet-container .leaflet-control-attribution a { color: var(--ink-2); }
@media (max-width: 700px) {
  .site-map { height: 300px; }
  .draw-map { height: 260px; }
}
@media (max-width: 768px), (pointer: coarse) {
  /* Leaflet ships 26px zoom buttons, 30px once it decides the device is
     touch. Both are too small for a thumb, and pinch-zoom is not a
     substitute for someone who taps. Named selectors because Leaflet's own
     stylesheet loads after this one and would otherwise win the tie. */
  .leaflet-container .leaflet-bar a.leaflet-control-zoom-in,
  .leaflet-container .leaflet-bar a.leaflet-control-zoom-out {
    width: 44px; height: 44px; line-height: 44px; font-size: 1.25rem;
  }
}
.leaflet-container .leaflet-control-layers {
  background: var(--surface); border: 1px solid var(--border);
  color: var(--ink-2); border-radius: var(--r);
}
.leaflet-container .leaflet-control-layers-list { font-size: var(--fs-sm); padding: 4px 2px; }
.leaflet-container .leaflet-control-layers label {
  display: flex; align-items: center; gap: 6px; padding: 4px 6px; cursor: pointer;
}
.leaflet-container .leaflet-control-layers input { width: auto; margin: 0; }
@media (max-width: 768px), (pointer: coarse) {
  /* The whole row toggles the layer, so give the row the height rather than
     inflating the radio inside it. */
  .leaflet-container .leaflet-control-layers label { min-height: 44px; padding: 0 8px; }
  .leaflet-container .leaflet-control-layers input { width: 22px; height: 22px; }
}

/* ---------------------------------------------------------------------------
   The job map
   Three colours carrying three states, the same on the pilot's map, the
   manager's and the admin's. Approved work is gone, so what is on the map is
   what is left to do.
--------------------------------------------------------------------------- */
.job-map {
  height: 520px; border: 1px solid var(--border); border-radius: var(--r);
  background: var(--bg); margin-top: 12px;
}
/* On a desktop the map is the page: the script sizes it to what is left of
   the window under the filters and the key; this is the floor it starts from. */
@media (min-width: 900px) {
  .job-map { height: clamp(320px, calc(100vh - 380px), 900px); }
}

/* ---------------------------------------------------------------------------
   Folds — a card whose body the reader opens when they want it. The pilot's
   home page is where the day's work lives; the payment history, the
   notifications and the away-days sit under a heading until asked for.
--------------------------------------------------------------------------- */
.fold { padding: 0; }
.fold > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; gap: 10px;
  padding: 16px 18px; min-height: 48px;
}
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary h2 { margin: 0; flex: 1; }
.fold > summary .fold-count {
  font-family: var(--mono); font-size: var(--fs-sm); color: var(--ink-muted);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 999px; padding: 2px 9px;
}
.fold > summary::after {
  content: ""; width: 8px; height: 8px; margin-top: -4px; flex: none;
  border-right: 1.5px solid var(--ink-muted); border-bottom: 1.5px solid var(--ink-muted);
  transform: rotate(45deg);
}
.fold[open] > summary::after { transform: rotate(225deg); margin-top: 4px; }
.fold > summary:hover { background: var(--surface-2); }
.fold > .fold-body { padding: 0 18px 18px; }
.fold > .fold-body > .card-sub:first-child { margin-top: 0; }
/* A fold inside a card — "Older" under a job list — sits flush with the
   table above it and keeps the card's own padding. */
.fold-more { margin-top: 10px; border-top: 1px solid var(--border); }
.fold-more > summary { padding: 12px 4px; min-height: 44px; }
.fold-more > summary h2 { font-size: var(--fs-base); color: var(--ink-muted); }
.fold-more > .fold-body { padding: 0; }
/* A group of rows inside a card — a pay stub, a month of jobs — with the
   count and total on the summary line so it reads closed. */
.rate-cell { width: 100%; min-width: 72px; padding: 5px 8px; font-size: var(--fs-md); text-align: inherit; }
/* Six editable columns need the whole width of the page (the card spans the
   grid), and on a desktop the figures are short: a 6.5em box each, the note
   takes what is left, and the Save / Delete pair never wraps. Should a
   narrow window still be too narrow, the table scrolls inside its card
   rather than running past the edge. */
.rates-scroll { overflow-x: auto; }
/* A sticky table header measures its offset from the nearest scroll
   container; inside this one that put the header 63px down, over the
   first row. The page scrolls, the header stays put. */
.rates-scroll .data-table thead th { position: static; }
@media (min-width: 701px) {
  .rates-table .rate-cell { width: 6.5em; min-width: 0; }
  .rates-table td[data-label="Note"] .rate-cell { width: 100%; min-width: 140px; }
  .rates-table td[data-label="Note"] { width: 40%; }
  .rates-table .rate-actions { white-space: nowrap; }
}
@media (max-width: 700px) {
  .rates-table .rate-cell { min-width: 0; }
}
.group-title { margin: 8px 0 4px; font-size: var(--fs-sm); letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-muted); }
.fold-group { border-top: 1px solid var(--border); }
.fold-group:last-child { border-bottom: 1px solid var(--border); }
.fold-group > summary { display: flex; align-items: center; list-style: none; cursor: pointer; padding: 11px 4px; min-height: 44px; gap: 12px; flex-wrap: wrap; }
.fold-group > summary::-webkit-details-marker { display: none; }
.fold-group > summary::before { content: "▸"; color: var(--ink-muted); font-size: var(--fs-base); transition: transform .15s ease; }
.fold-group[open] > summary::before { transform: rotate(90deg); }
.fold-group > summary h2 { font-size: 0.95rem; flex: 1 1 auto; }
.fold-group > summary .fold-meta { font-family: var(--mono); font-size: var(--fs-sm); color: var(--ink-muted); white-space: nowrap; }
.fold-group > .fold-body { padding: 0 0 12px; }
.fold-group .data-table { margin-top: 0; }
@media (max-width: 768px) {
  .fold-group > summary .fold-meta { white-space: normal; flex-basis: 100%; }
}
.map-empty {
  display: flex; align-items: center; justify-content: center; height: 100%;
  color: var(--ink-muted); font-size: var(--fs-md);
}
.map-legend {
  display: flex; gap: 16px; flex-wrap: wrap; align-items: center;
  margin-top: 10px; font-size: var(--fs-sm); color: var(--ink-2);
}
.map-key { display: inline-flex; align-items: center; gap: 6px; }
.map-key b { color: var(--ink); font-family: var(--mono); }
/* The legend keys are the layer switches: a key that is off reads dim and
   struck through, and its pins are gone from the map. */
button.map-key {
  background: none; border: 1px solid transparent; border-radius: 999px; padding: 5px 9px; margin: -5px -3px;
  color: inherit; font: inherit; cursor: pointer; min-height: 34px;
}
button.map-key:hover { border-color: var(--border); }
button.map-key[aria-pressed="false"] { opacity: 0.45; text-decoration: line-through; }
button.map-key[aria-pressed="false"] .pin-dot { background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--border); }
.map-note { color: var(--ink-muted); font-size: var(--fs-xs); }
.pin-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }

/* The pins themselves, drawn rather than loaded — no image per colour. */
.pin {
  display: block; width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid rgba(0, 0, 0, 0.55);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
}
.pin-wait, .pin-dot.pin-wait { background: #e9a826; }
.pin-going, .pin-dot.pin-going { background: #3ba8d4; }
.pin-done, .pin-dot.pin-done { background: #0CA30C; }
.pin-review, .pin-dot.pin-review { background: #a78bfa; }
.pin-back, .pin-dot.pin-back { background: #e05030; }
.pin-pay, .pin-dot.pin-pay { background: #19b3a6; }
.pin-paid, .pin-dot.pin-paid { background: #8a929c; }
.pin-off, .pin-dot.pin-off { background: #3a3f45; box-shadow: inset 0 0 0 1px #6b7178; }
/* Tick-chips on the map: which kinds of job to draw. Same shape as the range
   picker so the eye reads them as one control. */
.show-chips { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.show-chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; border: 1px solid var(--border);
  border-radius: 999px; font-size: var(--fs-sm); color: var(--ink-2); cursor: pointer; text-decoration: none; min-height: 34px; }
.show-chip.on { border-color: var(--gold); color: var(--ink); }
.show-chip input { accent-color: var(--gold); margin: 0; width: 15px; height: 15px; }
/* A ring for a clock that is running. */
.pin-live { box-shadow: 0 0 0 4px rgba(233, 168, 38, 0.45), 0 1px 4px rgba(0, 0, 0, 0.5); }

.pin-pop { min-width: 200px; }
.pin-title { display: block; color: var(--ink); font-size: var(--fs-base); line-height: 1.35; }
.pin-sub { color: var(--ink-2); font-size: var(--fs-sm); margin-top: 2px; }
.pin-meta { color: var(--ink-muted); font-size: var(--fs-xs); margin-top: 2px; }
.pin-warn { color: var(--gold); }
.pin-state {
  display: inline-block; margin-top: 7px; padding: 2px 8px; border-radius: 999px;
  font-family: var(--mono); font-size: var(--fs-label); text-transform: uppercase;
  letter-spacing: 0.07em; border: 1px solid var(--border);
}
.pin-state-wait { color: #e9a826; border-color: rgba(233, 168, 38, 0.5); }
.pin-state-going { color: #3ba8d4; border-color: rgba(59, 168, 212, 0.5); }
.pin-state-done { color: var(--good); border-color: rgba(12, 163, 12, 0.5); }
.pin-state-review { color: #a78bfa; border-color: rgba(167, 139, 250, 0.5); }
.pin-state-back { color: #e05030; border-color: rgba(224, 80, 48, 0.5); }

.pin-acts { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.pin-act { margin: 0; }
.pin-acts button, .pin-acts .pin-open, .pin-acts a.pin-next {
  font-family: var(--sans); font-size: var(--fs-xs); padding: 7px 11px;
  border-radius: var(--r); cursor: pointer; text-decoration: none;
  border: 1px solid var(--border); background: none; color: var(--ink-2);
}
.pin-acts .pin-start { background: var(--good); border-color: var(--good); color: #04140a; font-weight: 600; }
.pin-acts .pin-stop { background: #e05030; border-color: #e05030; color: #fff; font-weight: 600; }
.pin-acts .pin-next { background: var(--gold); border-color: var(--gold); color: #0b0c0e; font-weight: 600; }
.pin-acts .pin-open:hover { border-color: var(--gold); color: var(--ink); }

@media (max-width: 768px), (pointer: coarse) {
  .job-map { height: 60vh; min-height: 340px; }
  .pin-acts button, .pin-acts .pin-open, .pin-acts a.pin-next { min-height: 44px; display: inline-flex; align-items: center; }
}

/* ---------------------------------------------------------------------------
   Dashboard sections
   Money and website numbers used to sit in two identical rows of grey tiles
   with nothing to say which was which — and a date picker at the top that
   only ever governed one of them.
--------------------------------------------------------------------------- */
.dash-block { margin-bottom: 22px; }
.dash-head {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin-bottom: 10px; padding-bottom: 7px;
  border-bottom: 1px solid var(--border);
}
.dash-title {
  font-family: var(--serif); font-size: 1.18rem; color: var(--ink);
  margin: 0; font-weight: 400;
}
.dash-sub { color: var(--ink-muted); font-size: var(--fs-sm); flex: 1 1 240px; }
.dash-head .range-picker { margin-left: auto; flex: 0 0 auto; }
.kpi-note {
  margin-top: 4px; color: var(--ink-muted); font-size: var(--fs-xs); line-height: 1.35;
}
@media (max-width: 700px) {
  .dash-head { flex-direction: column; align-items: stretch; gap: 6px; }
  /* In a column the flex-basis that sets the desktop layout becomes a height
     to grow into, which left a gap the size of a card under the heading. */
  .dash-head .dash-sub { flex: 0 0 auto; }
  .dash-head .range-picker { margin-left: 0; width: auto; }
}

/* ---------------------------------------------------------------------------
   Pilot portal: work sorted by what it needs from them
   The old "My jobs" was one list of everything, which meant the job waiting
   on a pilot's acceptance sat below thirty jobs already paid. The tabs are a
   partition — every job is in exactly one — so a count on a tab is a real
   count of work, not a filter that overlaps its neighbours.
--------------------------------------------------------------------------- */
.form-row { display: flex; gap: 12px; flex-wrap: wrap; }
.form-row .form-field { flex: 1 1 200px; }

.jobtabs {
  display: flex; gap: 2px; flex-wrap: wrap;
  border-bottom: 1px solid var(--line); margin-bottom: 0;
}
.jobtabs button {
  appearance: none; background: none; border: 0; cursor: pointer;
  padding: 10px 14px; color: var(--ink-muted); font: inherit; font-size: var(--fs-md);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  display: inline-flex; align-items: center; gap: 7px;
}
.jobtabs button:hover { color: var(--ink-2); }
.jobtabs button[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--gold); }
.jobtabs button:focus-visible { outline: 2px solid var(--gold-deep); outline-offset: -2px; }
.tab-count {
  font-size: var(--fs-xs); font-variant-numeric: tabular-nums;
  background: var(--surface-2, rgba(255,255,255,.06)); color: var(--ink-muted);
  border-radius: 9px; padding: 1px 7px; min-width: 20px; text-align: center;
}
.jobtabs button[aria-selected="true"] .tab-count { color: var(--ink); }
.tab-count.hot { background: rgba(233,168,38,.18); color: var(--gold); }
.tabpanel[hidden] { display: none; }
.tabpanel { padding-top: 14px; }
.act-pill {
  display: inline-block; font-size: var(--fs-xs); color: var(--gold);
  border: 1px solid rgba(233,168,38,.4); border-radius: 3px; padding: 1px 7px;
}
@media (max-width: 768px), (pointer: coarse) {
  button.map-key, .chip-link { min-height: 44px; }      /* thumbs, not mouse pointers */
  .jobtabs { gap: 0; overflow-x: auto; flex-wrap: nowrap; scrollbar-width: none; }
  .jobtabs::-webkit-scrollbar { display: none; }
  .jobtabs button { min-height: 44px; white-space: nowrap; }
  /* More tabs off to the right: fade the edge so a thumb knows to swipe.
     The class is set from the tab strip's own scroll position. */
  .jobtabs.more-right {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent);
  }
}

/* A draft invoice is not money yet, but it should not vanish either — shown
   under the lifetime figure rather than added into it. */
.kpi-note {
  margin-top: 3px; font-size: var(--fs-xs); color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}

/* A page can hold two questions if it says which is which. Profitability
   answers "what has this customer been worth" and "is the year up" — eleven
   KPI tiles in a row read as one wall of money with no seam in it. */
.section-label {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-muted);
  margin: 0 0 10px;
}

/* Self-logged work on the clock, in the Today banner. It sits under the job
   clocks rather than beside them: a job clock has a job you can open, this
   one has a pilot standing somewhere and a name they typed in. Each gets its
   own row because it carries a Stop button, and a button crammed onto a
   comma-separated line is a button nobody presses on purpose. */
.log-run {
  display: flex; align-items: center; gap: 12px;
  margin-top: 8px; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: var(--r);
  background: rgba(255, 255, 255, 0.02);
  font-size: var(--fs-md);
}
/* The detail wraps inside its own box; the Stop button stays pinned to the
   right and vertically centred, so two rows of different lengths still look
   like two rows of the same thing. */
.log-run-meta {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px;
}
.log-run > form { flex: none; margin: 0; }
.log-run.over { border-color: var(--gold-deep, rgba(233, 168, 38, 0.5)); }
.log-run-who { color: var(--ink); font-weight: 500; }
.log-run-where { color: var(--ink-2); }
.log-run-since { color: var(--ink-muted); font-family: var(--mono); font-size: var(--fs-xs); }
.log-run-since.over { color: var(--gold); }
.log-run-warn { color: var(--gold); font-size: var(--fs-xs); }
.log-run-map { font-size: var(--fs-xs); }
.log-run form { margin: 0; }

/* An attention row that carries an action, not just a link. */
.att-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 4px 0;
}
.att-row form { margin: 0; flex: none; }
/* The hours ran straight into the site name — .att-late is positioned by the
   plain link rows above, and this row is a flex container, not a link. */
.att-row-what { min-width: 0; }
.att-row .att-late { margin-left: 6px; white-space: nowrap; }

/* Why a job has no pay figure, in the cell where the figure would have been.
   Gold because it is the same warning Profitability raises, not an error. */
.pay-gap {
  color: var(--gold);
  font-size: var(--fs-xs);
  font-family: var(--mono);
  white-space: normal;
}

/* ---------- Receipt photos on an expense ----------
   A receipt is evidence, and evidence you cannot see at a glance may as well
   not be filed. Thumbnails, not a "view" link. Tap targets are sized for a
   thumb on a truck bonnet. */
.rcpt-cell { max-width: 100%; min-width: 0; }
.rcpt { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; max-width: 100%; }
.rcpt-shot, .rcpt-file {
  display: block; width: 62px; height: 62px; max-width: 100%; flex: 0 0 auto;
  border: 1px solid var(--border); border-radius: 7px; overflow: hidden;
  background: var(--bg); text-decoration: none;
}
/* The tile is what decides the size, never the picture inside it. A phone
   photo is 3000px across, and a single one of them rendered at its own size
   pushed the whole table off the side of the screen. */
.rcpt img { max-width: 100%; height: auto; }
.rcpt-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rcpt-shot:hover, .rcpt-file:hover { border-color: var(--gold); }
.rcpt-file {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; padding: 4px; text-align: center;
}
.rcpt-glyph {
  font-family: var(--mono); font-size: var(--fs-label); letter-spacing: 0.06em;
  color: var(--gold); border: 1px solid var(--gold); border-radius: 3px; padding: 1px 4px;
}
.rcpt-name { font-size: 0.56rem; color: var(--ink-muted); line-height: 1.15;
  overflow: hidden; overflow-wrap: anywhere; }
.rcpt-add { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0; }
.rcpt-drop {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  width: 62px; height: 62px; gap: 1px; cursor: pointer;
  border: 1px dashed var(--border); border-radius: 7px; color: var(--ink-muted);
  transition: border-color 0.12s, color 0.12s;
}
.rcpt-drop:hover, .rcpt-drop:focus-within { border-color: var(--gold); color: var(--gold); }
.rcpt-drop input[type="file"] {
  position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none;
}
.rcpt-plus { font-size: 1.15rem; line-height: 1; }
.rcpt-label { font-size: 0.55rem; text-align: center; line-height: 1.15; padding: 0 3px; }
.rcpt-count { font-size: 0.52rem; color: var(--gold); }
.rcpt-none { font-size: var(--fs-xs); color: var(--ink-muted); }

/* Shut until asked for. The chip answers "is there paperwork, and how much"
   from the closed state, which is the only question the list itself raises —
   looking at the receipt is a separate decision, and one Cody wants to make
   rather than have made for him. */
.rcpt-fold { max-width: 100%; }
.rcpt-fold > summary, .chip-link {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  list-style: none; max-width: 100%;
  padding: 3px 9px; border: 1px solid var(--border); border-radius: 999px;
  background: var(--bg); color: var(--ink-2); text-decoration: none;
  font-size: var(--fs-xs); font-family: var(--mono); white-space: nowrap;
}
.rcpt-fold > summary::-webkit-details-marker { display: none; }
.rcpt-fold > summary:hover, .rcpt-fold > summary:focus-visible,
.chip-link:hover, .chip-link:focus-visible { border-color: var(--gold); color: var(--gold); }
.rcpt-fold[open] > summary { border-color: var(--gold); color: var(--gold); }
.rcpt-chip-mark { color: var(--gold); font-size: var(--fs-sm); line-height: 1; }
.rcpt-fold > .rcpt { margin-top: 8px; }
.rcpt-missing {
  font-size: var(--fs-label); color: var(--gold); border: 1px solid rgba(233, 168, 38, 0.45);
  border-radius: 3px; padding: 1px 5px; white-space: nowrap;
}
@media (max-width: 700px) {
  /* Bigger targets on a phone — this gets used standing in a field. */
  .rcpt-shot, .rcpt-file, .rcpt-drop { width: 74px; height: 74px; }
}

/* The two numbers that identify a capture. Monospaced because they are read
   digit by digit against a remittance, and dim because they are a label on
   the row, not the row's subject. */
.ref-tag {
  font-family: var(--mono); font-size: var(--fs-label); color: var(--ink-muted);
  letter-spacing: 0.01em; white-space: nowrap; overflow-wrap: normal;
}
.pin-ref { font-family: var(--mono); font-size: var(--fs-label); }

/* ---------- Pay run: find the jobs, then tick them ---------- */
.pay-tools { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-bottom: 8px; }
.pay-tools .search-input { flex: 1 1 260px; min-width: 0; }
.pay-btns { display: flex; gap: 6px; flex-wrap: wrap; }
.pay-tally { font-size: var(--fs-sm); color: var(--gold); margin-bottom: 8px; }
.pay-sum {
  font-size: 1.02rem; margin: 4px 0 12px; padding-top: 8px;
  border-top: 1px solid var(--border);
}
.pay-none { padding: 18px 4px; color: var(--ink-muted); font-size: var(--fs-md); }
@media (max-width: 700px) {
  .pay-tools { flex-direction: column; align-items: stretch; }
  .pay-btns { display: grid; grid-template-columns: 1fr 1fr; }
  .pay-btns .btn-ghost { width: 100%; }
}

/* The status control on the jobs board carries the badge's colour, because in
   a list of eighty jobs the colour is what you read, not the words. */
.status-select.status-live { border-color: currentColor; }

/* A correction riding along on a pay run. Visible before the button, not
   after: the figure that leaves the bank should never be a surprise. */
.pay-adj-note { display: block; font-size: var(--fs-md); color: var(--ink-muted); margin-top: 3px; }
.pay-holds {
  border: 1px solid rgba(233, 168, 38, 0.35); border-radius: 7px;
  padding: 10px 12px; margin: 0 0 12px;
}
.pay-holds-head {
  font-size: var(--fs-xs); letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--gold); margin-bottom: 6px;
}
.pay-hold { display: flex; gap: 10px; font-size: var(--fs-md); padding: 2px 0; flex-wrap: wrap; }
.pay-hold-amt { font-family: var(--mono); flex: 0 0 auto; min-width: 76px; }
.pay-hold-why { color: var(--ink-muted); flex: 1 1 220px; }

/* ---------------------------------------------------------------------------
   Logging an expense
--------------------------------------------------------------------------- */

/* A field with its name above it. The expense forms were letting placeholders
   do the labelling, which disappears the moment you type, reads to a screen
   reader as a filled-in value, and left "$ *" standing in for "Amount". */
.fld { display: flex; flex-direction: column; gap: 4px; flex: 1 1 190px; min-width: 0; margin: 0; }
.fld-narrow { flex: 0 1 150px; }
.fld-label {
  color: var(--ink-2); font-family: var(--mono); font-size: var(--fs-label);
  text-transform: uppercase; letter-spacing: 0.07em;
}
.fld > .search-input, .fld > select, .fld > input { width: 100%; min-width: 0; }
.fld-hint { color: var(--ink-muted); font-size: var(--fs-xs); }

/* A receipt you can take back off. The ✕ sits on the tile rather than beside
   it: a row can hold several, and a column of buttons next to a strip of
   thumbnails reads as a list of its own. */
.rcpt-item { position: relative; display: inline-flex; }
.rcpt-del { margin: 0; position: absolute; top: -7px; right: -7px; }
.rcpt-x {
  display: grid; place-items: center; width: 20px; height: 20px;
  padding: 0; border: none; background: none; cursor: pointer;
}
.rcpt-x span {
  display: grid; place-items: center; width: 20px; height: 20px; line-height: 1;
  border: 1px solid var(--border); border-radius: 50%;
  background: var(--surface); color: var(--ink-muted); font-size: var(--fs-label);
}
.rcpt-x:hover span { border-color: var(--gold); color: var(--gold); }

/* The running list, collapsed. .fin-group already draws a disclosure with the
   count and figures on its summary line, which is exactly the summary this
   list needs; all it wants on top of that is room above it for the form. */
.exp-list { margin-top: 16px; }

@media (max-width: 768px), (pointer: coarse) {
  /* One field per line on a phone — two half-width controls side by side is
     how the amount box ended up 90px wide. */
  .fld, .fld-narrow { flex: 1 1 100%; }

  /* 44px of thumb, 26px of ink: the target grows to a finger without the mark
     covering the receipt it removes. */
  /* A chip a thumb can hit without opening the wrong row's receipts. */
  .rcpt-fold > summary, .chip-link { padding: 7px 12px; font-size: var(--fs-sm); }
  .rcpt-x { width: 44px; height: 44px; }
  .rcpt-x span { width: 26px; height: 26px; font-size: var(--fs-xs); }
  .rcpt-del { top: -11px; right: -11px; }
}

/* ---------- Pay stubs (staff run page and the pilot's copy) ---------- */

.stub-id { text-align: right; }
.stub-number { font-family: var(--mono); font-size: 1.05rem; color: var(--gold); letter-spacing: 0.06em; }
.stub-status { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 14px 0 12px; font-size: 1rem; }
.stub-scheduled { border-color: var(--gold); }
.stub-lines tfoot td { border-top: 2px solid var(--border); font-size: 1.05rem; padding-top: 12px; }
.stub-adj td { color: var(--ink-2); }
.stub-list { display: grid; gap: 10px; margin-top: 10px; }
.stub-card {
  display: grid; grid-template-columns: 56px 1fr auto; align-items: center; gap: 14px;
  padding: 12px 14px; border: 1px solid var(--border); background: var(--surface-2);
  color: var(--ink); text-decoration: none; border-radius: var(--r);
}
.stub-card:hover { border-color: var(--gold); text-decoration: none; }
.stub-card-date { display: grid; text-align: center; font-family: var(--mono); line-height: 1.05; }
.stub-card-day { font-size: 1.5rem; color: var(--ink); }
.stub-card-mon { font-size: var(--fs-label); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-muted); }
.stub-card-main strong { font-size: 1.05rem; }
.pay-sched { color: var(--gold); font-size: var(--fs-md); white-space: nowrap; }
.jobs-search { display: flex; gap: 8px; margin: 0 0 12px; }
.jobs-search .search-input { flex: 1; min-width: 0; }
@media (max-width: 700px) {
  .stub-card { grid-template-columns: 48px 1fr; }
  .stub-card .badge { grid-column: 2; justify-self: start; }
}
@media print {
  .no-print, .topbar, .mobile-drawer, .drawer-overlay { display: none !important; }
  body { background: #fff; color: #000; }
  .stub, .card { border-color: #999 !important; background: #fff !important; color: #000 !important; }
  .stub a { color: #000 !important; text-decoration: none; }
  .stub-number { color: #000 !important; }
}
@media (max-width: 700px) {
  /* The total line stays a line — one label, one figure — instead of stacking. */
  .stub-lines tfoot tr { display: flex; justify-content: space-between; align-items: baseline; padding: 10px 6px 0; }
  .stub-lines tfoot td { display: block; border: none !important; padding: 0; }
  .stub-lines tfoot td::before { content: none; }
}

/* ---------- Job page: sections that open by relevance ---------- */

.job-section > summary {
  list-style: none; cursor: pointer; display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin: -2px 0 0; padding: 2px 0;
}
.job-section > summary::-webkit-details-marker { display: none; }
.job-section > summary h2 { margin: 0; }
.job-section > summary::before {
  content: "▸"; color: var(--ink-muted); font-size: var(--fs-base); transition: transform .15s ease;
}
.job-section[open] > summary::before { transform: rotate(90deg); }
.job-section > summary .sec-hint { color: var(--ink-muted); font-size: var(--fs-md); }
.job-section[open] > summary { margin-bottom: 8px; }
.job-section:not([open]) { padding-bottom: 12px; }

.next-block {
  display: flex; align-items: center; gap: 14px 20px; flex-wrap: wrap;
  border: 1px solid var(--border); border-left: 4px solid var(--gold); background: var(--surface);
  border-radius: var(--r); padding: 14px 18px; margin-bottom: 14px;
}
.next-block .next-main { flex: 1 1 320px; line-height: 1.5; }
.next-block .next-main strong { color: var(--ink); display: block; font-size: 1.05rem; }
.next-block .next-main span { color: var(--ink-2); }
.next-block .next-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.next-block.next-submitted { border-left-color: #e05030; }
.next-block.next-paid, .next-block.next-approved, .next-block.next-ready_pay { border-left-color: var(--good); }
.next-block.next-cancelled { border-left-color: var(--ink-faint); }

/* ---------- Phone: lists are cards, not stacked spreadsheets ---------- */
/* The stacked table printed every column with its label on its own line —
   fourteen jobs came to 5,963 px at 390 wide. A row is a card: the first
   cell is the title, the rest are short "label value" chips that wrap, and
   only a cell with a control in it gets a full line. */
@media (max-width: 700px) {
  .data-table.stack tbody tr {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 14px;
    padding: 10px 12px 9px; margin-bottom: 8px;
  }
  .data-table.stack tbody td {
    display: inline-block !important; width: auto !important; min-height: 0 !important;
    padding: 1px 0 !important; border: none !important; text-align: left !important;
    position: static !important; font-size: var(--fs-base); line-height: 1.4;
  }
  .data-table.stack tbody td::before {
    position: static !important; display: inline; width: auto !important; margin-right: 5px;
    font-size: 0.58rem; letter-spacing: 0.08em;
  }
  .data-table.stack tbody td:first-child {
    flex: 1 1 100%; display: block !important; font-size: 1rem; line-height: 1.35; margin-bottom: 3px;
  }
  .data-table.stack tbody td:first-child::before { content: none; }
  .data-table.stack tbody td[data-label=""]::before { content: none; }
  .data-table.stack tbody td:has(form), .data-table.stack tbody td:has(select),
  .data-table.stack tbody td:has(input[type=file]), .data-table.stack tbody td:has(textarea),
  .data-table.stack tbody td:has(input.rate-cell) {
    flex: 1 1 100%; display: block !important; margin-top: 6px;
  }
  .data-table.stack tbody td:has(form)::before, .data-table.stack tbody td:has(select)::before,
  .data-table.stack tbody td:has(input.rate-cell)::before {
    display: block; margin-bottom: 3px;
  }
  /* An editable rate is one full line: label above, the box the width of
     the card, every row the same — not a box sized by its label's length. */
  .data-table.stack tbody td .rate-cell { width: 100%; }
  .data-table.stack tbody td .badge { vertical-align: baseline; }
  .data-table.stack tfoot td { display: table-cell !important; }
  /* The job page on a phone: one column, and the sticky primary move. */
  .next-block { position: sticky; top: 64px; z-index: 5; }
}

/* ---------- Customer request: where it is ---------- */
.ask-stage { list-style: none; display: flex; gap: 0; margin: 0; padding: 0; font-size: var(--fs-xs); font-family: var(--mono); letter-spacing: 0.04em; }
.ask-stage li { padding: 3px 8px; border: 1px solid var(--border); color: var(--ink-muted); background: var(--bg); white-space: nowrap; }
.ask-stage li + li { border-left: none; }
.ask-stage li:first-child { border-radius: var(--r) 0 0 var(--r); }
.ask-stage li:last-child { border-radius: 0 var(--r) var(--r) 0; }
.ask-stage li.done { color: var(--ink-2); }
.ask-stage li.now { color: var(--gold-ink, #0b0c0e); background: var(--gold); border-color: var(--gold); font-weight: 600; }

/* A delete that looks like the edit next to it, only red — and the two
   of them on one line rather than the form dropping under the link. */
.row-actions { white-space: nowrap; }
.row-actions form { display: inline; margin-left: 6px; }
/* On a phone the row is a card and there is no column to keep the pair on
   one line: let Edit and Delete sit side by side and wrap if they must. */
@media (max-width: 700px) {
  .row-actions { white-space: normal; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
  .row-actions form { margin-left: 0; }
}
.chip-link.chip-danger { color: var(--bad, #e05030); cursor: pointer; font: inherit; font-size: var(--fs-sm); line-height: 1.2; }
.chip-link.chip-danger:hover { text-decoration: underline; }
.btn-ghost.btn-danger { color: var(--bad, #e05030); border-color: var(--bad, #e05030); }

/* Profitability's work-by-month table: the total is a table row on a
   desktop and one sentence on a phone, where a footer row has no labels. */
.flown-total { display: none; }
@media (max-width: 700px) {
  .flown-table tfoot { display: none; }
  .flown-total { display: block; }
}

/* ---------- "Put it on your home screen" ---------- */
/* One slim bar at the foot of the screen, once per phone. It never covers
   a control for long: Install or Not now and it is gone. */
.install-bar {
  position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 40;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 12px; border: 1px solid var(--gold-deep, #b8841c); border-radius: var(--r);
  background: var(--surface); color: var(--ink); font-size: var(--fs-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}
.install-bar span { flex: 1 1 220px; }
.install-bar .btn-gold, .install-bar .btn-ghost { min-height: 38px; padding: 6px 12px; font-size: var(--fs-md); }
@media (min-width: 900px) { .install-bar { left: auto; max-width: 520px; } }

/* ---------- Raw capture upload (the pilot's step after Captured) ---------- */
.fd-bar { height: 10px; border-radius: 6px; background: var(--bg); border: 1px solid var(--border); overflow: hidden; }
.fd-bar > span { display: block; height: 100%; background: var(--gold); transition: width 0.4s; }
/* ---------- Proposals: the editor, the rates page, the sign page ---------- */
.pb .pb-number { font-family: var(--mono); color: var(--gold); font-size: 1.2rem; }
.pb-bar {
  position: sticky; top: 0; z-index: 5; display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  margin: 0 0 14px; padding: 10px 14px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r);
}
.pb-bar-total { display: flex; align-items: baseline; gap: 8px; }
.pb-bar-total .label { color: var(--ink-muted); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.08em; }
.pb-bar-total strong { font-family: var(--mono); font-size: 1.25rem; color: var(--gold); font-variant-numeric: tabular-nums; }
.pb-status { margin: 0 auto 0 0; }
.pb-status.bad { color: var(--bad, #e05030); }
.pb-seg { display: inline-flex; border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; }
.pb-seg label { cursor: pointer; }
.pb-seg input { position: absolute; opacity: 0; width: 0; height: 0; }
.pb-seg span { display: block; padding: 6px 12px; font-size: var(--fs-sm); color: var(--ink-2); }
.pb-seg input:checked + span { background: var(--gold); color: #0b0c0e; font-weight: 600; }
.pb-seg input:focus-visible + span { outline: 2px solid var(--gold-deep); }
.pb-layout { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 16px; align-items: start; }
.pb-side { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.pb-side .card { margin: 0; }
.pb-side .fld { margin-top: 8px; }
.pb-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
.pb-grid3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0 12px; }
/* Picking what the job is made of: the services down the left, the items
   of the chosen one on the right, each with a tick. Ticked, a row opens
   into how many × at what rate = what it comes to. */
.pb-pick { display: grid; grid-template-columns: 176px minmax(0, 1fr); gap: 14px; align-items: start; }
.pb-pick-items { min-width: 0; }
.pb-cat-select { display: none; width: 100%; }
.pb-cat-list { display: flex; flex-direction: column; gap: 3px; }
.pb-cat {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  background: none; border: 1px solid transparent; border-radius: var(--r); color: var(--ink-2); cursor: pointer;
  padding: 7px 9px; font: inherit; font-size: var(--fs-md); line-height: 1.2;
}
.pb-cat:hover { border-color: var(--border); color: var(--ink); }
.pb-cat.on { background: var(--bg); border-color: var(--gold); color: var(--ink); }
.pb-cat.has .pb-cat-name { color: var(--ink); }
.pb-cat-icon { flex: 0 0 auto; }
.pb-cat-name { flex: 1; }
.pb-cat-n { display: inline-block; min-width: 18px; padding: 1px 5px; border-radius: 999px; background: var(--gold); color: #0b0c0e; font-size: var(--fs-xs); font-weight: 700; text-align: center; }
.pb-cat-head { margin: 2px 0 6px; }
.pb .card h2 .sec-hint { font-weight: 400; color: var(--ink-muted); font-size: var(--fs-sm); margin-left: 8px; }
.pb-market { font-family: var(--mono); font-size: var(--fs-xs); color: var(--ink-muted); margin-bottom: 10px; overflow-wrap: anywhere; }
.pb-items { display: flex; flex-direction: column; }
.pb-item { border-top: 1px solid var(--border); padding: 6px 0; }
.pb-item:last-child { border-bottom: 1px solid var(--border); }
.pb-item-main { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; cursor: pointer; margin: 0; font-size: var(--fs-base); min-height: 0; }
.pb-item-main input[type=checkbox] { width: 18px; height: 18px; min-width: 0; margin: 0; flex: 0 0 18px; accent-color: var(--gold); }
.pb-item-name { flex: 1 1 140px; min-width: 0; color: var(--ink-2); }
.pb-item.on .pb-item-name { color: var(--ink); font-weight: 600; }
.pb-item-rate { color: var(--ink-muted); font-size: var(--fs-sm); white-space: nowrap; font-variant-numeric: tabular-nums; margin-left: auto; }
.pb-item-rate em { font-style: normal; color: var(--gold); margin-left: 4px; }
.pb-item-fields { display: none; align-items: center; gap: 4px; flex-wrap: wrap; padding: 6px 0 2px 26px; }
.pb-item.on .pb-item-fields { display: flex; }
.pb-item-fields .pb-qty { width: 84px; min-width: 0; flex: none; padding: 5px 8px; text-align: right; }
.pb-item-fields .pb-rate { width: 96px; min-width: 0; flex: none; padding: 5px 8px; text-align: right; }
.pb-item-fields .pb-rate.changed { border-color: var(--gold); }
.pb-item-fields .pb-amt { font-family: var(--mono); font-variant-numeric: tabular-nums; margin-left: 4px; color: var(--ink); }
.pb-picked { margin-top: 4px; }
.pb-picked-row { display: grid; grid-template-columns: 130px minmax(0, 1fr) auto 24px; gap: 10px; align-items: center; padding: 5px 0; border-bottom: 1px solid var(--border); font-size: var(--fs-md); }
.pb-picked-cat { color: var(--ink-muted); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pb-picked-row small { color: var(--ink-muted); margin-left: 6px; }
.pb-picked-row strong { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.pb-picked-row .fd-x { background: none; border: none; color: var(--ink-muted); cursor: pointer; font-size: 1rem; line-height: 1; padding: 0 4px; }
.pb-picked-row .fd-x:hover { color: var(--bad, #e05030); }
.pb-picked-empty { padding: 8px 0 2px; }
.pb-dollar, .pb-x { color: var(--ink-muted); font-size: var(--fs-sm); margin: 0 3px; }
.pb-addon { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--border); }
.pb-addon:last-child { border-bottom: none; }
.pb-addon .pb-check { flex: 1 1 220px; margin: 0; }
.pb-addon-c { display: flex; align-items: center; gap: 4px; opacity: 0.45; }
.pb-addon.on .pb-addon-c { opacity: 1; }
.pb-addon-c input { width: 84px; min-width: 0; flex: none; padding: 5px 8px; text-align: right; }
.pb-check { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: var(--fs-base); }
.pb-check input[type=checkbox] { width: 18px; height: 18px; min-width: 0; flex: 0 0 18px; accent-color: var(--gold); }
.pb-custom-row, .pb-ms-row { display: flex; align-items: center; gap: 6px; margin: 6px 0; }
.pb-custom-row input[data-f=name] { flex: 2 1 160px; }
.pb-custom-row input[data-f=detail] { flex: 2 1 140px; }
.pb-custom-row input[data-f=amount] { flex: 0 0 110px; min-width: 0; text-align: right; }
.pb-ms-row input[data-f=label] { flex: 1 1 200px; }
.pb-ms-row input[data-f=percent] { flex: 0 0 76px; min-width: 0; text-align: right; }
.pb-clause { margin: 8px 0 12px; }
.pb-clause-top { display: flex; gap: 6px; align-items: center; margin-bottom: 4px; }
.pb-clause-top input { flex: 1; font-weight: 600; }
.pb-clause textarea { width: 100%; font-size: var(--fs-md); }
.pb-fold > summary h2 { display: flex; align-items: center; gap: 8px; }
.pb-fold > summary .pb-inc { display: inline-flex; margin: 0; }
.pb-fold > summary .pb-inc input { width: auto; margin: 0; }
.pb-fold > .pb-fold-body { padding: 0 18px 18px; }
.pb-fold > .pb-fold-body .btn-ghost { margin: 10px 6px 0 0; }
.pb-fold .sec-hint.bad { color: var(--bad, #e05030); }
.pb-photo { border: 1px dashed var(--border); border-radius: var(--r); padding: 12px; text-align: center; transition: border-color .15s; }
.pb-photo.over { border-color: var(--gold); }
.pb-photo-empty { cursor: pointer; color: var(--ink-muted); font-size: var(--fs-base); padding: 12px 0; }
.pb-photo-empty small { color: var(--ink-muted); font-size: var(--fs-xs); }
.pb-photo-preview { position: relative; }
.pb-photo-preview img { max-width: 100%; max-height: 260px; border-radius: 3px; }
.pb-photo-preview .fd-x { position: absolute; top: 4px; right: 4px; background: rgba(0, 0, 0, 0.6); border-radius: 50%; padding: 2px 7px; color: #fff; }
.pb-preview { width: 100%; height: 780px; border: 1px solid var(--border); border-radius: var(--r); background: #2b2b2e; }
.pb-public-pdf { width: 100%; height: min(1000px, 90vh); border: none; display: block; background: #2b2b2e; }
.rates-table .rate-changed td:first-child { color: var(--gold); }
.rates-table input { width: 110px; min-width: 0; flex: none; padding: 5px 8px; text-align: right; }
@media (max-width: 900px) {
  .pb-layout { grid-template-columns: 1fr; }
  .pb-grid2, .pb-grid3 { grid-template-columns: 1fr; }
  .pb-pick { grid-template-columns: 1fr; }
  .pb-bar { gap: 6px 8px; padding: 8px 10px; }
  .pb-bar .btn-ghost, .pb-bar .btn-gold { padding: 6px 10px; font-size: var(--fs-sm); }
  .pb-bar-total strong { font-size: 1.05rem; }
  .pb-item-main input[type=checkbox], .pb-check input[type=checkbox] { width: 22px; height: 22px; flex-basis: 22px; }
  .pb-cat-list { display: none; }
  .pb-cat-select { display: block; }
  .pb-picked-row { grid-template-columns: minmax(0, 1fr) auto 24px; }
  .pb-picked-cat { display: none; }
  .pb-preview { height: 70vh; }
  .pb-bar { top: 0; }
  .pb-status { flex-basis: 100%; }
}

/* Files: "Delete now" in progress — one panel over the page, wherever the
   button was pressed, with the bar and what is happening right now. */
.dn-panel {
  position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%);
  width: min(560px, calc(100vw - 24px)); z-index: 45;
  background: var(--surface); border: 1px solid var(--gold); border-radius: var(--r);
  padding: 14px 16px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}
.dn-panel .dn-title { font-weight: 600; margin-bottom: 8px; overflow-wrap: anywhere; }
.dn-panel .dn-text { margin-top: 8px; font-size: var(--fs-md); color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.dn-panel.dn-bad { border-color: var(--bad, #e05030); }
.dn-panel.dn-bad .dn-text { color: var(--ink-2); }
.dn-panel.dn-bad .fd-bar > span { background: var(--bad, #e05030); }
/* Files: the drive-style browser */
.fb-crumbs { font-size: 0.95rem; display: flex; flex-wrap: wrap; gap: 4px 6px; align-items: baseline; }
.fb-crumbs .fb-sep { color: var(--ink-muted); }
.fb-row[data-href] { cursor: pointer; }
.fb-row[data-href]:hover td { background: color-mix(in srgb, var(--gold) 6%, transparent); }
.fd-status { display: flex; flex-wrap: wrap; gap: 6px 18px; white-space: normal; overflow-wrap: anywhere; }
.fd-status-row td { white-space: normal; text-align: left; padding-top: 4px; }
/* Drop zone under the pick buttons; a computer thing, hidden until the script
   knows it is not on a phone. Gold while something is being dragged over it. */
.fd-drop {
  margin-top: 8px; padding: 16px 12px; text-align: center; font-size: var(--fs-md); color: var(--ink-muted);
  border: 1px dashed var(--border); border-radius: 8px; transition: border-color .15s, background .15s;
}
.fd-drop.over { border-color: var(--gold); color: var(--ink); background: color-mix(in srgb, var(--gold) 8%, transparent); }
@media (pointer: coarse) { .fd-folder { display: none !important; } }   /* phones have no folder picker */
.fd-stat { display: flex; flex-direction: column; min-width: 90px; }
.fd-stat .fd-k { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-muted); }
.fd-stat strong { font-variant-numeric: tabular-nums; }
.fd-list { max-height: 400px; overflow-y: auto; border: 1px solid var(--border); border-radius: 8px; padding: 0 10px; }   /* about fifteen rows; the rest scroll */
.fd-row { padding: 6px 0; border-bottom: 1px solid var(--border); font-size: var(--fs-md); }
.fd-row:last-child { border-bottom: none; }
.fd-row.fd-now { background: color-mix(in srgb, var(--gold) 8%, transparent); margin: 0 -10px; padding-left: 10px; padding-right: 10px; }
.fd-row .fd-x { background: none; border: none; color: var(--ink-muted); cursor: pointer; font-size: 1rem; line-height: 1; padding: 0 6px; }
.fd-row .fd-x:hover { color: var(--bad, #e05030); }
.fd-row-top { display: flex; justify-content: space-between; gap: 10px; }
.fd-row .fd-name { overflow-wrap: anywhere; }
.fd-row .fd-state { color: var(--ink-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.fd-mini { height: 3px; margin-top: 4px; border-radius: 2px; background: var(--bg); overflow: hidden; }
.fd-mini > span { display: block; height: 100%; width: 0; background: var(--gold); transition: width 0.3s; }
.fd-row.fd-ok .fd-mini > span { background: var(--good); width: 100% !important; }
.fd-row.fd-ok .fd-state { color: var(--good); }
.fd-row.fd-bad .fd-state { color: var(--bad, #e05030); white-space: normal; text-align: right; }

/* Profitability: the priced-but-not-invoiced note under a project's revenue */
.not-invoiced { color: var(--ink-muted); font-size: var(--fs-xs); font-weight: 400; white-space: nowrap; }

/* Invoice edit: the jobs an invoice covers */
.inv-jobs { display: flex; flex-direction: column; gap: 6px; max-height: 320px; overflow-y: auto; padding: 4px 0; }
.inv-job { display: flex; gap: 8px; align-items: flex-start; font-size: var(--fs-md); cursor: pointer; }
.inv-job input { margin-top: 3px; flex: none; }
.inv-job-other { color: var(--ink-muted); }
.inv-job-meta { display: block; color: var(--ink-muted); font-size: var(--fs-xs); }

/* ---------- Pay run on a phone ----------
   Two things went wrong here at phone width. The tools block stacks into a
   column, and a flex-basis of 260px on the search box then applied to its
   HEIGHT, so the box filled a screen. And the stacked table drew each job as
   a 260px card with a label on every cell, so Patrick's 53 jobs made a
   14,000px page — "it feels like it freezes" is a fair description of
   scrolling that. Each job is now one short card: tick box, title and
   reference numbers, customer and amount, date and status. */
input[type="search"].search-input { -webkit-appearance: none; appearance: none; }
input[type="search"].search-input::-webkit-search-decoration { -webkit-appearance: none; }
.btn-gold.btn-armed { outline: 2px solid var(--gold-deep); outline-offset: 2px; }
@media (max-width: 700px) {
  .pay-tools .search-input { flex: none; width: 100%; min-height: 44px; }
  .pay-btns .btn-ghost { min-height: 40px; padding: 6px 8px; font-size: var(--fs-md); }
  /* The running total stays in view while you tick your way down the list. */
  .pay-sum {
    position: sticky; top: 0; z-index: 3;
    background: var(--surface, var(--bg)); padding: 8px 0; margin: 0 0 6px;
    border-bottom: 1px solid var(--border);
  }
  #pay-table tbody tr {
    display: grid; grid-template-columns: 44px 1fr auto; column-gap: 8px; row-gap: 2px;
    grid-template-areas: "cb job job" "cb cust amt" "cb flown st";
    padding: 8px 8px 8px 4px; align-items: center;
  }
  #pay-table tbody tr[hidden] { display: none; }
  #pay-table tbody td { display: block; width: auto; padding: 0; border: none; min-width: 0; }
  #pay-table tbody td::before { content: none !important; }
  #pay-table tbody td[data-label="Pay this one"] { grid-area: cb; }
  #pay-table tbody td[data-label="Pay this one"] .cb-hit { margin: 0; }
  #pay-table tbody td[data-label="Job"] { grid-area: job; font-size: var(--fs-base); line-height: 1.3; overflow-wrap: anywhere; }
  #pay-table tbody td[data-label="Customer"] { grid-area: cust; font-size: var(--fs-sm); color: var(--ink-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  #pay-table tbody td[data-label="Customer"] br, #pay-table tbody td[data-label="Customer"] span { display: none; }
  #pay-table tbody td[data-label="Amount"] { grid-area: amt; text-align: right; font-family: var(--mono); font-size: var(--fs-base); }
  #pay-table tbody td[data-label="Amount"] br { display: none; }
  #pay-table tbody td[data-label="Amount"] span { margin-left: 4px; }
  #pay-table tbody td[data-label="Flown"] { grid-area: flown; text-align: left; font-size: var(--fs-sm); color: var(--ink-muted); }
  #pay-table tbody td[data-label="Where it's at"] { grid-area: st; justify-self: end; }
  #pay-table tbody td[data-label="Where it's at"] .status-select {
    max-width: none; width: auto; min-height: 36px; padding: 5px 8px; font-size: 14px;
  }
}

/* ---------- Customer page: header, KPI strip, tabs ----------
   The page is a header (who they are, the money, what to do next) over a row
   of tabs; each tab's panel is fetched on its own so the first paint is the
   overview, not everything at once. On a phone the tab row scrolls sideways
   with a fade at whichever edge has more, the KPI strip scrolls too, and the
   six header buttons fold into one "+ New" menu. */
.cust .chdr { margin-bottom: 14px; }
.chdr-top { display: flex; gap: 16px; align-items: flex-start; flex-wrap: wrap; }
.chdr-who { flex: 1 1 360px; min-width: 0; }
.chdr-industry { display: inline; margin: 0; align-self: center; }
.chdr-meta { display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; margin-top: 8px; font-size: var(--fs-md); color: var(--ink-2); }
.chdr-contact { overflow-wrap: anywhere; }
.chdr-contact strong { color: var(--ink); }
.chdr-status .status-select { min-height: 32px; padding: 3px 8px; font-size: var(--fs-sm); }
.chdr-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: flex-end; }
.chdr-actions .btn-ghost, .chdr-actions .btn-gold { text-decoration: none; white-space: nowrap; }
.chdr-menu { display: none; position: relative; }
.chdr-menu > summary { list-style: none; cursor: pointer; display: inline-block; text-decoration: none; }
.chdr-menu > summary::-webkit-details-marker { display: none; }
.chdr-menu-body {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 20; min-width: 200px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45); display: flex; flex-direction: column; padding: 6px 0;
}
.chdr-menu-body a { display: block; padding: 10px 14px; color: var(--ink); text-decoration: none; font-size: var(--fs-base); min-height: 44px; }
.chdr-menu-body a:hover, .chdr-menu-body a:focus-visible { background: var(--surface-2); color: var(--gold); }
.chdr-pop { position: relative; }
.chdr-pop > summary { list-style: none; cursor: pointer; margin: 0; }
.chdr-pop > summary::-webkit-details-marker { display: none; }
.chdr-pop > summary.chip-link { color: var(--gold); }
.chdr-pop > summary.chip-today { color: var(--gold); border-color: var(--gold); }
.chdr-pop-body {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 20; width: min(360px, calc(100vw - 32px));
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45); padding: 12px; display: flex; flex-direction: column; gap: 8px;
}
.chdr-pop-body .search-input { width: 100%; min-width: 0; }
.chdr-pop-body .card-sub { margin: 0; }
.chdr-pop-body .btn-ghost { align-self: flex-start; }

.ckpi-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-top: 14px; }
.ckpi {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r);
  padding: 10px 14px; color: inherit; text-decoration: none; min-width: 0;
}
a.ckpi { transition: border-color 0.12s ease, background 0.12s ease; }
a.ckpi:hover, a.ckpi:focus-visible { border-color: var(--gold); background: var(--surface-2, var(--surface)); }
.ckpi .label { color: var(--ink-muted); font-family: var(--mono); font-size: var(--fs-label); text-transform: uppercase; letter-spacing: 0.12em; white-space: nowrap; }
.ckpi .value { font-size: 1.35rem; font-weight: 700; margin-top: 2px; font-variant-numeric: tabular-nums lining-nums; }
.ckpi .value small { font-size: var(--fs-md); color: var(--ink-2); font-weight: 400; }

.ctabs {
  display: flex; gap: 2px; border-bottom: 1px solid var(--border); margin: 6px 0 16px;
  overflow-x: auto; overflow-y: hidden; scrollbar-width: none; -webkit-overflow-scrolling: touch; position: relative;
  touch-action: pan-x; overscroll-behavior-x: contain;
}
.ctabs::-webkit-scrollbar { display: none; }
.ctab {
  flex: none; padding: 10px 14px; margin-bottom: -1px; color: var(--ink-2); text-decoration: none; font-size: var(--fs-base);
  border-bottom: 2px solid transparent; white-space: nowrap; min-height: 44px; display: inline-flex; align-items: center; gap: 6px;
}
.ctab:hover, .ctab:focus-visible { color: var(--ink); }
.ctab.on { color: var(--gold); border-bottom-color: var(--gold); }
.ctab-n {
  font-family: var(--mono); font-size: var(--fs-label); padding: 1px 6px; border-radius: 10px;
  background: rgba(255, 255, 255, 0.06); color: var(--ink-muted); white-space: nowrap;
}
.ctab.on .ctab-n { background: rgba(233, 168, 38, 0.18); color: var(--gold); }
.ctab-panel { min-height: 200px; }
.ctab-panel.htmx-request { opacity: 0.6; transition: opacity 0.15s ease 0.1s; }

/* Filter chips inside a tab — Active / Completed / All, Open / Paid, kinds of file. */
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  display: inline-flex; align-items: center; gap: 5px; padding: 5px 10px; min-height: 32px;
  border: 1px solid var(--border); border-radius: 16px; color: var(--ink-2); text-decoration: none; font-size: var(--fs-sm); white-space: nowrap;
}
.chip:hover, .chip:focus-visible { color: var(--ink); border-color: var(--ink-muted); }
.chip.on { color: var(--gold); border-color: var(--gold); background: rgba(233, 168, 38, 0.08); }

/* Overview cards: a few rows each, "View all" in the corner. */
.ov-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 14px; }
.ov-card { margin: 0; min-width: 0; }
.ov-card h2 { display: flex; align-items: baseline; gap: 10px; }
.ov-more { margin-left: auto; font-size: var(--fs-sm); font-weight: 400; color: var(--gold); text-decoration: none; white-space: nowrap; }
.ov-more:hover { text-decoration: underline; }
.ov-row { display: flex; justify-content: space-between; gap: 12px; padding: 8px 0; border-top: 1px solid var(--border); font-size: var(--fs-base); min-width: 0; }
.ov-row > div:first-child { min-width: 0; overflow-wrap: anywhere; }
.ov-right { text-align: right; flex: none; font-size: var(--fs-md); }
.ov-empty { padding: 14px 0 4px; }
.ov-card > .card-sub:last-child { margin-top: 6px; }

/* Billing tab: the totals over the table. */
.bill-totals { display: flex; flex-wrap: wrap; gap: 8px 24px; margin: 10px 0 4px; }
.bill-totals > div { display: flex; flex-direction: column; }
.bill-totals .label { color: var(--ink-muted); font-family: var(--mono); font-size: var(--fs-label); text-transform: uppercase; letter-spacing: 0.1em; }
.bill-totals strong { font-size: 1.05rem; font-variant-numeric: tabular-nums; }
tr.inv-pay td { padding-top: 2px; padding-bottom: 8px; border-top: none; }
.inv-row.inv-sent td .chip-link[title="Attach the PDF you sent"],
.inv-row.inv-partial td .chip-link[title="Attach the PDF you sent"] { color: var(--bad, #e05030); border-color: rgba(224, 80, 48, 0.5); }
.po-label { font-family: var(--mono); font-size: var(--fs-xs); font-weight: 400; color: var(--ink-muted); margin-left: 6px; }

/* Activity tab: the inbox bar, then the timeline. */
.inbox-bar {
  display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; margin-bottom: 14px; padding: 10px 14px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); font-size: var(--fs-md); color: var(--ink-2);
}
.inbox-bar strong { color: var(--ink); }
.inbox-bar form { margin-left: auto; }
.tl { display: flex; flex-direction: column; }
.tl-item { padding: 10px 0 10px 14px; border-top: 1px solid var(--border); border-left: 2px solid var(--border); font-size: var(--fs-base); }
.tl-item.tl-k-hand { border-left-color: var(--gold); }
.tl-item.tl-k-sync { border-left-color: var(--series-2); }
.tl-item.tl-k-app { border-left-color: var(--series-3); }
.tl-head { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; font-size: var(--fs-xs); color: var(--ink-muted); }
.tl-kind { font-family: var(--mono); font-size: var(--fs-label); text-transform: uppercase; letter-spacing: 0.08em; padding: 1px 6px; border-radius: 3px; background: rgba(255, 255, 255, 0.06); }
.tl-kind.tl-hand { color: var(--gold); background: rgba(233, 168, 38, 0.14); }
.tl-kind.tl-sync { color: var(--series-2); background: rgba(57, 135, 229, 0.16); }
.tl-kind.tl-app { color: var(--series-3); background: rgba(25, 158, 112, 0.16); }
.tl-who { color: var(--ink-2); }
.tl-title { margin-top: 3px; color: var(--ink); }
.tl-text { margin-top: 3px; white-space: pre-line; overflow-wrap: anywhere; color: var(--ink-text); }
.tl-text.clamp { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.tl-text.clamp.open { display: block; -webkit-line-clamp: unset; }
.tl-more { background: none; border: none; color: var(--gold); cursor: pointer; padding: 2px 0; font-size: var(--fs-sm); font-family: inherit; }
.tl-short { min-width: 0; overflow-wrap: anywhere; }
.tl-short .tl-kind { margin-right: 2px; }
.danger-zone > summary h2 { color: var(--bad, #e05030); }

@media (max-width: 768px) {
  .chdr-top { gap: 10px; position: relative; }
  .chdr-who .page-head { padding-right: 88px; }   /* room for the + New button beside the title */
  .chdr-actions { display: none; }
  .chdr-menu { display: block; position: absolute; top: 0; right: 0; }
  .chdr-meta { gap: 6px 10px; font-size: var(--fs-md); }
  .ckpi .label { white-space: normal; line-height: 1.3; }
  .ckpi-strip {
    display: flex; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
    margin: 12px -12px 0; padding: 0 12px 4px; scroll-snap-type: x proximity;
  }
  .ckpi-strip::-webkit-scrollbar { display: none; }
  .ckpi { flex: 0 0 156px; scroll-snap-align: start; }
  .ctabs { margin: 4px -12px 14px; padding: 0 12px; scroll-padding: 0 12px; }
  .ctabs::before, .ctabs::after {
    content: ""; position: sticky; top: 0; bottom: 0; flex: none; width: 24px; pointer-events: none; opacity: 0; transition: opacity 0.15s;
  }
  .ctabs::before { left: 0; margin-right: -24px; background: linear-gradient(to right, var(--bg), transparent); }
  .ctabs::after { right: 0; margin-left: -24px; background: linear-gradient(to left, var(--bg), transparent); }
  .ctabs.more-left::before { opacity: 1; }
  .ctabs.more-right::after { opacity: 1; }
  .ctab { padding: 10px 12px; font-size: var(--fs-base); }
  .ov-grid { grid-template-columns: 1fr; }
  .ov-row { flex-direction: column; gap: 2px; }
  .ov-right { text-align: left; }
  .inbox-bar form { margin-left: 0; width: 100%; }
  .inbox-bar form .btn-ghost { width: 100%; }
  .bill-totals { gap: 8px 18px; }
  .inv-row td[data-label="Invoice"] .chip-link { display: inline-flex; width: auto; margin: 4px 0 0; }
  .tl-item { padding-left: 10px; }
}

/* Contacts tab: the add box and the inline edit row share one form. */
.contact-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 8px 10px; }
.contact-fields .fld { margin: 0; }
.contact-fields .fld-wide { grid-column: 1 / -1; }
.contact-fields .search-input { width: 100%; min-width: 0; }
.contact-roles { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 10px; }
.contact-roles .fld-label { margin-right: 4px; }
.contact-roles label.chip { cursor: pointer; }
.contact-roles label.chip input { margin: 0; width: 14px; height: 14px; accent-color: var(--gold); }
.contact-editing td { background: color-mix(in srgb, var(--gold) 5%, transparent); }
.contacts-table td[data-label="Roles"] .badge { margin: 1px 2px 1px 0; }
@media (max-width: 768px) {
  .contact-fields { grid-template-columns: 1fr 1fr; }
  .contact-fields .fld-wide, .contact-fields .fld:nth-child(3), .contact-fields .fld:nth-child(4) { grid-column: 1 / -1; }
  .contacts-table td[data-label=""] { display: flex; flex-wrap: wrap; gap: 6px; }
  .contacts-table td[data-label=""] .btn-ghost { min-height: 40px; }
}

/* Rates tab and the printable rate sheet. */
.rate-cat { font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-muted); margin: 18px 0 6px; }
.rate-more > summary { list-style: none; cursor: pointer; }
.rate-more > summary::-webkit-details-marker { display: none; }
.rate-more > summary::after { content: " ▸"; color: var(--ink-muted); font-size: var(--fs-sm); }
.rate-more[open] > summary::after { content: " ▾"; }
.rate-detail { margin-top: 8px; font-size: var(--fs-md); color: var(--ink-text); max-width: 640px; }
.tier-rows { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.tier-row { display: flex; gap: 6px; align-items: center; }
.tier-row .search-input { min-width: 0; flex: 1 1 90px; width: auto; }
.tier-row span { color: var(--ink-muted); }
.rs-head { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px; }
.rs-desc { color: var(--ink-2); font-size: var(--fs-sm); white-space: pre-line; margin-top: 3px; }
@media print {
  .rate-sheet .page-head button, .rate-sheet .page-head a, .flash-stack { display: none !important; }
  .rate-sheet .card { border: none; padding: 0; }
  .rate-sheet .rate-cat, .rate-sheet .rs-desc, .rate-sheet td, .rate-sheet th { color: #000 !important; }
  .rate-sheet .data-table th, .rate-sheet .data-table td { border-color: #bbb; }
  .rate-sheet .data-table thead th, .rate-sheet .data-table thead { background: #f0f0f0 !important; color: #000 !important; }
  .rate-sheet .card-sub, .rate-sheet .rs-head { color: #333 !important; }
  .rate-sheet h1 { font-size: 1.3rem; }
}
@media (max-width: 768px) {
  .rates-table td[data-label=""] { display: flex; flex-wrap: wrap; gap: 6px; }
  .rates-table td[data-label=""] .btn-ghost { min-height: 40px; }
  .tier-row { flex-wrap: wrap; }
}

/* ---- Pilots hub ------------------------------------------------------- */
/* The hub strip on Roster / Applicants / Scorecards, and the pipeline
   chip: one status that follows a person from application to roster. */
.hub-tabs { margin-top: -6px; }
.pipe { white-space: nowrap; }
.pipe-new       { color: var(--series-2); border-color: rgba(57, 135, 229, 0.55); }
.pipe-contacted { color: var(--gold); border-color: rgba(233, 168, 38, 0.5); }
.pipe-invited   { color: var(--gold); border-color: var(--gold); border-style: dashed; }
.pipe-signed_up { color: var(--good); border-color: rgba(67, 176, 107, 0.5); }
.pipe-inactive, .pipe-passed, .pipe-archived { color: var(--ink-muted); border-color: var(--border); }
.setup-badge { font-size: var(--fs-label); vertical-align: middle; }
a.pipe { text-decoration: none; }
/* The clear-to-fly checklist on the pilot's Overview. */
.checklist { list-style: none; margin: 10px 0 0; padding: 0; }
.checklist li { display: grid; grid-template-columns: 22px auto 1fr; gap: 8px; align-items: baseline; padding: 6px 0; border-top: 1px solid var(--border); font-size: var(--fs-base); }
.checklist li:first-child { border-top: 0; }
.ck-mark { font-family: var(--mono); font-weight: 700; text-align: center; }
.ck-ok .ck-mark { color: var(--good); }
.ck-warn .ck-mark { color: var(--gold); }
.ck-missing .ck-mark { color: #e05030; }
.ck-missing strong { color: #e05030; }
.ov-form { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin: 0; justify-content: flex-end; }
.ov-form .status-select { min-height: 34px; padding: 4px 8px; font-size: var(--fs-md); }

/* ---- Pilot map ---------------------------------------------------------- */
/* Pins by pipeline status: colour and shape both carry it, a red ring means
   not clear to fly, an envelope means invited with no account yet. */
.ppin { display: flex; align-items: center; justify-content: center; width: 20px; height: 20px; box-sizing: border-box;
  border: 2px solid rgba(0, 0, 0, 0.6); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.55); color: #0b0c0e; font-size: 11px; line-height: 1; }
.ppin-signed { background: #3fd07a; border-radius: 50%; }
.ppin-reach  { background: #e9a826; border-radius: 4px; }
.ppin-new    { background: #4fb3ff; transform: rotate(45deg); border-radius: 3px; }
.ppin-new .ppin-mail { transform: rotate(-45deg); }
.ppin-gone   { background: #262a30; border-radius: 50%; border-color: #8a929c; border-style: dashed; }
.ppin-ring   { box-shadow: 0 0 0 3px #e05030, 0 1px 4px rgba(0, 0, 0, 0.55); }
.ppin-ring-only { background: transparent; border-color: transparent; box-shadow: 0 0 0 3px #e05030; }
.ppin-key { width: 12px; height: 12px; border-width: 1px; font-size: 8px; box-shadow: none; }
.ppin-key.ppin-ring { box-shadow: 0 0 0 2px #e05030; }
.ppin-mail { font-weight: 700; }
.ppin-cluster { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%;
  background: rgba(233, 168, 38, 0.9); color: #0b0c0e; font-family: var(--mono); font-weight: 700; font-size: 12px;
  border: 2px solid rgba(0, 0, 0, 0.6); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.55); }
.pmap-row { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: 12px; align-items: start; }
.pmap-side { margin-top: 12px; }
.pmap-unplaced { list-style: none; margin: 6px 0 0; padding: 0; font-size: var(--fs-md); }
.pmap-unplaced li { padding: 6px 0; border-top: 1px solid var(--border); }
.pmap-filters { margin-top: 10px; }
.pmap-filters > summary { display: none; list-style: none; cursor: pointer; }
.pmap-filters > summary::-webkit-details-marker { display: none; }
.pmap-filter-body { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.pmap-filter-body .search-input { flex: 1 1 200px; min-width: 160px; }
.pmap-pop { min-width: 240px; }
.pmap-k { color: var(--ink-2); font-family: var(--mono); font-size: var(--fs-label); text-transform: uppercase; letter-spacing: 0.08em; }
.pmap-pop .pin-meta { margin-top: 4px; }
.pmap-sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 1000; background: var(--surface); border-top: 1px solid var(--border);
  border-radius: 14px 14px 0 0; padding: 14px 16px 18px; box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.5); max-height: 70vh; overflow-y: auto; }
.pmap-sheet[hidden] { display: none; }
.pmap-sheet-close { position: absolute; top: 8px; right: 10px; background: none; border: 0; color: var(--ink-muted); font-size: 1rem; min-width: 44px; min-height: 44px; }
.pmap-sheet .pin-pop { min-width: 0; }
@media (max-width: 900px) {
  .pmap-row { grid-template-columns: 1fr; }
  .pmap-filters > summary { display: inline-flex; }
  .pmap-filters:not([open]) .pmap-filter-body { display: none; }
  .pmap-filter-body { margin-top: 8px; }
}
@media (max-width: 768px), (pointer: coarse) {
  .pmap-wrap .card.full { padding-left: 0; padding-right: 0; }
  .pmap-wrap .card.full > h2, .pmap-wrap .card.full > .card-sub, .pmap-wrap .card.full > .pmap-filters, .pmap-wrap .card.full > .map-legend, .pmap-side { padding-left: 12px; padding-right: 12px; }
  .pmap { border-left: 0; border-right: 0; border-radius: 0; }
}

/* Phones: the small links inside stacked table rows, overview rows and the
   map's side list get a full-height tap area, and the status badge on the
   jobs board is a finger-sized button. */
@media (max-width: 768px), (pointer: coarse) {
  .data-table.stack td a, .ov-row a, .pmap-unplaced a, .ov-card .card-sub a, .notice a, .kpi-note a {
    display: inline-flex; align-items: center; min-height: 44px; padding: 0 2px;
  }
  .ov-row .ov-right a { min-height: 36px; }   /* a phone and an email stacked in one cell: tappable, not towering */
  .data-table.stack td a strong { display: inline; }
  .status-pick .status-badge { min-height: 40px; display: inline-flex; align-items: center; }
  .att-card a, .att-more { min-height: 44px; display: inline-flex; align-items: center; }
}
@media (max-width: 768px), (pointer: coarse) {
  .chdr-contact a, .ov-more, .card-sub a, .subnav a, .range-picker a { display: inline-flex; align-items: center; min-height: 44px; }
  main .btn-ghost, main .btn-gold { min-height: 44px; }
}

/* ---------------------------------------------------------------------------
   Utilities
   The handful of inline styles that appeared on hundreds of elements, as
   classes. Add a class here before writing style="" in a template.
--------------------------------------------------------------------------- */
.muted { color: var(--ink-muted) !important; }
.ink { color: var(--ink) !important; }
.gold { color: var(--gold) !important; }
.good { color: var(--good) !important; }
.bad { color: var(--bad) !important; }
.mono { font-family: var(--mono) !important; }
.small { font-size: var(--fs-xs) !important; }
.tiny { font-size: var(--fs-label) !important; }
.hint { color: var(--ink-muted) !important; font-size: var(--fs-xs) !important; }
.plain { text-decoration: none !important; }
.plain:hover { text-decoration: none !important; }
.nowrap { white-space: nowrap !important; }
.pre-line { white-space: pre-line !important; }
.inline { display: inline !important; }
.m-0 { margin: 0 !important; }
.mt-4 { margin-top: 4px !important; }
.mt-6 { margin-top: 6px !important; }
.mt-8 { margin-top: 8px !important; }
.mt-10 { margin-top: 10px !important; }
.mt-12 { margin-top: 12px !important; }
.mt-14 { margin-top: 14px !important; }
.mt-16 { margin-top: 16px !important; }
.mt-18 { margin-top: 18px !important; }
.mb-12 { margin-bottom: 12px !important; }
.mb-14 { margin-bottom: 14px !important; }
.mb-16 { margin-bottom: 16px !important; }
.ml-auto { margin-left: auto !important; }
.w-full { width: 100% !important; }
.self-center { align-self: center !important; }
.row-actions { margin-left: auto !important; display: flex !important; gap: 8px !important; flex-wrap: wrap !important; align-items: center !important; }

/* A wide table scrolls inside its card instead of running past its edge. */
.table-scroll { overflow-x: auto; max-width: 100%; }
/* An overflow box is its own scrolling frame, so a sticky heading inside it
   pins 63px down from the box, not from the page: it floated over the first
   row. Inside the wrapper the heading simply stays where it is. */
.table-scroll .data-table thead th { position: static; }
/* The customer's files table: three dropdowns a row, sized so eight columns
   fit the card on a desktop; the dates and buttons never wrap. */
.files-table .status-select { max-width: 150px; min-width: 0; }
.files-table td.file-name { max-width: 300px; overflow-wrap: anywhere; }
.files-table td.added { white-space: nowrap; }

/* The upload form under the files: a labelled field per control, the
   button on the end. The file picker's own box never grows past the form:
   WebKit sizes a file input by its button and text and will not shrink it
   on its own, which is how it ran off the card on a phone. */
.upload-form { margin-top: 12px; align-items: flex-end; }
.upload-form .fld { flex: 1 1 170px; }
.upload-form .fld-narrow { flex: 0 1 160px; }
.upload-form .file-input { padding: 7px; min-width: 0; max-width: 100%; }
.upload-form .upload-go { align-self: flex-end; }
input[type="file"].search-input { min-width: 0; max-width: 100%; }

/* Phone: a file is one card. The name breaks wherever it must (a flex item
   otherwise keeps a long filename on one line and pushes the card sideways,
   which is the overhang WebKit showed), the four dropdowns sit two to a
   row, and nothing sets the card wider than the screen. */
@media (max-width: 700px) {
  .data-table.stack tbody td { min-width: 0; max-width: 100%; }
  .files-table td.file-name { max-width: none; }
  .files-table td.file-name a { display: block; overflow-wrap: anywhere; word-break: break-word; }
  .files-table tbody td:has(select) { flex: 1 1 calc(50% - 7px) !important; max-width: calc(50% - 7px); }
  .files-table tbody td:has(select) form { margin: 0; }
  .files-table .status-select { width: 100%; max-width: none; }
  .files-table tbody td.nowrap { flex: 1 1 100%; display: flex !important; gap: 10px; margin-top: 8px; }
  .filter-row > select, .filter-row > input:not([type="checkbox"]):not([type="radio"]) { min-width: 0; }
  .upload-form .fld, .upload-form .fld-narrow { flex: 1 1 100%; }
  .upload-form .upload-go { width: 100%; }
}

/* Anything HTMX is fetching dims and the cursor says so; nothing jumps. */
.htmx-request { cursor: progress; }

/* ---------- Customer portal: the home page in sections ---------- */
/* One row of chips under the heading takes you to the part you came for;
   a customer with six projects and forty invoices should not have to scroll
   past the map to find the invoice they were asked about. */
.portal-sections { margin: -6px 0 16px; }
.portal-sections .chip { text-decoration: none; }
.portal-contact { color: var(--ink-muted); font-size: var(--fs-md); margin: -8px 0 14px; }
.portal-contact a { color: var(--gold); }
/* The office looking at the portal as the customer: a band across the top
   says so, and the forms that would send something are shown but inert. */
.preview-band {
  display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center;
  margin: 0 0 16px; padding: 10px 14px; border-radius: var(--r);
  border: 1px solid var(--gold-deep, #b8841c); background: rgba(233, 168, 38, 0.08);
  color: var(--ink); font-size: var(--fs-md);
}
.preview-band strong { color: var(--gold); }
.preview-band .card-sub { margin: 0; }
/* The portal-access card on the customer page. */
.portal-access .access-table .invite-link { font-family: var(--mono); font-size: 0.7rem; max-width: 260px; min-width: 0; }
.portal-access .invite-form { align-items: flex-end; }
.portal-access .invite-form .fld { flex: 1 1 220px; }
.self-end { align-self: flex-end !important; }
@media (max-width: 700px) {
  .portal-access .access-table .invite-link { max-width: 100%; width: 100%; }
  .portal-access .invite-form .fld, .portal-access .invite-form .btn-gold { flex: 1 1 100%; width: 100%; }
  .portal-sections { margin-top: 0; }
}

/* ---------- Customer portal: four tabs and a landing page ---------- */
.portal-head { margin-bottom: 10px; }
.portal-head h1 { margin: 0 0 4px; }
.portal-head .portal-contact { margin: 0; }
.portal-tabs { margin-bottom: 18px; }
/* Four tiles, each a link to the tab that holds the detail. */
.portal-tiles { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.kpi.tile { display: block; text-decoration: none; color: inherit; transition: border-color 0.15s ease, background 0.15s ease; }
.kpi.tile:hover, .kpi.tile:focus-visible { border-color: var(--gold); background: rgba(233, 168, 38, 0.05); text-decoration: none; }
.kpi.tile .value.gold { color: var(--gold); }
/* "Needs your attention": one line per thing, the whole line a link. */
.needs-you { border-color: var(--gold-deep, #b8841c); display: block; }
.needs-you h2 { margin-bottom: 4px; }
.att-row {
  display: flex; align-items: center; gap: 12px; padding: 10px 0;
  border-top: 1px solid var(--border); text-decoration: none; color: inherit;
}
.att-row:hover { text-decoration: none; }
.att-row:hover .att-go { color: var(--gold); text-decoration: underline; }
.att-glyph { color: var(--gold); font-size: 1.1rem; flex: 0 0 24px; text-align: center; }
.att-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.att-body strong { color: var(--ink); overflow-wrap: anywhere; }
.att-go { flex: 0 0 auto; color: var(--gold); font-size: var(--fs-sm); white-space: nowrap; }
.ov-link { text-decoration: none; color: inherit; }
.ov-link:hover { text-decoration: none; }
.ov-link:hover strong { color: var(--gold); }
.ov-link .ov-right { color: var(--gold); }
.portal-cta { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.portal-cta h2 { margin-bottom: 4px; }
.portal-cta .row-actions { margin-left: 0 !important; }
@media (max-width: 700px) {
  .portal-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .att-go { display: none; }
  .portal-cta .row-actions { width: 100%; }
  .portal-cta .row-actions a { flex: 1 1 45%; text-align: center; }
}

/* ---------- Files tab: tick files, share them with the customer ---------- */
td.pick, th.pick { width: 28px; padding-right: 0 !important; }
td.pick input, th.pick input { width: 16px; height: 16px; margin: 0; }
.share-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
  margin: 10px 0 0; padding: 10px 12px; border-radius: var(--r);
  border: 1px solid var(--gold-deep, #b8841c); background: rgba(233, 168, 38, 0.08);
  font-size: var(--fs-md);
}
.share-bar .share-mail { display: flex; align-items: center; gap: 6px; color: var(--ink-2); cursor: pointer; }
.share-bar .share-mail input { width: auto; margin: 0; }
@media (max-width: 700px) {
  .data-table.stack tbody td.pick { position: absolute !important; right: 10px; top: 10px; padding: 0 !important; }
  .data-table.stack tbody tr:has(td.pick) { position: relative; padding-right: 40px; }
}

/* ---------- Customer portal: a deliverable's files ---------- */
/* On the Files tab a deliverable is a count and a size with two buttons,
   never a list; the list lives on its own page, a hundred to a view. */
.dl-cell .dl-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.dl-head { flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 8px; }
.dl-table td.file-name { max-width: 460px; overflow-wrap: anywhere; }
@media (max-width: 700px) {
  .dl-head .btn-gold { width: 100%; margin-left: 0 !important; }
  .dl-cell .dl-actions a, .dl-cell .dl-actions button { flex: 1 1 45%; text-align: center; }
}

/* ---------- Leads: the pipeline board ---------- */
/* What needs someone today comes first, in strips by reason; the four
   stages follow as columns a card can be dragged across. On a phone the
   columns stack, each a short list, and the stage picker on the card does
   what dragging does on a desktop. */
.needs-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 10px; margin-bottom: 16px; }
.needs-col { border: 1px solid var(--border); border-radius: var(--r); padding: 10px 12px; background: var(--surface-2); min-width: 0; }
.needs-col.bad { border-color: rgba(224, 80, 48, 0.55); }
.needs-col.gold { border-color: var(--gold-deep, #b8841c); }
.needs-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.needs-head .pipe-title { color: var(--ink-2); }
.needs-row { display: flex; align-items: center; gap: 8px; padding: 5px 0; border-top: 1px solid var(--border); font-size: var(--fs-md); min-width: 0; }
.needs-row a { color: var(--ink); text-decoration: none; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.needs-row a:hover { color: var(--gold); }
.needs-row .why { margin-left: auto; color: var(--ink-muted); font-size: var(--fs-xs); white-space: nowrap; }
.needs-row .why.bad { color: var(--bad, #e05030); }
.needs-more { color: var(--ink-muted); font-size: var(--fs-xs); padding-top: 4px; }

.pipeline.leads { grid-template-columns: repeat(4, minmax(220px, 1fr)); }
.pipe-col.new .pipe-head { border-bottom-color: var(--gold); }
.pipe-col.contacted .pipe-head { border-bottom-color: #3ba8d4; }
.pipe-col.quoted .pipe-head { border-bottom-color: #b48ce6; }
.pipe-col.won .pipe-head { border-bottom-color: var(--good); }
.pipe-col.drop-ok { outline: 2px dashed var(--gold); outline-offset: 2px; border-radius: var(--r); }
.pipe-sum { font-family: var(--mono); font-size: var(--fs-xs); color: var(--ink-muted); }
.lead-card { cursor: grab; position: relative; }
.lead-card:active { cursor: grabbing; }
.lead-card.dragging { opacity: 0.5; }
.lead-card.attention-overdue { border-color: rgba(224, 80, 48, 0.6); }
.lead-card.attention-today, .lead-card.attention-untouched { border-color: var(--gold-deep, #b8841c); }
.lead-card .pipe-job { font-weight: 600; }
.lead-card .lead-co { color: var(--ink-2); font-size: var(--fs-sm); overflow-wrap: anywhere; }
.lead-card .lead-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.lead-card .lead-chips .badge { font-size: 0.62rem; }
.lead-card .lead-value { font-family: var(--mono); color: var(--ink); }
.lead-owner { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; background: rgba(233, 168, 38, 0.15); color: var(--gold); font-size: 0.65rem; font-weight: 600; flex: 0 0 auto; }
.lead-card .pipe-move select { font-size: var(--fs-xs); min-height: 30px; padding: 3px 6px; }
.lead-figures { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); margin-bottom: 14px; }
.lead-filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 12px; }
.lead-filters .search-input { min-width: 180px; flex: 1 1 200px; }

/* The lead page: the stage stepper and the next-step card. */
.stage-steps { display: flex; gap: 4px; flex-wrap: wrap; margin: 8px 0 14px; }
.stage-step { padding: 5px 12px; border: 1px solid var(--border); border-radius: 999px; font-family: var(--mono); font-size: var(--fs-xs); letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-muted); background: var(--bg); text-decoration: none; cursor: pointer; }
.stage-step.done { color: var(--ink-2); border-color: rgba(67, 176, 107, 0.5); }
.stage-step.now { color: var(--gold-ink, #0b0c0e); background: var(--gold); border-color: var(--gold); font-weight: 600; }
.stage-step.closed { color: var(--bad, #e05030); border-color: rgba(224, 80, 48, 0.5); }
.stage-step:hover { color: var(--ink); border-color: var(--gold); }
.lead-head-meta { display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; color: var(--ink-2); font-size: var(--fs-md); margin: 4px 0 0; }
.lead-head-meta a { color: var(--gold); }
.next-step { border-color: var(--gold-deep, #b8841c); }
.next-step .fld { flex: 1 1 150px; }
.tl { list-style: none; margin: 10px 0 0; padding: 0; }
.tl li { display: grid; grid-template-columns: 92px 1fr; gap: 10px; padding: 8px 0; border-top: 1px solid var(--border); font-size: var(--fs-md); }
.tl .tl-when { color: var(--ink-muted); font-family: var(--mono); font-size: var(--fs-xs); padding-top: 2px; }
.tl .tl-event { color: var(--ink-2); font-size: var(--fs-sm); }
.tl .tl-event .who { color: var(--ink-muted); }
.tl .tl-note { white-space: pre-line; color: var(--ink); }
.lost-box { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; margin-top: 8px; }
@media (max-width: 700px) {
  .pipeline.leads { grid-template-columns: 1fr; overflow: visible; }
  .pipe-col { min-width: 0; }
  .lead-card { cursor: default; }
  .tl li { grid-template-columns: 1fr; gap: 2px; }
}
.range-picker a { background: var(--surface); border: 1px solid var(--border); color: var(--ink-2); border-radius: var(--r); padding: 6px 14px; font-family: var(--mono); font-size: var(--fs-xs); text-decoration: none; letter-spacing: 0.04em; }
.range-picker a:hover { color: var(--ink); border-color: var(--gold-deep); }
.range-picker a.active { color: #0b0c0e; background: var(--gold); border-color: var(--gold); font-weight: 500; }
.stage-steps form { margin: 0; display: inline; }
.stage-steps details summary::-webkit-details-marker { display: none; }
.lost-box .fld { flex: 1 1 120px; }
.lead-head-meta .badge { margin-right: 2px; }
.kpi.needs-you { border-color: var(--gold-deep, #b8841c); }
.needs-row { flex-wrap: wrap; }
.needs-row a { flex: 0 1 auto; max-width: 100%; }
.pipe-more-card.hidden { display: none; }
.pipe-show-more { width: 100%; margin-top: 6px; }

/* ---------- Invoices: collections first ---------- */
.coll-figures { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.coll-top { display: flex; flex-wrap: wrap; gap: 10px 20px; align-items: flex-start; justify-content: space-between; margin-bottom: 8px; }
.coll-top h2 { margin-bottom: 2px; }
.coll-owing { display: flex; flex-direction: column; gap: 2px; min-width: 240px; font-size: var(--fs-sm); }
.coll-owing .label { font-family: var(--mono); font-size: var(--fs-label); text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-muted); margin-bottom: 2px; }
.coll-owing a { color: var(--ink-2); text-decoration: none; }
.coll-owing a strong { color: var(--ink); font-family: var(--mono); }
.coll-owing a:hover { color: var(--gold); }
.coll-group { margin-top: 14px; border: 1px solid var(--border); border-radius: var(--r); padding: 8px 12px 4px; }
.coll-group.bad { border-color: rgba(224, 80, 48, 0.55); }
.coll-group.warn { border-color: var(--gold-deep, #b8841c); }
.coll-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 4px; }
.coll-table thead th { position: static; }
.coll-actions { white-space: nowrap; }
.coll-actions form.inline, .coll-actions details { display: inline-block; vertical-align: middle; margin-right: 4px; }
.coll-pop { position: relative; }
.coll-pop summary { list-style: none; cursor: pointer; display: inline-flex; }
.coll-pop summary::-webkit-details-marker { display: none; }
.coll-pop .coll-form { position: absolute; right: 0; top: 36px; z-index: 6; min-width: 300px; margin: 0; display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; white-space: normal; border-color: var(--gold-deep, #b8841c); }
.coll-form .fld { flex: 1 1 120px; }
.btn-gold-text { color: var(--gold) !important; }
.inv-list td { vertical-align: top; }
@media (max-width: 700px) {
  .coll-actions { white-space: normal; }
  .coll-pop .coll-form { position: static; min-width: 0; margin-top: 6px; }
  .coll-owing { min-width: 0; }
}
tr.coll-more.hidden { display: none; }
.coll-group .pipe-show-more { margin: 4px 0 8px; }
/* Reports: four tabs over one page */
.rep-year a { color: var(--gold); text-decoration: none; }
section.rtab[hidden] { display: none; }

/* ---------- CSV and text previews ---------- */
.csv-note { padding: 10px 14px; margin: 0; border-bottom: 1px solid var(--border); }
.csv-wrap { overflow: auto; max-height: calc(100vh - 230px); min-height: 200px; }
.csv-table { border-collapse: collapse; font-family: var(--mono); font-size: var(--fs-xs); white-space: nowrap; min-width: 100%; }
.csv-table th, .csv-table td { padding: 5px 10px; border-bottom: 1px solid var(--border); border-right: 1px solid var(--border); text-align: left; max-width: 360px; overflow: hidden; text-overflow: ellipsis; }
.csv-table thead th { position: sticky; top: 0; background: var(--surface); color: var(--ink-2); font-weight: 600; z-index: 1; }
.csv-table td { color: var(--ink); }
.csv-table .csv-n { color: var(--ink-muted); text-align: right; position: sticky; left: 0; background: var(--surface); }
.csv-table tbody tr:hover td { background: rgba(255, 255, 255, 0.03); }
.csv-text { margin: 0; padding: 14px; font-family: var(--mono); font-size: var(--fs-xs); white-space: pre; overflow: auto; max-height: calc(100vh - 230px); color: var(--ink); }

/* The job page's Files section: each customer folder is its own block. */
.cust-folder { border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; }
.cust-folder .data-table { margin-bottom: 0; }

/* "More" on the Files page: the rarely used actions behind one button. */
.fb-more { position: relative; display: inline-block; }
.fb-more > summary { list-style: none; cursor: pointer; }
.fb-more > summary::-webkit-details-marker { display: none; }
.fb-more-menu { position: absolute; right: 0; top: calc(100% + 4px); z-index: 20; min-width: 240px; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 6px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35); display: flex; flex-direction: column; gap: 2px; }
.fb-more-menu > a, .fb-more-menu > button, .fb-more-menu > form > button { display: block; width: 100%; text-align: left; background: none; border: none; color: var(--ink); font: inherit; font-size: var(--fs-sm); padding: 7px 10px; border-radius: 6px; cursor: pointer; text-decoration: none; }
.fb-more-menu > a:hover, .fb-more-menu > button:hover, .fb-more-menu > form > button:hover { background: rgba(255, 255, 255, 0.06); }
.fb-more-danger { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 6px; }

/* State names and cities drawn over the pilot map (static/js/us-overlay.js). */
.us-state-label { pointer-events: none; }
.us-state-label span { display: block; text-align: center; font: 600 12px/16px var(--sans); letter-spacing: 0.08em; color: #fff; opacity: 0.85;
  text-shadow: 0 0 3px #000, 0 0 6px #000, 0 1px 2px #000; }
.us-city { pointer-events: none; white-space: nowrap; }
.us-city i { position: absolute; left: -3px; top: -3px; width: 6px; height: 6px; border-radius: 50%; background: #fff; box-shadow: 0 0 0 1.5px #000; }
.us-city span { position: absolute; left: 6px; top: -9px; font: 500 11px/18px var(--sans); color: #fff; text-shadow: 0 0 3px #000, 0 0 5px #000, 0 1px 2px #000; }
.us-city-1 i { width: 8px; height: 8px; left: -4px; top: -4px; }
.us-city-1 span { font-weight: 600; font-size: 12px; left: 7px; }
.us-city-3 span { font-size: 10px; opacity: 0.9; }
.us-city-3 i { width: 5px; height: 5px; }

/* Stage billing: the per-project line on the Work tab and the Billing tab. */
.bill-line { display: flex; flex-wrap: wrap; gap: 10px 18px; align-items: center; margin: 2px 0 12px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; }
.bill-line .label { display: block; font-size: var(--fs-xs); color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.06em; }
.bill-line strong { font-size: var(--fs-md); }
.bill-line .bill-stage { margin-left: auto; }
.bill-stage > summary::-webkit-details-marker { display: none; }
