/* The design's tokens, verbatim. */
:root {
  --bg: #F4F2EC; --ink: #1B1A17; --mid: #3C3A35; --muted: #5C5A54;
  --line: #D9D5CB; --chip: #E6E2D6; --dash: #B8B3A6; --green: #1E7A3C; --red: #A32D2D;
  --accent: #1A4FD6; --card: #FFFFFF;
  --display: 'Archivo', system-ui, -apple-system, sans-serif;
  --body: 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
/* The page itself never scrolls or bounces on the phone. Each screen is a box the
   height of the viewport and scrolls inside itself only when it is taller than the phone. */
html, body { height: 100%; overflow: hidden; overscroll-behavior: none; }
html { background: var(--bg); color: var(--ink); -webkit-text-size-adjust: 100%; }
body { margin: 0; position: fixed; inset: 0; font: 14px/1.4 var(--body); background: var(--bg); }
a { color: inherit; text-decoration: none; }
button, input, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
h1 { margin: 0; font-family: var(--display); font-weight: 700; font-size: 32px; line-height: 1.1; }

.screen {
  max-width: 480px; margin: 0 auto; height: 100dvh;
  overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 20px;
  padding: max(56px, calc(env(safe-area-inset-top) + 20px)) 20px calc(24px + env(safe-area-inset-bottom));
}
/* A plumber's screens scroll as a phone does: no bar down the side taking room. */
html:not(.office) .screen { scrollbar-width: none; -webkit-overflow-scrolling: touch; }
html:not(.office) .screen::-webkit-scrollbar { display: none; }
/* A plumber's job screen fits the phone and does not scroll: long notes scroll inside their own card. */
.screen.fit { overflow: hidden; }
.screen.fit > * { flex: none; }
.screen.fit > .notes { flex: 0 1 auto; min-height: 64px; }
.screen.fit > .notes .text { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.screen.today { padding-top: max(60px, calc(env(safe-area-inset-top) + 24px)); }
.cols { display: flex; gap: 24px; align-items: flex-start; flex-wrap: wrap; }
.cols > .col { flex: 1 1 360px; min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.cols > .col.side { flex: 0 1 380px; }
.seg .in { flex: 1; min-width: 0; width: auto; }
select.in { appearance: auto; -webkit-appearance: menulist; }
/* The contact picker: a search box over GHL's contacts, the list under it, a chip once someone is picked. */
.picker { display: flex; flex-direction: column; gap: 8px; }
.plist { display: flex; flex-direction: column; max-height: 344px; overflow-y: auto; background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 4px 0 6px; }
.phead { padding: 10px 16px 4px; font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.prow { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%; padding: 8px 16px; border: 0; background: none; text-align: left; }
.prow:hover, .prow:focus-visible { background: var(--bg); outline: none; }
.pname { display: flex; align-items: center; gap: 8px; font-size: 16px; font-weight: 600; }
.psub { font-size: 13px; color: var(--muted); }
.ctag { padding: 1px 6px; border: 1px solid var(--line); border-radius: 5px; font-size: 10px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.ctag.blue { border-color: var(--accent); color: var(--accent); }
.ctag.gold { border-color: #C9A24A; color: #8A5A00; }
.pchip { display: flex; align-items: center; gap: 12px; padding: 10px 10px 10px 16px; background: var(--card); border: 1px solid var(--ink); border-radius: 10px; }
.pchip .pmain { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.pchip .btn { flex: 0 0 auto; width: auto; }

/* Header bits */
.eyebrow { font-size: 14px; font-weight: 500; color: var(--muted); letter-spacing: 0.02em; }
.titlerow { display: flex; align-items: baseline; justify-content: space-between; }
.titlerow h1 { font-size: 40px; line-height: 1; }
.count { font-size: 15px; font-weight: 500; color: var(--muted); }
/* Over the plumber's list: the day on the left; a day back, a day on, and Today once off it, on the right. */
.dayrow { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.days { display: flex; gap: 8px; }
.days .btn { width: auto; min-width: 44px; padding: 0 12px; }
.back { display: flex; align-items: center; gap: 6px; min-height: 44px; font-size: 15px; font-weight: 500; color: var(--mid); background: none; border: 0; padding: 0; text-align: left; }
.back svg { width: 18px; height: 18px; }
.head { display: flex; flex-direction: column; gap: 6px; }
.sub { font-size: 14px; color: var(--muted); }
.badgerow { display: flex; align-items: center; gap: 10px; }

/* Badges */
.badge { font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: 999px; background: var(--chip); color: var(--mid); white-space: nowrap; }
.badge.next, .badge.working { background: var(--accent); color: #fff; }
.badge.working { background: var(--green); }
/* A job that is done: its badge says Job complete, in green with a check, at the far right of the row. */
.badge.complete { display: flex; align-items: center; gap: 6px; order: 1; margin-left: auto; background: var(--green); color: #fff; }
.badge.complete svg { flex: none; width: 13px; height: 13px; }

/* Job list */
.list { display: flex; flex-direction: column; gap: 12px; }
.job { display: flex; flex-direction: column; gap: 8px; background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 16px; }
.job.next, .job.working { border: 2px solid var(--accent); padding: 15px; }
.job.working { border-color: var(--green); }
.job.estimate { opacity: 0.55; }
/* Done: the card's words dim, its Job complete badge does not. */
.job.done > :not(.row), .job.done .time { opacity: 0.55; }
.job .row { display: flex; justify-content: space-between; align-items: center; }
.job .time { font-family: var(--display); font-weight: 600; font-size: 17px; }
.job .name { font-size: 16px; font-weight: 600; }
.job .customer { font-size: 14px; color: var(--mid); }
.job .addr { font-size: 13px; color: var(--muted); }
.empty { padding: 32px 16px; text-align: center; color: var(--muted); border: 1px dashed var(--dash); border-radius: 10px; }
.foot { margin-top: auto; font-size: 13px; color: var(--muted); text-align: center; }

/* Cards */
.card { display: flex; flex-direction: column; gap: 10px; background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 16px; }
.card.rows { gap: 0; padding: 4px 16px; }
.label { font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.big { font-size: 18px; font-weight: 600; line-height: 1.3; }
.text { font-size: 15px; line-height: 1.5; color: var(--ink); white-space: pre-wrap; }
.text.dim { font-size: 14px; color: var(--mid); }
.hint { font-size: 13px; color: var(--muted); line-height: 1.4; }
.hint.err { color: var(--red); }
.dashed { display: flex; flex-direction: column; gap: 8px; padding: 12px 16px; border: 1px dashed var(--dash); border-radius: 10px; }
/* What the company sent the plumber for the job's materials, over the cost on their close out: the receipt is asked for right under it. */
.sentbox { display: flex; flex-direction: column; gap: 8px; padding: 14px 16px; background: var(--card); border: 1px solid var(--line); border-left: 4px solid var(--accent); border-radius: 10px; }
.sentbox .t { font-size: 16px; font-weight: 600; }
.sentbox .got { display: flex; align-items: center; gap: 8px; font-weight: 600; color: var(--green); }
.sentbox .got svg { flex: none; width: 20px; height: 20px; }
#matnote { display: flex; flex-direction: column; gap: 8px; }
#matnote:empty { display: none; }
.row { display: flex; justify-content: space-between; align-items: center; }
.card.rows .row { min-height: 48px; border-bottom: 1px solid var(--chip); font-size: 15px; color: var(--mid); }
.card.rows .row:last-child { border-bottom: 0; }
.row .when { font-size: 14px; font-weight: 500; color: var(--muted); white-space: nowrap; margin-left: 12px; }
.row .ok { display: flex; align-items: center; gap: 8px; font-weight: 600; color: var(--green); }
.row .ok svg { width: 20px; height: 20px; }
.row .wait { color: var(--muted); }
.row .bad { font-weight: 600; color: var(--red); }
.total { display: flex; justify-content: space-between; align-items: baseline; border-top: 1px solid var(--chip); padding-top: 12px; }
.total .amt { font-family: var(--display); font-weight: 700; font-size: 24px; color: var(--ink); }
/* How a total adds up, over the total itself: the price, the sales tax, the processing fee. */
.adds { display: flex; flex-direction: column; gap: 8px; border-top: 1px solid var(--chip); padding-top: 12px; font-size: 15px; color: var(--mid); }
.adds .row .money { font-weight: 500; }
/* The second total, by cash or check: under the card total, smaller, with no rule of its own. */
.total.cash { border-top: 0; padding-top: 0; margin-top: -4px; }
.total.cash .amt { font-size: 18px; }
/* The line under a price as it is typed (what the customer will pay) takes no room until there is something to say. */
#pays:empty { display: none; }
/* A figure beside a line that wraps (how the total adds up) keeps its distance from it and stays on one line. */
.card.rows .row { gap: 12px; }
.row .money { white-space: nowrap; }
.row .money { font-size: 15px; font-weight: 600; color: var(--ink); }
.row .money.big { font-family: var(--display); font-weight: 700; font-size: 20px; }

/* Buttons */
.btn { display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 48px; border: 2px solid var(--ink); border-radius: 8px; background: transparent; font-size: 15px; font-weight: 600; padding: 0 16px; width: 100%; }
.btn svg { width: 18px; height: 18px; }
.btn.chip { min-height: 44px; border: 0; background: var(--chip); }
.btn.primary { margin-top: auto; min-height: 56px; border: 0; border-radius: 10px; background: var(--accent); color: #fff; font-family: var(--display); font-size: 18px; }
.btn.primary.now { margin-top: 0; }
.btn:disabled { opacity: 0.4; cursor: default; }
.btn.busy { opacity: 0.7; pointer-events: none; }

/* Card / Cash / Check */
.seg { display: flex; gap: 8px; }
.seg .btn { flex: 1; min-height: 44px; padding: 0 8px; border: 1px solid var(--line); background: var(--card); font-size: 15px; white-space: nowrap; }
.seg .btn.on { background: var(--ink); border-color: var(--ink); color: #fff; }

/* Four to pick from (the license level): two rows of two. */
.seg.two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* Who gets the texts, who pays: a person's name on each button, cut short when it is long, and on a landlord job which of the two they are. */
.seg .btn .ellipsis { min-width: 0; }
.seg .btn .role { font-size: 10px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.65; }
/* Two boxes side by side, the second with twice the room (the license's state and the day it expires). */
.pair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: 8px; }
.pair .in { min-width: 0; }
/* The proof of insurance on the plumber's details: a tile to add it, then what is on file. */
.insdoc { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 72px; padding: 10px 14px; border: 1px dashed var(--dash); border-radius: 10px; background: var(--card); font-size: 15px; font-weight: 600; text-align: left; }
.insdoc.has { border: 1px solid var(--line); }
.insdoc img { flex: none; width: 52px; height: 52px; object-fit: cover; border-radius: 8px; border: 1px solid var(--line); }
.insdoc svg { flex: none; width: 22px; height: 22px; }
.insdoc.busy { opacity: 0.7; pointer-events: none; }

/* Fields */
.field { display: flex; flex-direction: column; gap: 8px; }
.field > .field { margin-top: 6px; }
textarea { width: 100%; padding: 14px; border: 1px solid var(--line); border-radius: 10px; background: var(--card); font-size: 16px; line-height: 1.5; resize: none; outline: none; }
textarea:focus, .money-in:focus-within { border-color: var(--ink); }
.money-in { display: flex; align-items: center; gap: 10px; background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 0 16px; min-height: 60px; }
.money-in .sym { font-family: var(--display); font-weight: 600; font-size: 26px; color: var(--muted); }
.money-in input { flex: 1; min-width: 0; border: 0; outline: none; background: transparent; font-family: var(--display); font-weight: 600; font-size: 28px; }

/* Photos */
.photos { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; align-items: start; }
/* One column per kind, under its little label: its shots, then the tile that adds another. */
.kind { display: flex; flex-direction: column; gap: 6px; }
.kind-name { font-size: 13px; font-weight: 600; color: var(--mid); }
.shots { display: flex; flex-direction: column; gap: 10px; }
.shot { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; aspect-ratio: 1; border: 1px dashed var(--dash); border-radius: 10px; background: var(--card); font-size: 11px; font-weight: 600; overflow: hidden; padding: 0; }
.shot svg { width: 22px; height: 22px; }
.shot.has { border: 1px solid var(--line); background: var(--chip); }
/* A shot taken: the photo whole, a green tick in its corner; "Removing…" rides on a pill over it. */
.shot.has svg { position: absolute; top: 6px; right: 6px; width: 20px; height: 20px; padding: 4px; border-radius: 50%; background: var(--green); color: #fff; }
.shot.has span { padding: 2px 6px; border-radius: 999px; background: rgba(255,255,255,.9); }
.shot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.shot span, .shot svg { position: relative; }
.shot span:empty { display: none; }
.shot.busy { opacity: 0.7; pointer-events: none; }

/* Sign in */
.names { display: flex; flex-direction: column; gap: 12px; }
.names > .btn:not(.primary) { min-height: 56px; font-size: 17px; background: var(--card); border: 1px solid var(--line); }
.in { width: 100%; min-height: 56px; padding: 0 16px; border: 1px solid var(--line); border-radius: 10px; background: var(--card); font-size: 18px; outline: none; }
.in:focus { border-color: var(--ink); }

#toast { position: fixed; left: 16px; right: 16px; bottom: calc(24px + env(safe-area-inset-bottom)); max-width: 448px; margin: 0 auto; padding: 12px 16px; border-radius: 10px; background: var(--ink); color: #fff; font-size: 14px; line-height: 1.4; box-shadow: 0 6px 20px rgba(0,0,0,.2); z-index: 10; }
#toast.err { background: var(--red); }

.veil { position: fixed; inset: 0; z-index: 20; display: flex; align-items: flex-end; justify-content: center; padding: 16px; padding-bottom: calc(16px + env(safe-area-inset-bottom)); background: rgba(27,26,23,.5); }
.ask { width: 100%; max-width: 448px; display: flex; flex-direction: column; gap: 12px; padding: 20px; border-radius: 14px; background: var(--card); box-shadow: 0 12px 32px rgba(0,0,0,.25); }
.ask .btn.primary { margin-top: 8px; }
/* Delete's sheet: what the job has, a row each: green goes, red stays in GHL, gold when GHL could not be asked. */
.fates { display: flex; flex-direction: column; gap: 6px; }
.fate { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 9px 12px; border: 1px solid var(--line); border-left: 3px solid var(--line); border-radius: 8px; }
.fate .what { min-width: 0; }
.fate .t { font-size: 14px; font-weight: 600; }
.fate .s { margin-top: 2px; font-size: 12px; line-height: 1.4; color: var(--muted); }
.fate .tag { flex: none; font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.fate.goes { border-left-color: var(--green); }
.fate.goes .t, .fate.goes .tag { color: var(--green); }
.fate.stays { border-left-color: var(--red); }
.fate.stays .t, .fate.stays .tag { color: var(--red); }
.fate.unsure { border-left-color: var(--gold, #8A5A00); }
.fate.unsure .t, .fate.unsure .tag { color: var(--gold, #8A5A00); }

/* A price changed after the customer signed: said in red on the Job screen. */
.sub.warn { color: var(--red); font-weight: 500; }
/* "Change" beside the authorized amount on Close out. */
.row a.change { margin-left: 8px; font-size: 13px; font-weight: 600; color: var(--accent); text-decoration: underline; }
/* A negative balance: the plumber owes the company. */
.money.neg, .amt.neg { color: var(--red); }
/* The receipt shot on a payout line, when the plumber paid for the materials. */
.receipt { display: inline-flex; align-items: center; gap: 8px; margin-top: 8px; font-size: 13px; font-weight: 600; color: var(--accent); }
.receipt img { width: 64px; height: 64px; object-fit: cover; border-radius: 8px; border: 1px solid var(--line); }

/* ── The job in slides (#/job/<id>) ── */
/* Where the job is, pinned to the top while the slide scrolls; a tap turns to that slide. Sticky counts from inside
   the screen's top padding, so the offset takes that padding back to sit flush with the top edge (under the notch
   when the phone draws the page under its status bar, hence the padding of the bar's own). */
.steps { position: sticky; top: calc(-1 * max(56px, calc(env(safe-area-inset-top) + 20px))); z-index: 5; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; margin: -6px -20px; padding: max(6px, env(safe-area-inset-top)) 20px 6px; background: var(--bg); box-shadow: 0 1px 0 var(--line); }
.steps button { display: flex; flex-direction: column; justify-content: center; gap: 6px; min-height: 44px; padding: 0; border: 0; background: none; font-size: 12px; font-weight: 600; color: var(--muted); text-align: left; }
.steps i { display: block; height: 4px; border-radius: 2px; background: var(--line); }
.steps .done { color: var(--green); }
.steps .done i { background: var(--green); }
.steps .now { color: var(--accent); }
.steps .now i { background: var(--accent); }
/* The slide shown: its name in ink, its bar thicker. The colours still say where the job is. */
.steps .on { color: var(--ink); }
.steps .on i { height: 6px; margin-top: -2px; border-radius: 3px; }
.steps button:first-child.on i { background: var(--ink); }
/* One slide shown at a time; the deck fills the screen so a swipe under a short slide still turns it. */
.slides { flex: 1 0 auto; display: flex; flex-direction: column; }
.slide { display: flex; flex-direction: column; gap: 20px; }
/* The slide before and the slide after, pinned to the bottom of the screen while the slide scrolls under them.
   Sticky counts from inside the screen's bottom padding, so the offset takes that padding back, as the bar at the top does. */
.pager { position: sticky; bottom: calc(-24px - env(safe-area-inset-bottom)); z-index: 5; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: auto -20px calc(-24px - env(safe-area-inset-bottom)); padding: 10px 20px calc(12px + env(safe-area-inset-bottom)); background: var(--bg); box-shadow: 0 -1px 0 var(--line); }
.slide { padding-bottom: 20px; }
.stage { gap: 12px; }
.stage-head { display: flex; align-items: center; gap: 10px; }
.stage-head .num { flex: none; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; background: var(--chip); color: var(--mid); font: 700 14px var(--display); }
.stage-head .num svg { width: 16px; height: 16px; }
.stage.now .num { background: var(--accent); color: #fff; }
.stage.done .num { background: var(--green); color: #fff; }
.stage-head h2 { flex: 1; margin: 0; font: 700 20px/1.2 var(--display); }
.stage-head .tag { font-size: 13px; font-weight: 600; color: var(--muted); white-space: nowrap; }
.stage.done .tag { color: var(--green); }
.stage.now .tag { color: var(--accent); }
.stage .stage-head .tag.err { max-width: 62%; color: var(--red); font-weight: 500; white-space: normal; text-align: right; }
.shot .dim { font-size: 13px; color: var(--muted); font-weight: 500; }
/* Can't do job: the way out of a job that is not ours to do, top right over the job's name, across from the way back.
   Quiet, so it is not taken for the next thing to do. */
.toprow { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.toprow .btn { flex: none; width: auto; min-height: 40px; padding: 0 14px; border-radius: 999px; font-size: 13px; }
/* The sheet that asks why sits at the top of the screen, clear of the phone's keyboard. */
.veil.top { align-items: flex-start; padding-top: max(56px, calc(env(safe-area-inset-top) + 20px)); }
/* Closed that way: dim on the day's list, like an estimate left behind; on its own screen every step reads done,
   and none of them opens anything. */
.job.cantdo { opacity: 0.55; }
.steps.closed > div { display: flex; flex-direction: column; justify-content: center; gap: 6px; min-height: 44px; font-size: 12px; font-weight: 600; }
/* The job's screen fits the phone (2026-10-05): the name, the bar and the two buttons at the foot stay put, and the
   slide between them takes what is left. What is typed into (the scope, the report) stretches or gives to fit, a long
   text scrolls inside its own card, and everything sits a little closer. Only a slide with more on it than the
   phone has room for scrolls, inside itself. A part not open yet is dim in the bar. */
.screen.all { overflow: hidden; gap: 10px; padding-top: max(12px, calc(env(safe-area-inset-top) + 6px)); padding-bottom: 0; }
.screen.all > * { flex: none; }
.screen.all h1 { font-size: 24px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.screen.all .head { gap: 4px; }
.screen.all .steps { position: static; margin: 0 -20px; padding: 0 20px 2px; }
.screen.all .steps button { min-height: 36px; }
.screen.all .steps button:disabled { opacity: 0.4; }
.screen.all > .slides { flex: 1 1 0; min-height: 0; }
.screen.all .slide { flex: 1 1 0; min-height: 0; gap: 10px; padding-bottom: 8px; overflow-y: auto; scrollbar-width: none; }
.screen.all .slide::-webkit-scrollbar { display: none; }
.screen.all .slide > * { flex: none; }
.screen.all .pager { position: static; margin: 0 -20px; padding: 8px 20px calc(10px + env(safe-area-inset-bottom)); }
.screen.all .btn { min-height: 44px; }
.screen.all .field { gap: 6px; }
.screen.all .card { padding: 12px 14px; gap: 8px; }
.screen.all .card.rows { padding: 2px 14px; }
.screen.all .card.rows .row { min-height: 36px; font-size: 14px; }
.screen.all .money-in { min-height: 48px; }
.screen.all .money-in input { font-size: 24px; }
.screen.all .hint { font-size: 12px; line-height: 1.35; }
.screen.all .slide > .field.grow { flex: 1 1 64px; min-height: 64px; }
.screen.all .field.grow > textarea, .screen.all .field.grow > .card { flex: 1 1 0; min-height: 0; overflow-y: auto; }
.screen.all .slide > .card.grow { flex: 0 1 auto; min-height: 64px; overflow: hidden; }
.screen.all .card.grow > * { flex: none; }
.screen.all .card.grow > .text { flex: 0 1 auto; min-height: 20px; overflow-y: auto; overscroll-behavior: contain; }
.screen.all .shots { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.screen.all .shot.has svg { top: 3px; right: 3px; width: 16px; height: 16px; padding: 3px; }
.screen.all .sentbox { padding: 10px 14px; gap: 6px; }

/* ── The office, at a desk: the old Job Tracker's look. Dark, mono
   labels, amber for what to press, under a bar across the top. All of it hangs off html.office, set while
   the office is signed in; the plumbers' screens keep the light design above. ── */
html.office {
  --bg: #101216; --panel: #14161A; --card: #1B1E24; --hover: #20242B; --raised: #23272E;
  --line: #2A2F37; --line1: #23272E; --line3: #3A4150; --chip: #23272E; --dash: #3A4150;
  --ink: #E8E6E1; --mid: #C7CBD2; --muted: #9AA1AC; --dim: #7C838F; --faint: #5C636E;
  --amber: #B45309; --amber2: #D97706; --on-amber: #14161A; --accent: #D97706;
  --green: #34D399; --red: #EF4444; --blue: #7EA8F8; --gold: #E9A23B;
  --mono: 'Azeret Mono', ui-monospace, Menlo, monospace;
  --display: 'Public Sans', system-ui, -apple-system, sans-serif; --body: 'Public Sans', system-ui, -apple-system, sans-serif;
  color-scheme: dark;
}
html.office body { display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); font-size: 13px; -webkit-font-smoothing: antialiased; }
html.office ::placeholder { color: var(--faint); }
html.office ::-webkit-scrollbar { width: 10px; height: 10px; }
html.office ::-webkit-scrollbar-thumb { background: var(--line); border-radius: 6px; }
html.office .screen.office { max-width: none; margin: 0; height: 100%; padding: 22px 26px 40px; gap: 18px; }

/* The bar across the top: the shop, the ways around, who is signed in */
.oside { display: flex; align-items: center; gap: 20px; height: 56px; padding: 0 16px; background: var(--panel); border-bottom: 1px solid var(--line1); }
.oside .brandrow { display: flex; align-items: center; gap: 9px; }
.brand-mark { flex: none; display: grid; place-items: center; width: 24px; height: 24px; border-radius: 5px; background: var(--amber); color: var(--on-amber); font: 600 12px var(--mono); }
.brand-name { font: 10px var(--mono); letter-spacing: .16em; text-transform: uppercase; color: var(--muted); }
.oside nav { display: flex; gap: 2px; margin-right: auto; }
.nav-item { padding: 8px 12px; border-radius: 7px; font-size: 13.5px; color: var(--muted); white-space: nowrap; }
.nav-item:hover { background: var(--hover); }
.nav-item.on { background: var(--raised); color: var(--ink); font-weight: 600; }
.oside .me { display: flex; align-items: center; gap: 10px; }
.oside .avatar { flex: none; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; background: var(--raised); background: color-mix(in srgb, var(--blue) 26%, var(--panel)); color: var(--ink); font-size: 11px; font-weight: 600; }
.oside .me .name { font-size: 13.5px; font-weight: 600; white-space: nowrap; }
.out { padding: 6px 10px; border: 1px solid var(--line); border-radius: 7px; background: transparent; color: var(--muted); font: 500 12px var(--body); white-space: nowrap; }
.out:hover { color: var(--ink); border-color: var(--amber); }
/* The clock, on the bar: who is on shift (an admin's), or the dispatcher's own Clock in / Clock out; in one pill with what it says */
.clockslot { display: flex; align-items: center; gap: 10px; min-width: 0; }
.clockslot:empty { display: none; }
.oside .clockslot:has(> .onshift) { height: 34px; padding: 0 4px 0 12px; border: 1px solid var(--line); border-radius: 17px; }
.oside .clockslot > .onshift:last-child { padding-right: 8px; }
html.office .oside .clockslot .btn { padding: 4px 11px; border-radius: 13px; font-size: 12px; }
.onshift { display: inline-flex; align-items: center; gap: 7px; font: 11px var(--mono); color: var(--muted); white-space: nowrap; overflow: hidden; }
.onshift i { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--green); }
.onshift.off { color: var(--dim); }
.onshift.off i { background: var(--faint); }
[data-onshift]:empty { display: none; }
.ctclock { display: inline-flex; align-items: baseline; gap: 5px; font: 12px var(--mono); color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ctclock small { font: inherit; }
.ctclock:empty { display: none; }
/* "Still working?": the time left before the clock-out; and the two ticks before a clock-in */
.countdown { font: 600 34px/1 var(--mono, ui-monospace, Menlo, monospace); letter-spacing: .02em; text-align: center; padding: 4px 0 2px; color: var(--amber2, #D97706); }
.countdown.low { color: var(--red); }
.checkrow { display: flex; align-items: flex-start; gap: 10px; padding: 11px 12px; border: 1px solid var(--line); border-radius: 8px; font-size: 14px; line-height: 1.35; cursor: pointer; }
.checkrow input { flex: none; width: 18px; height: 18px; margin: 0; accent-color: var(--amber2, #D97706); }

/* Type and the pieces every office screen shares, re-dressed */
html.office h1 { font-size: 27px; font-weight: 700; letter-spacing: -.02em; line-height: 1.15; text-wrap: pretty; }
html.office .eyebrow, html.office .label { font-family: var(--mono); font-size: 10px; font-weight: 400; letter-spacing: .14em; text-transform: uppercase; color: var(--dim); }
html.office .sub { font-size: 13px; color: var(--muted); }
html.office .sub.warn { color: var(--gold); }
html.office .hint { font-size: 11.5px; color: var(--dim); }
html.office .hint.err { color: var(--red); }
html.office .big { font-size: 15px; font-weight: 700; }
html.office .count, .note { font: 11px var(--mono); color: var(--dim); }
html.office .back { min-height: 0; font: 11px var(--mono); color: var(--dim); }
html.office .back:hover { color: var(--amber2); }
html.office .back svg { width: 13px; height: 13px; }
html.office .card { border-color: var(--line); }
html.office .card.rows .row { min-height: 42px; border-bottom-color: var(--line1); font-size: 13px; color: var(--muted); }
html.office .empty { padding: 36px 18px; border: 0; font-size: 13px; color: var(--dim); }
html.office .foot { font: 11px var(--mono); color: var(--dim); text-align: left; }
html.office .btn { width: auto; min-height: 0; padding: 9px 15px; border: 1px solid var(--line); border-radius: 8px; font-size: 13px; font-weight: 500; white-space: nowrap; }
html.office .btn:hover { border-color: var(--amber); }
html.office .btn.primary { margin-top: 0; min-height: 0; background: var(--amber); border-color: var(--amber); color: var(--on-amber); font: 700 13px var(--body); border-radius: 8px; }
html.office .btn.primary:hover { background: var(--amber2); border-color: var(--amber2); }
html.office .btn.chip { background: var(--raised); border-color: var(--raised); font-size: 12.5px; font-weight: 600; }
html.office .btn.chip:hover { background: var(--line); border-color: var(--line); }
html.office .btn.sm { padding: 7px 13px; border-radius: 7px; font-size: 12px; }
html.office .field > .btn, html.office .picker > .btn { align-self: flex-start; }
html.office .seg .btn { min-height: 0; padding: 9px 12px; background: var(--panel); border: 1px solid var(--line); font-size: 13px; }
html.office .seg .btn.on { background: var(--amber); border-color: var(--amber); color: var(--on-amber); font-weight: 700; }
html.office .in, html.office textarea { min-height: 0; padding: 11px 12px; background: var(--panel); border: 1px solid var(--line); border-radius: 7px; font-size: 13.5px; line-height: 1.5; }
html.office .in:focus, html.office textarea:focus { border-color: var(--line3); outline: 1px solid var(--amber); }
html.office input::-webkit-calendar-picker-indicator { filter: invert(.6); cursor: pointer; }
html.office .money-in { min-height: 48px; background: var(--panel); border-color: var(--line); border-radius: 7px; }
html.office .money-in .sym, html.office .money-in input { font: 500 20px var(--mono); }
html.office .money-in:focus-within { border-color: var(--line3); outline: 1px solid var(--amber); }
html.office .row .money, html.office .total .amt { font-family: var(--mono); font-weight: 500; }
html.office #toast { left: auto; right: 20px; bottom: 20px; max-width: 360px; margin: 0; border: 1px solid #2F5D4A; background: var(--raised); color: var(--green); font: 11.5px var(--mono); box-shadow: 0 8px 30px rgba(0, 0, 0, .4); }
html.office #toast.err { border-color: #5A2020; background: var(--raised); color: var(--red); }
html.office .veil { align-items: center; background: rgba(0, 0, 0, .6); }
html.office .ask { border: 1px solid var(--line); }
html.office .badge { padding: 3px 8px; border-radius: 5px; background: var(--raised); color: var(--muted); font: 10.5px var(--mono); }
html.office .badge.working { background: #10301F; color: var(--green); }
html.office .job { border-color: var(--line); }
html.office .job:hover { border-color: var(--amber); }
html.office .job .name { font-size: 14px; }
html.office .job .customer { font-size: 12.5px; color: var(--muted); }
html.office .job .addr { font: 11px var(--mono); color: var(--dim); }
/* Each part of a form is a card. */
html.office .cols > .col > .field { padding: 16px 18px; background: var(--card); border: 1px solid var(--line); border-radius: 10px; }
html.office .field .card { background: var(--panel); }
/* Who is calling and the people taken from the call share one card. */
html.office .field.group { gap: 18px; }
html.office .field.group > .field { margin-top: 0; }
html.office .field.group:not(:has(> :not([hidden]))) { display: none; }
.callsteps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.callsteps span { display: flex; flex-direction: column; gap: 6px; font-size: 12px; font-weight: 600; color: var(--muted); }
.callsteps i { display: block; height: 4px; border-radius: 2px; background: var(--line); }
.callsteps .done { color: var(--green); }
.callsteps .done i { background: var(--green); }
.callsteps .now { color: var(--amber); }
.callsteps .now i { background: var(--amber); }
.callsteps .warn { color: var(--gold); }
.callsteps .warn i { background: var(--gold); }
#calllink { align-self: flex-start; text-align: center; text-decoration: none; }
/* A small Y and N after a question the landlord answers. */
.callsay .yn { display: inline-flex; gap: 4px; margin-left: 10px; vertical-align: middle; }
html.office .callsay .yn .btn { height: 24px; min-height: 0; min-width: 28px; padding: 0 8px; font-size: 12px; font-weight: 600; }
/* The answer picked is filled in: Y green, N red; the other one fades. */
html.office .callsay .yn .btn.on[data-go="yes"], html.office .callsay .yn .btn.on[data-paysok="yes"] { background: var(--green); border-color: var(--green); color: #0B1A13; }
html.office .callsay .yn .btn.on[data-go="no"], html.office .callsay .yn .btn.on[data-paysok="no"] { background: var(--red); border-color: var(--red); color: #fff; }
html.office .callsay .yn:has(.on) .btn:not(.on) { opacity: .45; }
/* Not answered yet: the two pulse in amber until one is picked. */
html.office .callsay .yn:not(:has(.on)) .btn { border-color: var(--amber); color: var(--amber); animation: flash 1.1s ease-in-out infinite; }
.callsay .hint { margin-top: 6px; font-size: 13px; }
html.office .callsay #toresi { display: flex; height: 30px; min-height: 0; margin-top: 8px; padding: 0 12px; font-size: 13px; }
html.office .callsay #calllink { display: inline-flex; height: 30px; min-height: 0; padding: 0 12px; font-size: 13px; }
.callsay { display: flex; flex-direction: column; gap: 10px; margin: 0; padding-left: 20px; font-size: 14px; color: var(--ink); }
.callsay li::marker { color: var(--muted); font: 600 12px var(--mono); }
.callsay .emailrow { display: flex; gap: 8px; }
.callsay li.got { color: var(--green); }
.callsay li.got::marker { color: var(--green); }
.callsay li.got svg { display: inline-block; width: 15px; height: 15px; margin-right: 6px; vertical-align: -2px; }
.callsay .emailrow .in { flex: 0 1 320px; min-width: 0; }
/* The size of the lines beside it: a box and a button no taller than a line of text. */
html.office .callsay .emailrow .in { height: 30px; min-height: 0; padding: 0 10px; font-size: 14px; }
html.office .callsay .emailrow .btn { height: 30px; min-height: 0; padding: 0 12px; font-size: 13px; }
html.office .cols > .col.side > .btn { align-self: stretch; }
/* A job's details are locked until Edit: what is saved lies flat on the card, and the card being edited is edged in amber. */
.cardhead { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 30px; }
.acts { display: flex; gap: 8px; }
html.office .cols > .col > .field.editing { border-color: var(--amber); }
html.office .in[readonly], html.office textarea[readonly] { background: transparent; border-color: var(--line1); color: var(--mid); cursor: default; }
html.office .in[readonly]:focus, html.office textarea[readonly]:focus { border-color: var(--line1); outline: 0; }
html.office .seg .btn:disabled { cursor: default; }
html.office .seg .btn.on:disabled { opacity: 1; }
html.office .seg .btn:disabled:not(.on):hover { border-color: var(--line); }
/* The scope of work over the pricing rows. */
html.office .card.rows .scope { padding: 12px 0; border-bottom: 1px solid var(--line1); font-size: 13px; }
/* The contact picker */
html.office .plist { background: var(--panel); }
/* The people under the search box: one line each (name · cell, the tag), four tall, the rest a scroll away. */
html.office [data-q] + .plist { --row: 40px; max-height: calc(38px + 4 * var(--row)); }
html.office [data-q] + .plist .prow { flex: none; min-height: var(--row); justify-content: center; }
html.office .pmore { font: 12px var(--mono); color: var(--muted); }
html.office .pmore::before { content: "·"; margin-right: 8px; }
html.office .psub:empty { display: none; }
html.office .phead { font: 10px var(--mono); letter-spacing: .14em; color: var(--dim); }
html.office .prow:hover, html.office .prow:focus-visible { background: var(--hover); }
html.office .pname { font-size: 14px; }
html.office .psub { font: 11.5px var(--mono); color: var(--muted); }
html.office .ctag { border-color: var(--line); border-radius: 4px; font: 9.5px var(--mono); color: var(--muted); }
html.office .ctag.blue { border-color: #1E3252; color: var(--blue); }
html.office .ctag.gold { border-color: #5A3410; color: var(--gold); }
html.office .pchip { background: var(--panel); border-color: var(--amber); }

/* Jobs: the search, the heading, the tabs, the day, the table */
.search { position: relative; max-width: 640px; }
.search input { width: 100%; height: 36px; padding: 0 12px 0 34px; background: var(--card); border: 1px solid var(--line); border-radius: 8px; font-size: 13px; outline: none; }
.search input:focus { border-color: var(--line3); background: var(--hover); }
.search span { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--faint); font-size: 14px; pointer-events: none; }
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.page-head h1 { margin-top: 7px; }
/* A screen's top row with only a search in it (People) */
.jobhead { justify-content: flex-start; }
.jobhead .search { flex: 1 1 240px; }
.tabs { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.tab { display: inline-flex; align-items: center; gap: 8px; padding: 6px 8px 6px 13px; border: 1px solid var(--line); border-radius: 20px; background: transparent; color: var(--muted); font: 11px var(--mono); white-space: nowrap; }
.tab:hover { border-color: #4A5260; }
.tab.on { background: var(--card); border-color: #4A5260; color: var(--ink); font-weight: 600; }
.tab .n { min-width: 18px; padding: 1px 6px; border-radius: 10px; background: var(--line); color: var(--muted); font-size: 10px; font-weight: 400; line-height: 1.5; text-align: center; }
.tab.zero { opacity: .55; }
.tabs .sep { flex: none; width: 1px; height: 18px; margin: 0 4px; background: var(--line); }
.tab.fold { padding-right: 10px; border-style: dashed; }
.tab.fold.open { border-style: solid; }
.tab.fold .chev { font-size: 10px; color: var(--dim); }
.mini-track { display: inline-flex; align-items: center; flex: none; }
.mini-track i { width: 5px; height: 5px; border-radius: 50%; background: var(--line); }
.mini-track i + i { margin-left: 4px; }
.mini-track i.on { background: var(--amber); }
.track { display: flex; align-items: center; max-width: 120px; }
.track i { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--line); }
.track b { flex: 1; height: 2px; background: var(--line); }
.track i.on, .track b.on { background: var(--amber); }
.track + .stage { display: block; margin-top: 5px; padding-top: 0; border-top: 0; font: 10px var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The addresses under the street box: one line each (the street, then the city and ZIP code), every one of them in
   sight with no scrolling inside the list. */
#addrlist { max-height: none; scroll-margin-bottom: 16px; }
#addrlist .prow { flex: none; flex-direction: row; align-items: baseline; gap: 10px; padding: 9px 16px; }
#addrlist .pname { flex: none; }
#addrlist .psub { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* A service address: the street gets twice the room of the city. */
.seg.addr .in:first-child { flex: 2; }
/* The When boxes: the date and the time get the room, the length only what it needs. */
html.office .seg.when .in { padding-left: 10px; padding-right: 8px; }
html.office .seg.when select.in { flex: 0 0 92px; }
html.office .seg.when #time { flex: 0 0 100px; }
html.office .seg.when select.in:has(option[value=""]:checked), html.office .seg.when #datebtn.blank { color: var(--faint); }
html.office .seg.when select.in option { color: var(--text, #fff); }
/* The day is a button that opens a month of days to tap: today ringed, the day picked in amber, days gone by dimmed. */
#datebtn { display: flex; align-items: center; justify-content: space-between; gap: 6px; text-align: left; white-space: nowrap; overflow: hidden; }
#datebtn::after { content: ""; flex: 0 0 auto; width: 6px; height: 6px; margin: 0 4px 3px 0; border-right: 1.5px solid var(--mid); border-bottom: 1.5px solid var(--mid); transform: rotate(45deg); }
#datebtn[aria-expanded="true"] { border-color: var(--line3); outline: 1px solid var(--amber); }
.cal { padding: 10px; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; }
.calhead { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.calhead b { font-size: 13px; font-weight: 600; }
html.office .calhead .btn { padding: 3px 12px; font-size: 16px; line-height: 1.2; }
.calgrid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 2px; }
.calgrid > i { padding: 4px 0; text-align: center; font: 10px var(--mono); color: var(--dim); }
.calgrid button { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; min-height: 40px; padding: 0; border: 1px solid transparent; border-radius: 7px; background: transparent; font-size: 13px; }
/* Under a day ahead, a dot a job booked that day, in its plumber's colour (red: nobody's yet); past four, how many more. */
.caldots { display: flex; align-items: center; justify-content: center; gap: 2px; height: 6px; }
.caldots i { flex: none; width: 5px; height: 5px; border-radius: 50%; }
.caldots i.loose { background: var(--red); }
.caldots em { margin-left: 1px; font: 8px/1 var(--mono); color: var(--dim); }
.calgrid button.on .caldots i { box-shadow: 0 0 0 1px var(--on-amber); }
.calgrid button.on .caldots em { color: var(--on-amber); }
.calgrid button:hover { border-color: var(--amber); }
.calgrid button.past { color: var(--faint); }
.calgrid button.today { border-color: var(--line3); }
.calgrid button.on { background: var(--amber); border-color: var(--amber); color: var(--on-amber); font-weight: 700; }
.calquick { display: flex; gap: 8px; margin-top: 8px; }
.calquick .btn { flex: 1; }
/* A box the booking is not taken without has a red asterisk beside its label. */
.label.req::after { content: "*"; margin-left: 5px; color: var(--red); font: 700 14px/0 var(--body); letter-spacing: 0; vertical-align: -4px; }
/* The day at a glance under them: a lane a plumber, the jobs booked in the plumber's colour, this job's time in amber across the lanes. */
.glance { display: flex; flex-direction: column; gap: 8px; }
.gsum { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.gfree { font-size: 12.5px; font-weight: 600; }
.gfree::before { content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 7px; border-radius: 50%; background: var(--green); }
.gfree.none::before { background: var(--red); }
.gbox { display: grid; grid-template-columns: fit-content(132px) minmax(0, 1fr); column-gap: 10px; padding: 6px 12px 4px 10px; background: var(--panel); border: 1px solid var(--line); border-radius: 7px; }
.glane { display: contents; }
.gwho { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 11px; color: var(--mid); white-space: nowrap; }
.gwho i { flex: none; width: 8px; height: 8px; border-radius: 2px; }
.gwho i[style*="transparent"] { border: 1px dashed var(--dim); }
.gwho em { margin-left: auto; padding-left: 4px; font: 9px var(--mono); font-style: normal; letter-spacing: .06em; text-transform: uppercase; color: var(--gold); }
.gtrack { position: relative; height: 22px; background: linear-gradient(to right, var(--line1) 1px, transparent 1px) 0 0 / calc(100% / var(--hours)) 100%; }
.gtrack u { position: absolute; top: 0; bottom: 0; background: rgba(217, 119, 6, .16); border: solid var(--amber2); border-width: 0 1px; }
.glane:first-child .gtrack u { border-top-width: 1px; border-radius: 3px 3px 0 0; }
.glane:nth-last-child(2) .gtrack u { border-bottom-width: 1px; border-radius: 0 0 3px 3px; }
.glane:first-child:nth-last-child(2) .gtrack u { border-radius: 3px; }
.gjob { position: absolute; top: 5px; height: 12px; border-radius: 3px; box-shadow: 0 0 0 1px var(--panel); }
.gjob.loose { background: repeating-linear-gradient(135deg, var(--faint) 0 3px, transparent 3px 6px); box-shadow: 0 0 0 1px var(--panel), inset 0 0 0 1px var(--dim); }
.gaxis .gwho { color: var(--dim); font: 10px var(--mono); }
.gaxis .gnew { background: rgba(217, 119, 6, .16); border: 1px solid var(--amber2); }
.gticks { position: relative; height: 20px; }
.gticks span { position: absolute; top: 5px; transform: translateX(-50%); font: 9.5px var(--mono); color: var(--dim); }
html.office .hint.warn { color: var(--gold); }
.daybox { display: flex; flex-direction: column; gap: 12px; padding: 14px 18px 18px; background: var(--panel); border: 1px solid var(--line); border-radius: 12px; }
.daytabs { display: flex; align-items: stretch; gap: 2px; border-bottom: 1px solid var(--line1); }
.daytab { flex: 1 1 0; min-width: 0; padding: 9px 16px 11px; border: 0; border-bottom: 2px solid transparent; border-radius: 8px 8px 0 0; background: transparent; text-align: left; }
.daytab:hover:not(.on) { background: var(--hover); }
.daytab .d1 { font-size: 13.5px; font-weight: 500; color: #C7CBD2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.daytab .d2 { margin-top: 4px; font: 10px var(--mono); color: #8C939E; white-space: nowrap; }
.daytab.none .d1 { color: #6B7280; }
.daytab.none .d2 { color: var(--faint); }
.daytab.on { background: var(--card); border-bottom-color: var(--amber); }
.daytab.on .d1 { font-weight: 700; color: var(--ink); }
.daytab.on .d2 { color: var(--amber2); }
.daynav { flex: none; padding: 0 10px; border: 0; background: transparent; color: var(--muted); font-size: 18px; }
.daynav:hover { color: var(--amber2); }
.dayjump { display: flex; gap: 2px; margin-left: auto; padding: 3px; border: 1px solid var(--line); border-radius: 10px; }
.daycap { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin: 0 2px 10px; }
.daycap b { font-size: 14px; font-weight: 600; color: var(--ink); }
.daycap .ctclock { padding: 3px 9px; border: 1px solid var(--line); border-radius: 8px; background: var(--raised); font-size: 14px; font-weight: 600; color: var(--ink); }
.daycap .ctclock small { font-size: 10.5px; color: var(--amber); }
.between { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.table { background: var(--card); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.thead, .trow { display: grid; align-items: center; gap: 14px; padding: 11px 18px; }
/* The Jobs table, one thing a column: status, customer, address, payer, type, service, plumber, dispatcher, billed, arrival. */
.jobs-cols { grid-template-columns: 158px minmax(0, 1.2fr) minmax(0, 1.8fr) minmax(0, 1fr) 100px minmax(0, 1.5fr) minmax(148px, 1fr) minmax(0, 1fr) 112px 144px; }
/* It is ruled: a line between every two columns, down the header and every row. So the cells, not the row, carry
   the padding (the widths above count it in), and each fills its row's height, what it says centred in it, for
   the lines to meet. */
.thead.jobs-cols, .trow.jobs-cols { gap: 0; padding: 0; align-items: stretch; }
.jobs-cols > div { display: flex; flex-direction: column; justify-content: center; min-width: 0; padding: 14px 12px; border-left: 1px solid var(--line); }
.thead.jobs-cols > div { padding-top: 11px; padding-bottom: 11px; }
.jobs-cols > div:first-child { padding-left: 18px; border-left: 0; }
.jobs-cols > div:last-child { padding-right: 18px; }
.trow.jobs-cols { border-bottom-color: var(--line); }
@media (min-width: 1341px) { .jobs-cols .fold { display: none; } }
.jobs-cols > .plumber .flash { margin-right: 0; } /* "Needs a plumber" alone in the plumber's column */
.thead { border-bottom: 1px solid var(--line); font: 10px var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--dim); }
.trow { padding: 14px 18px; border-bottom: 1px solid var(--line1); }
.trow:last-child { border-bottom: 0; }
.trow:hover { background: var(--hover); }
.trow .primary { font-size: 13.5px; font-weight: 600; }
.trow .sub { margin-top: 2px; font-size: 11.5px; color: var(--dim); }
.trow .self { color: var(--dim); }
.trow .when { font-size: 12.5px; font-weight: 600; }
.trow .when.today { color: var(--amber2); }
/* Open work with nobody on it: a red edge on its row, and a badge that flashes until a plumber is picked. An accepted estimate waiting for its new time is flagged the same way, where its time would be. */
.trow.need { background: rgba(239, 68, 68, .07); box-shadow: inset 3px 0 0 var(--red); }
.trow.need:hover { background: rgba(239, 68, 68, .12); }
.jobs-cols > .time .flash { margin-right: 0; }
.flash { display: inline-block; margin-right: 6px; padding: 1px 7px; border: 1px solid var(--red); border-radius: 4px; background: rgba(239, 68, 68, .16); color: #FCA5A5; font: 600 9.5px var(--mono); letter-spacing: .08em; text-transform: uppercase; animation: flash 1.1s ease-in-out infinite; }
@keyframes flash { 50% { opacity: .3; } }
@media (prefers-reduced-motion: reduce) { .flash { animation: none; } }
.flash.still { border-color: var(--gold); background: rgba(233, 162, 59, .14); color: var(--gold); animation: none; }
/* What needs a person's attention, over the Jobs table: one line each, with the links to act on. */
.attn { display: flex; flex-direction: column; margin: 0 0 14px; border: 1px solid #5A3410; border-radius: 10px; background: rgba(233, 162, 59, .05); }
.attn-head { padding: 11px 14px 6px; font: 600 10px var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--gold); }
.attn-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 9px 14px; border-top: 1px solid var(--line); font-size: 13px; line-height: 1.45; color: var(--mid); }
.attn-links { display: flex; flex: 0 0 auto; flex-wrap: wrap; justify-content: flex-end; gap: 6px; max-width: 45%; }
@media (max-width: 720px) { .attn-row { flex-direction: column; align-items: flex-start; } .attn-links { max-width: none; justify-content: flex-start; } }
.tab.alert { border-color: var(--red); color: #FCA5A5; }
.tab.alert .n { background: var(--red); color: #fff; }
html.office .cols > .col > .field.need { border-color: var(--red); box-shadow: 0 0 0 1px var(--red); }
html.office .dayjump .btn { height: 28px; padding: 0 13px; border: 0; border-radius: 7px; background: transparent; color: var(--muted); font-size: 13px; }
html.office .dayjump .btn:hover:not(.on) { background: var(--hover); color: var(--ink); }
html.office .dayjump .btn.on { background: var(--raised); color: var(--ink); font-weight: 600; }
/* Staff: a word on where a plumber's onboarding stands; and a person's profile, what they filed at onboarding in parts under one heading. */
.flag { display: inline-block; padding: 2px 8px; border: 1px solid var(--line); border-radius: 5px; font: 600 10px var(--mono); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); white-space: nowrap; }
.flag.gold { border-color: #5A3410; background: rgba(233, 162, 59, .14); color: var(--gold); }
.flag.red { border-color: #5A2020; background: rgba(239, 68, 68, .14); color: #FCA5A5; }
.flag.green { border-color: #2F5D4A; background: rgba(52, 211, 153, .1); color: var(--green); }
html.office .cols > .col > .field.onfile { gap: 0; padding: 0; }
.onfile .part { display: flex; flex-direction: column; gap: 10px; padding: 14px 18px; border-top: 1px solid var(--line1); }
.onfile .part:first-child { gap: 3px; border-top: 0; border-bottom: 1px solid var(--line); }
.onfile .part:first-child + .part { border-top: 0; }
.onfile .part.two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
.onfile .part.two > div { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
.onfile .wait { color: var(--muted); }
.kv { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 28px; }
.kv > div { display: flex; justify-content: space-between; gap: 12px; min-width: 0; }
.kv span { color: var(--muted); white-space: nowrap; }
.kv b { font-weight: 600; text-align: right; overflow-wrap: anywhere; }
.more { font-weight: 600; color: var(--amber2); }
.more:hover { text-decoration: underline; }
@media (max-width: 560px) { .kv, .onfile .part.two { grid-template-columns: minmax(0, 1fr); } }
.min { min-width: 0; }
.right { text-align: right; }
.mono { font-family: var(--mono); }
.ellipsis { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* A window short of desk width: the address is back under the customer and the plumber back under the job. */
@media (max-width: 1340px) {
  .jobs-cols { grid-template-columns: 158px minmax(0, 1.3fr) minmax(0, 1fr) 100px minmax(0, 1.5fr) minmax(0, 1fr) 112px 144px; }
  .jobs-cols > :nth-child(3), .jobs-cols > :nth-child(7) { display: none; }
}
/* Narrower: the table drops its dispatcher column, */
@media (max-width: 1000px) {
  .jobs-cols { grid-template-columns: 158px minmax(0, 1.3fr) minmax(0, 1fr) 100px minmax(0, 1.5fr) 112px 144px; }
  .jobs-cols > :nth-child(8) { display: none; }
}
/* and a narrow window its service column. */
@media (max-width: 860px) {
  .jobs-cols { grid-template-columns: 146px minmax(0, 1.2fr) minmax(0, 1fr) 100px 112px 144px; }
  .jobs-cols > :nth-child(6) { display: none; }
}
/* A phone: the status, the customer and the arrival; the day tabs scroll sideways. */
@media (max-width: 560px) {
  html.office .screen.office { padding: 16px 14px 32px; }
  .oside { gap: 10px; padding: 0 14px; }
  .oside .me .name, .brand-name { display: none; }
  .jobs-cols { grid-template-columns: 112px minmax(0, 1fr) 104px; }
  .jobs-cols > div { padding-left: 8px; padding-right: 8px; }
  .jobs-cols > div:first-child { padding-left: 12px; }
  .jobs-cols > div:last-child { padding-right: 12px; }
  .jobs-cols > :nth-child(4), .jobs-cols > :nth-child(5), .jobs-cols > :nth-child(9) { display: none; }
  .daybox { padding: 10px 12px 14px; }
  .daytabs { overflow-x: auto; }
  .daytab { flex: 1 0 auto; padding: 9px 10px 11px; }
}

/* ── Payouts: a card a person (what they are owed, and under it the proof job by job), then the payment log.
   After the old Job Tracker's Balances screen. ── */
#pay { display: flex; flex-direction: column; gap: 22px; }
.seg#pay { flex-direction: row; gap: 8px; } /* a job's Card | Cash/Check carries the same id: side by side */
html.office .eyebrow.sm { font-size: 9.5px; letter-spacing: .12em; }
/* The two lists of people, each under its name with how many there are; beside it the pay rules that go for all of
   them, a tag a rule, and for the dispatchers how far through the pay period today is. */
.payee-sec-head { display: flex; align-items: center; justify-content: space-between; gap: 10px 18px; flex-wrap: wrap; margin-bottom: 12px; padding: 0 2px; }
.py-sect { display: flex; align-items: center; gap: 9px; font-size: 16px; font-weight: 700; letter-spacing: -.01em; color: var(--ink); }
.py-sect i { flex: none; width: 9px; height: 9px; border-radius: 3px; background: var(--amber2); }
.py-sect.disp i { background: var(--blue); }
.py-sect span, .py-sech .t span, .py-more span:not(.chev-in) { padding: 2px 8px; border-radius: 999px; background: var(--raised); font: 500 11px var(--mono); letter-spacing: 0; color: var(--muted); }
.py-rules, .py-tags { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.py-tag { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; border: 1px solid var(--line); border-radius: 999px; font: 11px/1.35 var(--mono); color: var(--muted); white-space: nowrap; }
.py-tag.role { border-color: transparent; background: var(--raised); background: color-mix(in srgb, var(--acc) 15%, transparent); color: var(--acc); }
.py-tag.live { border-color: transparent; background: rgba(52, 211, 153, .12); color: var(--green); }
.py-tag.hot { border-color: transparent; background: var(--raised); background: color-mix(in srgb, var(--amber2) 18%, transparent); color: var(--amber2); }
.py-tag.neg { border-color: transparent; background: rgba(239, 68, 68, .14); color: var(--red); }
.py-tag.live i, .py-live i { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--green); }
.py-live { display: inline-flex; align-items: center; gap: 6px; color: var(--green); }
.py-period { display: inline-flex; align-items: center; gap: 9px; padding-left: 6px; font: 11px var(--mono); color: var(--muted); white-space: nowrap; }
.py-period .bar { width: 120px; height: 6px; border-radius: 999px; background: var(--raised); overflow: hidden; }
.py-period .bar i { display: block; height: 100%; border-radius: 999px; background: var(--blue); }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); gap: 14px; align-items: start; }
/* A person's card. --acc is their colour: the plumbers' or the dispatchers'. Shut, it is the head alone: who, what
   they are (a tag a fact), the sum and where it stands. */
.card.payee { --acc: var(--amber2); gap: 0; padding: 0; overflow: hidden; overflow: clip; transition: border-color .3s ease; }
.card.payee.disp { --acc: var(--blue); }
/* An opened card takes the whole row: the table under it has a column a figure. */
.card.payee.open { grid-column: 1 / -1; }
html.office .card.payee.due { border-color: var(--amber); box-shadow: 0 0 0 1px var(--amber); }
.payee-head { display: flex; align-items: center; gap: 14px; width: 100%; padding: 16px 20px; border: 0; background: none; text-align: left; }
.payee-head:hover { background: var(--hover); }
.payee-head .avatar { flex: none; display: grid; place-items: center; width: 44px; height: 44px; border-radius: 12px; background: var(--raised); background: color-mix(in srgb, var(--acc) 16%, var(--card)); color: var(--acc); font-size: 14px; font-weight: 700; }
.payee-head .who { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 7px; }
.payee-head .n { font-size: 17px; font-weight: 700; letter-spacing: -.01em; line-height: 1.2; }
.payee-head .r { max-width: 100%; font: 11px/1.5 var(--mono); color: var(--dim); }
.payee-head .r.gold { color: var(--gold); }
.payee-head .amt { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 7px; }
.payee-head .a { font: 500 26px/1 var(--mono); letter-spacing: -.02em; color: var(--acc); white-space: nowrap; }
.payee-head .a.zero { color: var(--dim); }
.payee-head .a.neg { color: var(--red); }
.payee-head .amt .py-tag { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; }
.card-chev { flex: none; padding-left: 2px; font: 13px var(--mono); color: var(--dim); }
.payee-head:hover .card-chev { color: var(--ink); }
/* Opened: the sum on the left, set out as a pay stub (a line a part, the total, the button that records the payout),
   and on the right the proof; the sum stays in sight while a long proof scrolls by. On a narrower screen the proof
   goes under the sum. */
.py-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 22px; padding: 20px; border-top: 1px solid var(--line); }
@media (min-width: 1440px) { .py-body { grid-template-columns: 320px minmax(0, 1fr); gap: 22px; align-items: start; } .py-ledger { position: sticky; top: 0; } }
@media (min-width: 1520px) { .py-body { grid-template-columns: 372px minmax(0, 1fr); gap: 26px; } }
.py-ledger { display: flex; flex-direction: column; gap: 14px; max-width: 560px; padding: 18px 18px 20px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); }
.py-ledger .eyebrow:not(:first-child) { margin-top: 8px; }
.py-lines { display: flex; flex-direction: column; }
.py-line { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 11px 0; border-bottom: 1px solid var(--line1); }
.py-line:first-child { padding-top: 0; }
.py-line:last-child { border-bottom-color: var(--line3); }
.py-line b { display: block; font-size: 14px; font-weight: 600; color: var(--ink); }
.py-line small { display: block; margin-top: 3px; font-size: 12px; line-height: 1.35; color: var(--dim); }
.py-line > span { flex: none; font: 500 15px var(--mono); color: var(--ink); white-space: nowrap; }
.py-line.zero b, .py-line.zero > span { color: var(--dim); }
.py-line.neg > span { color: var(--red); }
.py-total { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.py-total span { font-size: 14px; font-weight: 700; color: var(--ink); }
.py-total b { font: 600 28px/1 var(--mono); letter-spacing: -.02em; color: var(--acc); white-space: nowrap; }
.py-total.zero b { color: var(--dim); }
.py-total.neg b { color: var(--red); }
/* A dispatcher's sum again by when it is paid: what is due now, and what waits for the payday. */
.py-when { display: flex; gap: 8px; }
.py-when > div { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 5px; padding: 12px 13px; border: 1px solid var(--line); border-radius: 10px; background: var(--card); }
.py-when .k { font: 9.5px var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--dim); }
.py-when .v { font: 500 19px/1.1 var(--mono); color: var(--ink); white-space: nowrap; }
.py-when .s { font-size: 11.5px; line-height: 1.4; color: var(--muted); }
.py-when .zero .v { color: var(--dim); }
.py-when .hot { border-color: var(--amber); }
.py-when .hot .v { color: var(--amber2); }
.pay-btn { width: 100%; margin-top: 2px; padding: 12px 10px; border: 0; border-radius: 9px; background: var(--raised); color: var(--ink); font-size: 13.5px; font-weight: 700; }
.pay-btn:hover { filter: brightness(1.15); }
/* Money to hand over now: the one thing on the card to press. */
.pay-btn.go { background: var(--amber); color: var(--on-amber); }
/* Not payday yet: the commission is adding up, and the button says when it is paid. */
.pay-btn.locked { background: transparent; border: 1px dashed var(--line3); color: var(--dim); cursor: not-allowed; }
.pay-btn.locked:hover { filter: none; }
.pay-btn:disabled { opacity: .45; cursor: default; filter: none; }
.pay-btn.busy { opacity: .7; pointer-events: none; }
.py-aside { font-size: 12px; line-height: 1.5; color: var(--dim); }
.py-aside b { font: 500 12px var(--mono); color: var(--mid); }
.py-detail { display: flex; flex-direction: column; gap: 24px; min-width: 0; }
.py-sec { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.py-sech { display: flex; align-items: center; justify-content: space-between; gap: 6px 14px; flex-wrap: wrap; }
.py-sech .t, .py-more { display: flex; align-items: center; gap: 8px; font-size: 14.5px; font-weight: 700; color: var(--ink); }
.py-sech .note { font: 11.5px var(--mono); color: var(--dim); }
.py-none { padding: 14px 16px; border: 1px dashed var(--line); border-radius: 10px; font-size: 12.5px; color: var(--dim); }
.py-more { align-self: flex-start; padding: 0; border: 0; background: none; }
button.py-more:hover { color: var(--amber2); }
div.py-more { color: var(--dim); }
/* The table. As written here it is the phone's: a row is a short list, each figure a line with its column's name
   before it. On a wider screen (below) the rows share one set of columns, each as wide as its figures; when room is
   short the columns' names fold onto two lines first, and only then does the table scroll sideways. A row with
   somewhere to go is a link all the way across: its name's link is stretched over it, and the receipt shots sit on top of that. */
.py-scroll { max-width: 1280px; overflow-x: auto; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
.py-tr { position: relative; display: flex; flex-direction: column; gap: 7px; padding: 13px 16px; border-top: 1px solid var(--line1); }
.py-tr.head { display: none; }
.py-tr.head + .py-tr { border-top: 0; }
.py-tr.head i { margin-right: 6px; font-style: normal; color: var(--faint); }
.py-tr .lead { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.py-tr .lead b { font-size: 13.5px; font-weight: 600; color: var(--ink); }
.py-tr .lead .top { display: flex; align-items: center; gap: 9px; min-width: 0; }
.py-tr .lead .top .py-tag { flex: none; padding: 2px 8px; font-size: 10.5px; }
.py-tr .lead small { font-size: 12px; color: var(--dim); }
.py-tr .lead small.py-live { color: var(--green); }
.py-tr .lead small.gold { color: var(--gold); }
.py-tr a.lead::after { content: ""; position: absolute; inset: 0; }
.py-tr:has(a.lead):hover { background: var(--hover); }
.py-tr .num { display: flex; align-items: baseline; justify-content: flex-end; gap: 8px; font: 12.5px var(--mono); color: var(--mid); white-space: nowrap; }
.py-tr .num::before { content: attr(data-k); margin-right: auto; font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--dim); }
.py-tr .num:empty { display: none; }
.py-tr .num b { font-weight: inherit; }
.py-tr .num small { font: 10.5px var(--mono); color: var(--dim); }
.py-tr .num small.gold, .py-tr .gold { color: var(--gold); }
.py-tr .num .neg { color: var(--red); }
.py-tr .mat { align-items: center; }
.py-tr .mat > span:last-child { display: flex; align-items: baseline; gap: 8px; }
.py-tr .rc-list:empty { display: none; }
.py-tr .rc-thumb, .py-tr .rc-missing { position: relative; z-index: 1; }
.py-tr .rc-thumb { width: 38px; height: 38px; border-radius: 7px; }
.py-tr:not(.head) .strong { font-weight: 500; color: var(--ink); }
.py-tr:not(.head) .sum { font-size: 13.5px; font-weight: 600; color: var(--acc); }
.py-table.pending .py-tr:not(.head) .sum, .py-table.pending .sum .neg { font-weight: 500; color: var(--muted); }
.py-tr.foot { border-top-color: var(--line3); background: rgba(255, 255, 255, .025); }
.py-tr.foot .lead b { font: 9.5px var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--dim); }
.py-tr.foot .num { color: var(--ink); }
.chev-in, .py-edit { margin-left: 5px; font: 10px var(--mono); color: var(--blue); }
.py-edit { margin: 0; font-size: 11px; }
@media (min-width: 760px) and (max-width: 1679px) { .py-table, .py-tr { --gap: 16px; } }
@media (min-width: 760px) { @supports (grid-template-columns: subgrid) {
  .py-table { display: grid; grid-template-columns: minmax(150px, 1fr) repeat(var(--n), auto); column-gap: var(--gap, 26px); min-width: min-content; }
  .py-table.staged { grid-template-columns: minmax(220px, 1fr) repeat(var(--n), auto); }
  .py-tr { display: grid; grid-template-columns: subgrid; grid-column: 1 / -1; align-items: center; gap: 0 var(--gap, 26px); }
  .py-tr.head { display: grid; padding-top: 10px; padding-bottom: 10px; border-top: 0; border-bottom: 1px solid var(--line); font: 9.5px var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--dim); }
  .py-tr .lead { max-width: 440px; }
  .py-tr .num { flex-direction: column; align-items: flex-end; justify-content: center; gap: 3px; }
  .py-tr .num::before { content: none; }
  .py-tr .num:empty { display: flex; }
  .py-tr .txt { align-items: flex-start; }
  .py-tr .mat { flex-direction: row; align-items: center; justify-content: flex-end; gap: 10px; }
  .py-tr .mat > span:last-child { flex-direction: column; align-items: flex-end; gap: 3px; margin-left: auto; }
  .py-tr.head .num { display: block; font: inherit; line-height: 1.5; color: inherit; text-align: right; white-space: normal; }
  .py-tr.head .txt { text-align: left; }
} }
@media (max-width: 620px) {
  .payee-head { gap: 11px; padding: 14px; }
  .payee-head .avatar { width: 38px; height: 38px; border-radius: 10px; font-size: 13px; }
  .payee-head .a { font-size: 20px; }
  .py-body { padding: 14px; }
  .py-period .bar { width: 72px; }
}
.gold { color: var(--gold); }
/* A receipt shot on a row: a small picture that opens the shot whole; said in gold when there should be one and is none. */
.rc-thumb { flex: none; display: block; width: 46px; height: 36px; border: 1px solid #2F5D4A; border-radius: 5px; overflow: hidden; }
.rc-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.rc-thumb:hover { border-color: var(--blue); }
.rc-list { display: flex; align-items: center; gap: 6px; }
.logjobs .rc-list:not(:empty) { margin-top: 3px; }
.rc-missing { flex: none; padding: 3px 7px; border: 1px dashed #5A3410; border-radius: 5px; font: 9.5px var(--mono); color: var(--gold); white-space: nowrap; }
.faint { color: var(--dim); }
.rules-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 170px), 1fr)); gap: 10px; }
.rules-grid .label { margin-bottom: 6px; }
html.office .rules-grid .in { padding: 8px 10px; font-size: 12.5px; }
.payrules .acts { margin-top: 10px; }
.pmain { flex: 1; min-width: 0; }
.pmain .t { font-size: 12.5px; }
.pmain .s { margin-top: 3px; font: 10.5px/1.55 var(--mono); color: var(--muted); }
.payrow .amt { flex: none; font: 12.5px var(--mono); white-space: nowrap; }
/* The payment log: one row a payout, the jobs it paid for under the name, each with its own sum. */
.card.paylog { gap: 0; padding: 0; overflow: hidden; }
.paylog-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; padding: 16px 18px; }
.paylog-head .t { font-size: 15px; font-weight: 700; }
.paid-today { font: 11px var(--mono); color: var(--green); }
.paylog .thead { border-top: 1px solid var(--line); }
.paylog-cols { grid-template-columns: minmax(150px, 200px) minmax(0, 1fr) minmax(96px, auto) minmax(80px, auto) 30px; gap: 12px; align-items: start; }
.paylog .trow:hover { background: none; }
.paylog .when { font-size: 11.5px; color: var(--muted); }
.logjobs { display: flex; flex-direction: column; gap: 3px; margin-top: 7px; }
.logjob { font: 10.5px/1.5 var(--mono); color: var(--dim); }
.logjob:hover { color: var(--ink); }
.logjob b { font-weight: 500; color: var(--mid); }
/* A payment added by hand: the button over the log, what it was for on its line, and the sheet with its job dropdown and search. */
.paylog-acts { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.logwhy { font-size: 12.5px; line-height: 1.45; color: var(--mid); overflow-wrap: anywhere; }
.ask.addpay { max-height: calc(100dvh - 32px); overflow-y: auto; }
.addpay .label { display: block; margin-bottom: 6px; }
.jobpick { display: flex; align-items: center; justify-content: space-between; gap: 10px; text-align: left; }
.jobpick .ellipsis { min-width: 0; }
.jobpick .none, .jobpick .chev { flex: none; color: var(--dim); }
.jobmenu { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.jobmenu .plist { max-height: 232px; }
.jobmenu .pname { flex-wrap: wrap; row-gap: 0; }
.x { width: 24px; height: 24px; padding: 0; border: 1px solid var(--line); border-radius: 6px; background: transparent; color: var(--dim); font-size: 14px; line-height: 1; }
.x:hover { border-color: var(--red); color: var(--red); }
.card.payrules { gap: 12px; }
.payrules-said { align-items: flex-start; flex-wrap: nowrap; gap: 18px; }
.payrules-said .btn { flex: none; }
/* The sheet a payout is recorded on. */
.ask.wide { max-width: 660px; }
.payrows { display: flex; flex-direction: column; max-height: 42vh; overflow-y: auto; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); }
.payrow { display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px; border-bottom: 1px solid var(--line1); cursor: pointer; }
.payrow:last-child { border-bottom: 0; }
.payrow input { flex: none; margin: 3px 0 0; accent-color: var(--amber2); }
.payrow.fixed { padding-left: 35px; cursor: default; } /* a payment from the log, in the payout whatever is ticked: no tick, in line with the rows that have one */
.paysum { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; font-size: 13px; color: var(--muted); }
.paysum b { font: 500 20px var(--mono); color: var(--ink); }
/* Who is paid what on a job's page: a sum a row, how it is figured under its name. */
html.office .card.rows .row.tall { align-items: flex-start; gap: 14px; padding: 9px 0; }
.row.tall .money { white-space: nowrap; }
.st-paid { color: var(--green); }
.st-owed { color: var(--amber2); }
@media (max-width: 760px) {
  .paylog-cols { grid-template-columns: minmax(0, 1fr) minmax(84px, auto) 30px; }
  .paylog-cols .hide-sm { display: none; }
  .payrules-said { flex-wrap: wrap; }
}

/* ── People: the list at the left, the person picked at the right (the People design of 2026-10-05, in the office's
   own colours: what the design has in its accent is var(--amber), so blue mode turns it blue). At a desk the screen
   does not scroll: the list and the person each scroll in their own box. Narrower, it is the list, then the person
   on their own with a way back. ── */
.pacts { display: flex; flex: none; gap: 6px; margin-left: 10px; }
html.office .screen.office.ppl { font-size: 14px; gap: 16px; }
.ppl-back { display: none; }
.ppl-head { flex: none; display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.ppl-title { flex: 1 1 auto; display: flex; align-items: baseline; gap: 10px; }
html.office .ppl-title h1 { font: 600 24px/1.2 var(--body); letter-spacing: 0; }
.ppl-title span { font-size: 13px; color: var(--muted); }
.ppl-search { position: relative; flex: 0 1 420px; min-width: 240px; }
.ppl-search svg { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--muted); pointer-events: none; }
.ppl-search input { width: 100%; height: 38px; padding: 0 10px 0 36px; background: var(--panel); border: 1px solid var(--line3); border-radius: 7px; font-size: 14px; outline: none; }
.ppl-search input:focus { outline: 2px solid var(--amber); outline-offset: 1px; }
.ppl-chips { flex: none; display: flex; gap: 6px; flex-wrap: wrap; }
.ppl-chip { display: inline-flex; align-items: center; gap: 8px; height: 34px; padding: 0 12px; border: 1px solid var(--line3); border-radius: 999px; background: transparent; color: var(--mid); font-size: 13px; }
.ppl-chip:hover { border-color: var(--dim); }
.ppl-chip.on { background: color-mix(in srgb, var(--amber) 18%, var(--card)); border-color: color-mix(in srgb, var(--amber) 55%, var(--card)); color: var(--ink); font-weight: 500; }
.ppl-chip .n { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: var(--line); color: var(--mid); font: 11px var(--mono); }
.ppl-chip .n.zero { background: transparent; color: var(--dim); }
.ppl-chip.on .n { background: var(--amber); color: var(--on-amber); }
.ppl-body { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start; }
.ppl-list { flex: 1 1 340px; max-width: 460px; min-width: 0; background: var(--card); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.ppl-detail { flex: 999 1 560px; min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.ppl-detail > * { flex: none; }
.ppl-lhead { position: sticky; top: 0; z-index: 1; display: flex; justify-content: space-between; padding: 10px 14px; background: var(--card); border-bottom: 1px solid var(--line); font: 10px var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--dim); }
.ppl-row { position: relative; display: flex; align-items: center; gap: 12px; min-height: 64px; padding: 10px 14px; border-bottom: 1px solid var(--line1); }
.ppl-row:last-child { border-bottom: 0; }
.ppl-row:hover { background: var(--hover); }
.ppl-row.on { background: color-mix(in srgb, var(--amber) 12%, var(--card)); box-shadow: inset 3px 0 0 var(--amber); }
.ppl-row.kid { padding-left: 40px; }
.ppl-row.kid::before { content: ""; position: absolute; left: 22px; top: 0; height: 50%; width: 10px; border: solid var(--line3); border-width: 0 0 1px 1px; border-bottom-left-radius: 6px; }
.ppl-av { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 50%; background: var(--raised); color: var(--mid); font-size: 12px; font-weight: 600; }
.ppl-row.on .ppl-av { background: var(--amber); color: var(--on-amber); }
.ppl-av.big { width: 52px; height: 52px; background: color-mix(in srgb, var(--amber) 24%, var(--card)); color: var(--ink); font-size: 17px; }
.ppl-av.big svg { width: 22px; height: 22px; }
.ppl-who { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.ppl-name { display: flex; align-items: center; gap: 8px; min-width: 0; font-weight: 600; }
.ppl-name .ctag { flex: none; }
.ppl-sub { font-size: 13px; color: var(--muted); }
.ppl-sub.none { color: var(--dim); }
.ppl-n { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 2px; font-size: 12px; color: var(--muted); }
.ppl-n span:first-child { color: var(--dim); }
.ppl-n span.has { color: var(--ink); font-weight: 500; }
.ppl-ghead { display: flex; align-items: baseline; gap: 10px; padding: 12px 14px 8px; border-bottom: 1px solid var(--line1); font-weight: 600; }
.ppl-ghead span { font-size: 12px; font-weight: 400; color: var(--muted); }
.ppl-kidnone { padding: 8px 14px 10px 40px; border-bottom: 1px solid var(--line1); font-size: 12px; color: var(--dim); }
.ppl-none { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 40px 18px; text-align: center; color: var(--muted); }
.ppl-none b { font-weight: 500; color: var(--ink); }
.ppl-none .ppl-btn { margin-top: 6px; }
.ppl-more { padding: 10px 14px; font-size: 12px; color: var(--muted); }
.ppl-card { padding: 18px; background: var(--card); border: 1px solid var(--line); border-radius: 10px; }
.ppl-card.flush { padding: 0; overflow: hidden; }
.ppl-card.ppl-wait { color: var(--muted); }
.ppl-top { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; }
.ppl-id { flex: 1 1 260px; min-width: 0; }
.ppl-id h2 { display: flex; align-items: center; gap: 10px; margin: 0; font: 600 22px/1.2 var(--body); }
.ppl-id h2 .ctag { flex: none; }
.ppl-reach { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 6px; color: var(--mid); }
.ppl-reach a, .ppl-id .sub.warn a { color: var(--amber2); text-decoration: underline; }
.ppl-reach i { font-style: normal; color: var(--faint); }
.ppl-reach .no { color: var(--dim); }
.ppl-note { margin-top: 6px; font-size: 12px; color: var(--muted); }
.ppl-id .sub.warn { margin-top: 8px; font-size: 12.5px; line-height: 1.45; }
.ppl-acts { display: flex; gap: 8px; flex-wrap: wrap; }
.ppl-btn { display: inline-flex; align-items: center; gap: 7px; height: 36px; padding: 0 14px; border: 1px solid var(--line3); border-radius: 7px; background: var(--panel); color: var(--mid); font-size: 13px; white-space: nowrap; }
.ppl-btn:hover { border-color: var(--amber); }
.ppl-btn.primary { border-color: transparent; background: var(--amber); color: var(--on-amber); font-weight: 500; }
.ppl-btn.primary:hover { background: var(--amber2); }
.ppl-btn.md { height: 34px; }
.ppl-btn.sm { height: 30px; padding: 0 12px; gap: 6px; }
.ppl-btn.sm svg { width: 11px; height: 11px; }
.ppl-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin-top: 16px; }
.ppl-stats > div, .ppl-box { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; }
.ppl-stats > div { padding: 10px 12px; }
.ppl-stats span { display: block; font-size: 11px; color: var(--muted); }
.ppl-stats b { display: block; margin-top: 2px; font: 500 18px var(--mono); }
.ppl-chead { display: flex; justify-content: space-between; align-items: center; min-height: 30px; }
.ppl-card.flush .ppl-chead { min-height: 0; padding: 14px 18px; border-bottom: 1px solid var(--line); }
.ppl-chead h3 { margin: 0; font: 500 11px var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.ppl-chead > span { font-size: 12px; color: var(--muted); }
.ppl-job { display: grid; grid-template-columns: 124px minmax(0, 1fr) auto; gap: 16px; align-items: center; padding: 12px 18px; border-bottom: 1px solid var(--line1); transition: background-color .12s ease; }
.ppl-job:last-child { border-bottom: 0; }
.ppl-job:hover { background: var(--hover); }
.ppl-job.dead { opacity: .5; }
.ppl-when { display: flex; flex-direction: column; }
.ppl-when b { font-weight: 500; }
.ppl-when span { font: 12px var(--mono); color: var(--muted); white-space: nowrap; }
.ppl-what { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ppl-what b { font-weight: 600; }
.ppl-what .addr { font-size: 13px; color: var(--mid); }
.ppl-pills { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.ppl-pills span { display: inline-flex; align-items: center; min-height: 20px; padding: 0 7px; border: 1px solid var(--line3); border-radius: 999px; background: var(--hover); color: var(--mid); font-size: 11px; }
.ppl-end { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.ppl-end .mono { font-size: 12px; color: var(--muted); }
.ppl-stage { --c: var(--muted); display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 9px; border: 1px solid color-mix(in srgb, var(--c) 45%, transparent); border-radius: 999px; background: color-mix(in srgb, var(--c) 14%, transparent); color: var(--ink); font-size: 12px; font-weight: 500; white-space: nowrap; }
.ppl-stage i { width: 6px; height: 6px; border-radius: 50%; background: var(--c); }
.ppl-nojobs { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding: 28px 18px; color: var(--muted); }
.ppl-two { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px; }
.ppl-two .ppl-card { padding: 16px 18px; }
.ppl-box { display: flex; align-items: center; gap: 10px; margin-top: 10px; padding: 10px 12px; }
.ppl-box > svg { flex: none; color: var(--muted); }
.ppl-box > span:last-child { min-width: 0; display: flex; flex-direction: column; }
.ppl-box b { font-weight: 500; }
.ppl-box small { font-size: 12px; color: var(--muted); }
.ppl-box.link:hover { border-color: var(--amber); }
.ppl-glabel { margin-top: 12px; font: 10px var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--dim); }
.ppl-glabel + .ppl-box { margin-top: 6px; }
.ppl-quiet { margin-top: 10px; font-size: 13px; color: var(--muted); }
.ppl-dash { margin-top: 10px; padding: 14px 12px; border: 1px dashed var(--line3); border-radius: 8px; font-size: 13px; color: var(--muted); }
.ask.ppl-ask { max-height: calc(100dvh - 32px); }
.ask.ppl-ask .plist { flex: 1 1 auto; min-height: 80px; }
.ask.ppl-ask .prow.on { background: var(--hover); box-shadow: inset 3px 0 0 var(--amber); }
@media (min-width: 981px) {
  html.office .screen.office.ppl { overflow: hidden; padding-bottom: 22px; }
  .ppl-body { flex: 1 1 0; min-height: 0; flex-wrap: nowrap; align-items: stretch; }
  .ppl-list, .ppl-detail { overflow-y: auto; }
  .ppl-list { align-self: flex-start; max-height: 100%; }
}
@media (max-width: 980px) {
  .ppl-list { max-width: none; flex-basis: 100%; }
  .ppl.one .ppl-back { display: flex; }
  .ppl.one > .back:not(.ppl-back), .ppl.one .ppl-head, .ppl.one .ppl-chips, .ppl.one .ppl-list, .ppl:not(.one) .ppl-detail { display: none; }
}
@media (max-width: 560px) {
  .ppl-job { grid-template-columns: 84px minmax(0, 1fr); gap: 6px 12px; }
  .ppl-end { grid-column: 2; flex-direction: row; align-items: center; gap: 10px; }
  .ppl-when span { white-space: normal; }
}

/* ── Onboarding: a card a step, after the CRM's. The app's mark and which step this is across the top (a bar a
   step, the one showing a little longer), what the step asks, then Back and Continue along the bottom. ── */
.ob { flex: none; display: flex; flex-direction: column; background: var(--card); border: 1px solid var(--line); border-radius: 18px; box-shadow: 0 16px 48px rgba(27, 26, 23, .08); overflow: hidden; }
.ob-top { display: flex; align-items: center; gap: 12px; padding: 18px 20px 14px; border-bottom: 1px solid var(--line); }
.ob-top img { flex: none; width: 38px; height: 38px; border-radius: 11px; }
.ob-prog { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.ob-prog .label { font-size: 11px; }
.ob-bars { display: flex; gap: 5px; }
.ob-bars i { flex: 1; height: 5px; border-radius: 99px; background: var(--chip); }
.ob-bars i.on { background: var(--accent); }
.ob-bars i.now { flex: 1.6; }
.ob-body, .ob-body section { display: flex; flex-direction: column; gap: 16px; }
.ob-body { padding: 20px; }
.ob h1 { font-size: 24px; }
.ob-art { align-self: center; width: 96px; height: 96px; margin: 14px 0; }
.ob .in { min-height: 48px; padding: 0 14px; font-size: 16px; }
/* The welcome the card ends on: a tick, then what the app does from here, a line each. */
.ob-art.done { display: flex; align-items: center; justify-content: center; align-self: center; width: 56px; height: 56px; margin: 0; border-radius: 50%; background: var(--green); color: #fff; }
.ob-art.done svg { width: 30px; height: 30px; }
.ob-art.done ~ .head, .ob-art.done ~ .hint { text-align: center; }
.ob-foot { display: flex; gap: 12px; margin-top: 4px; }
.ob-foot .btn { flex: none; width: auto; min-height: 48px; padding: 0 18px; border: 1px solid var(--dash); border-radius: 10px; }
.ob-foot .btn.primary { flex: 1; border: 0; font-size: 16px; }

/* ── Blue mode: the office's dark look with blue where the amber is. The switch is at the foot of the sign-in
   screen and is kept on the device (html.blue, set in app.js). The plumbers' screens are light and blue already
   and stay as they are. The dark look's own names are pointed at blues here, so under it "amber" is whatever is
   pressed or picked; what warns stays gold and red. ── */
.bluesw { display: flex; align-items: center; gap: 14px; margin-top: auto; padding: 12px 16px; background: var(--card); border: 1px solid var(--line); border-radius: 10px; cursor: pointer; }
.bluesw span { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.bluesw b { font-size: 16px; font-weight: 600; }
.bluesw small { font-size: 13px; line-height: 1.4; color: var(--muted); }
.bluesw input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.bluesw i { flex: none; position: relative; width: 52px; height: 32px; border-radius: 999px; background: var(--dash); transition: background .15s ease; }
.bluesw i::after { content: ""; position: absolute; top: 3px; left: 3px; width: 26px; height: 26px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, .25); transition: transform .15s ease; }
.bluesw input:checked + i { background: var(--accent); }
.bluesw input:checked + i::after { transform: translateX(20px); }
.bluesw input:focus-visible + i { outline: 2px solid var(--ink); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .bluesw i, .bluesw i::after { transition: none; } }
/* More rows like it under Blue mode, close together: Skip onboarding, a switch, and Reset onboarding, a button (armed, the plumbers' names are outlined: the next one tapped is reset). */
.bluesw ~ .bluesw { margin-top: -10px; }
.bluesw.act { cursor: default; }
.bluesw .btn { flex: none; width: auto; min-height: 36px; padding: 0 14px; background: transparent; border: 1px solid var(--dash); border-radius: 8px; font-size: 14px; }
.screen.resetting .names > .btn:not([data-office]) { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }

/* --amber fills what is pressed, under white letters; --amber2 is the lighter blue for words and thin lines on the
   dark. --blue was the dispatchers' colour on Payouts: a violet now, to stay apart from the plumbers' blue. */
html.office.blue { --amber: #2563EB; --amber2: #6B9BFF; --on-amber: #FFFFFF; --accent: #6B9BFF; --blue: #B69DF8; }
/* The lighter blue is too pale under white letters, so a pressed button under the pointer has its own. */
html.office.blue .btn.primary:hover { background: #3B76F6; border-color: #3B76F6; }
/* Book a job: this job's time across the day's lanes. */
html.office.blue .gtrack u, html.office.blue .gaxis .gnew { background: rgba(37, 99, 235, .22); }
html.office .glance.picked .gtrack u, html.office .glance.picked .gaxis .gnew { background: color-mix(in srgb, var(--job) 24%, transparent); border-color: var(--job); }
html.office .glance.nobody .gtrack u, html.office .glance.nobody .gaxis .gnew { background: transparent; border-style: dashed; border-color: var(--muted); }
/* What was blue in the dark look stays blue, not the dispatchers' violet. */
html.office.blue .ctag.blue, html.office.blue .chev-in, html.office.blue .py-edit { color: var(--amber2); }
html.office.blue .rc-thumb:hover { border-color: var(--amber2); }

/* ── A job's page, for the office. A head: the job and the customer, and across from them who has it, who booked
   it and when it is. The job's status, a line of steps. Then two columns. The wide one: the job (what and where,
   the plumber and the time, who approves and pays, what the plumber sent in) and under it the estimate. The
   narrow one: the office's own notes, and what was sent for materials.
   A card's parts are set apart by a line, and a card open for a change is edged in the accent. What only explains
   is behind an "i". Narrower than a desk the columns stack, and the page scrolls like any other. ── */
html.office .screen.office.jobpage { padding: 16px 24px 24px; gap: 14px; }
.jobpage > * { flex: none; }
.jhead { display: flex; align-items: flex-start; flex-wrap: wrap; gap: 10px 16px; }
.jhead .jwho { flex: 1 1 480px; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.jneed { display: flex; align-items: center; gap: 4px; margin-top: 4px; }
html.office .jhead h1 { font-size: 24px; line-height: 1.2; }
.jcust { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px; margin-top: 2px; font-size: 13.5px; color: var(--muted); }
.jcust > b { font-weight: 500; color: var(--ink); }
.jcust > i { font-style: normal; color: var(--faint); }
.jcust > a { color: var(--mid); text-decoration: underline; text-underline-offset: 2px; }
.jcust > a:hover { color: var(--amber2); }
.jcust .none { color: var(--faint); }
.jlinks { flex: none; display: inline-flex; gap: 6px; }
.jcust .jlinks { margin-left: 6px; }
.jhead .jmeta { display: flex; flex-direction: column; align-items: flex-end; gap: 10px; margin-left: auto; padding-top: 18px; }
.jchips, .jhead .jacts { display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 8px; }
.jhead .jacts .eyebrow { margin-right: 4px; }
html.office .jhead .btn.danger { border-color: var(--red); color: var(--red); }
html.office .jhead .btn.danger:hover { background: rgba(239, 68, 68, .1); }
html.office .attn-links .btn.danger { border-color: var(--red); color: var(--red); }
html.office .attn-links .btn.danger:hover { background: rgba(239, 68, 68, .1); }
/* Who has the job and who booked it: a pill each, their initials in their own colour (the plumbers', the dispatchers'). */
.jchip { display: inline-flex; align-items: center; gap: 8px; height: 30px; padding: 0 11px; border: 1px solid var(--line); border-radius: 999px; background: var(--card); font-size: 13px; color: var(--dim); white-space: nowrap; }
.jchip:has(> i) { padding-left: 4px; }
.jchip > i { display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; background: var(--raised); background: color-mix(in srgb, var(--acc) 18%, var(--card)); color: var(--acc); font: 600 10px var(--body); }
.jchip > i svg { width: 12px; height: 12px; }
.jchip > b { font-weight: 500; color: var(--ink); }
.jchip.plumber { --acc: var(--amber2); }
.jchip.disp { --acc: var(--blue); }
.jchip .flash { margin-right: 0; }
/* A card, and its parts. */
html.office .jcard { min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 16px 18px; background: var(--card); border: 1px solid var(--line); border-radius: 10px; }
html.office .jcard.editing { border-color: var(--amber); box-shadow: 0 0 0 1px var(--amber); }
html.office .jcard.need { border-color: var(--red); box-shadow: 0 0 0 1px var(--red); }
/* A job with no plumber: the plumber box is ringed in red. */
html.office .jf.need { margin: -8px; padding: 8px; border: 1px solid var(--red); border-radius: 8px; box-shadow: 0 0 0 1px var(--red); }
.jsec { min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.jsec + .jsec { padding-top: 14px; border-top: 1px solid var(--line1); }
.jmain { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 16px; }
.jcol { flex: 999 1 560px; min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.jside { flex: 1 1 380px; min-width: 0; display: flex; flex-direction: column; gap: 16px; }
/* The job's status: its stage in GHL, and its steps in a line. A dot and a word a step, and when it happened. Done is
   green, the step the job is waiting on is lit, one that needs a person is gold, one this job skips is struck out. */
html.office .jcard.jstatus { gap: 10px; padding: 14px 18px; }
html.office .jcard.jstatus.off { border-color: rgba(239, 68, 68, .4); background: color-mix(in srgb, var(--red) 4%, var(--card)); }
.jstatus .cardhead { min-height: 22px; }
.jstage { display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 9px; border: 1px solid var(--line3); border: 1px solid color-mix(in srgb, var(--c) 45%, transparent); border-radius: 999px; background: color-mix(in srgb, var(--c) 12%, transparent); color: var(--c); font-size: 12px; font-weight: 500; white-space: nowrap; }
.jstage svg { width: 10px; height: 10px; }
.jline { display: flex; align-items: center; margin: 0; padding: 5px 4px; list-style: none; overflow-x: auto; font-size: 13px; }
.jline li { flex: 1 1 0; display: flex; align-items: center; gap: 8px; white-space: nowrap; color: var(--dim); }
.jline li:last-child { flex: 0 0 auto; }
.jline li > i { flex: none; box-sizing: border-box; width: 12px; height: 12px; border: 2px solid var(--line3); border-radius: 50%; }
.jline li > .min { display: flex; flex-direction: column; gap: 1px; }
.jline li b { font-weight: 400; }
.jline li em { font: 10px var(--mono); color: var(--dim); }
.jline li > u { flex: 1; min-width: 14px; height: 1px; margin: 0 10px; background: var(--line); }
.jline li:last-child > u { display: none; }
.jline li.done { color: var(--ink); }
.jline li.done > i { border-color: var(--green); background: var(--green); }
.jline li.done > u { background: color-mix(in srgb, var(--green) 40%, var(--line)); }
.jline li.now { color: #fff; }
.jline li.now b { font-weight: 600; }
.jline li.now > i { border-color: var(--amber); background: var(--amber); box-shadow: 0 0 0 3px color-mix(in srgb, var(--amber) 30%, transparent); }
.jline li.bad { color: var(--gold); }
.jline li.bad > i { border-color: var(--gold); background: var(--gold); }
.jline li.skip { opacity: .4; }
.jline li.skip > i { border-style: dashed; }
.jline li.skip b { text-decoration: line-through; }
.jline li.skip > u, .jline li.x > u { height: 0; border-top: 1px dashed var(--line3); background: none; }
/* A job called off: what had happened in grey, the step it was waiting on, and the X where it stopped. */
.jline li.was, .jline li.at { color: var(--muted); }
.jline li.was > i { border-color: var(--faint); background: var(--faint); }
.jline li.was > u, .jline li.at > u { background: var(--line3); }
.jline li.x { color: #FCA5A5; }
.jline li.x b { font-weight: 600; }
.jline li.x > i { display: grid; place-items: center; width: 20px; height: 20px; border: 1.5px solid var(--red); background: rgba(239, 68, 68, .16); box-shadow: 0 0 0 4px rgba(239, 68, 68, .1); }
.jline li.x > i svg { width: 8px; height: 8px; }
/* Under the steps: what a step has to say for itself, and what happened that is no step. */
.jnotes { display: flex; flex-direction: column; gap: 5px; padding-top: 10px; border-top: 1px solid var(--line1); }
.jnote { display: flex; align-items: baseline; gap: 9px; font-size: 13px; color: var(--muted); }
.jnote > i { flex: none; width: 7px; height: 7px; border: 1px solid var(--faint); border-radius: 50%; }
.jnote.ok { color: var(--ink); }
.jnote.ok > i { background: var(--green); border-color: var(--green); }
.jnote.bad { color: var(--gold); }
.jnote.bad > i { background: var(--gold); border-color: var(--gold); }
.jnote .hint { margin-left: 8px; }
.jnote .when { flex: none; margin-left: auto; font: 11px var(--mono); color: var(--dim); }
/* A field: a small name over a box. What is saved lies in the same box as what is typed, three or two to a row. */
.jfields { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.jfields.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.jfields .full { grid-column: 1 / -1; }
.jfields .span2 { grid-column: span 2; }
.jf { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.jlabel { font-size: 11px; color: var(--dim); }
html.office .jobpage .in, html.office .jobpage textarea, .jbox { box-sizing: border-box; min-height: 36px; padding: 7px 10px; background: var(--panel); border: 1px solid var(--line); border-radius: 7px; font-size: 13.5px; line-height: 1.4; }
html.office .jobpage .in[readonly] { color: var(--ink); cursor: default; }
html.office .jobpage textarea { resize: vertical; }
.jbox { display: flex; align-items: center; min-width: 0; color: var(--ink); }
.jbox.mono { font-family: var(--mono); }
.jbox.none { color: var(--faint); }
/* Someone's words (the notes, the scope of work, the report): the rest of a long one a scroll away inside its box. */
.said { box-sizing: border-box; min-height: 72px; max-height: 260px; overflow-y: auto; padding: 8px 10px; background: var(--panel); border: 1px solid var(--line); border-radius: 7px; font-size: 13.5px; line-height: 1.4; color: var(--ink); white-space: pre-wrap; }
.said.mid { min-height: 140px; }
.said.tall { min-height: 160px; }
.said.none { color: var(--faint); }
/* The pieces every office screen shares, at this page's size; rows lie flat on the card, a hairline between them. */
html.office .jobpage .btn { padding: 8px 14px; font-size: 13px; }
html.office .jobpage .btn.sm { padding: 6px 12px; border-radius: 7px; font-size: 12.5px; }
html.office .jhead .btn.sm { padding: 5px 10px; border-radius: 6px; font-size: 12px; }
html.office .jobpage .hint { font-size: 12px; line-height: 1.4; }
.jobpage .hint:empty { display: none; }
.acts.end { justify-content: flex-end; }
html.office .jobpage .card.rows { gap: 0; padding: 0; border: 0; border-radius: 0; background: none; }
html.office .jobpage .card.rows .row { min-height: 34px; gap: 10px; font-size: 13px; }
html.office .jobpage .card.rows .row.tall { gap: 10px; padding: 7px 0; }
html.office .jobpage .card.rows .row > :first-child { min-width: 0; }
html.office .jobpage .card.rows .row > :last-child:not(:first-child) { flex: none; max-width: 62%; text-align: right; }
html.office .jobpage .row .money { font-size: 13px; }
html.office .jobpage .row .money.big { font: 700 15px var(--mono); }
html.office .jobpage .money-in { min-height: 38px; }
html.office .jobpage .money-in .sym, html.office .jobpage .money-in input { font-size: 16px; }
html.office .jobpage .seg { gap: 6px; }
html.office .jobpage .seg .btn { padding: 7px 4px; font-size: 12.5px; }
.jobpage #senthow { flex-wrap: wrap; }
/* A heading with its "i" (or, across from it, when its part was saved). */
.lrow { display: flex; align-items: center; gap: 6px; min-height: 16px; }
.lrow.between { justify-content: space-between; }
.lrow .when { font: 11px var(--mono); color: var(--dim); }
/* The "i": what it explains shows in a box by it. */
.tip { flex: none; display: inline-block; width: 13px; height: 13px; margin-left: 5px; border: 1px solid var(--line3); border-radius: 50%; font: 600 9px/11px var(--body); letter-spacing: 0; text-align: center; text-transform: none; color: var(--dim); cursor: help; vertical-align: 1px; }
.lrow > .tip { margin-left: 0; }
.tip:hover, .tip:focus { border-color: var(--amber2); color: var(--amber2); outline: 0; }
.tipbox { position: fixed; z-index: 60; max-width: 300px; padding: 8px 10px; border: 1px solid var(--line3); border-radius: 7px; background: var(--raised); box-shadow: 0 8px 24px rgba(0, 0, 0, .45); font: 11.5px/1.45 var(--body); color: var(--mid); pointer-events: none; }
/* Who approves and pays: the payer, a line. */
.jpayer { display: flex; align-items: center; gap: 12px; padding: 10px 12px; background: var(--panel); border: 1px solid var(--line); border-radius: 9px; }
.jpayer > i { flex: none; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: var(--raised); color: var(--mid); font: 600 12px var(--body); }
.jpayer > i svg { width: 15px; height: 15px; }
.jpayer .who { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.jpayer .who b { font-size: 13.5px; font-weight: 500; color: var(--ink); }
.jpayer .who span { font-size: 12px; color: var(--dim); }
.jtag { flex: none; display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border: 1px solid var(--line); border-radius: 999px; background: var(--raised); color: var(--muted); font-size: 11px; white-space: nowrap; }
/* The payer, open for a change: GHL's contacts to pick from, the three boxes, and Cancel and Save across the foot. */
.jpick { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); overflow: hidden; }
.jpick > div { display: flex; flex-direction: column; align-items: stretch; gap: 8px; padding: 10px; }
.jpick > div + div { border-top: 1px solid var(--line1); }
.jpick > .jpick-foot { flex-direction: row; justify-content: flex-end; background: var(--bg); }
html.office .jpick .in, html.office .jpick .plist { background: var(--card); }
html.office .jpick .btn.chip { align-self: flex-start; }
/* The plumber's photos: a tile each for before, after and the receipt; the shots in it small. */
.jshots { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.jshot { box-sizing: border-box; min-height: 84px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; padding: 8px; border: 1px dashed var(--dash); border-radius: 8px; font-size: 11px; color: var(--faint); }
.jshot svg { width: 18px; height: 18px; }
.jshot b { font-size: 12px; font-weight: 400; color: var(--muted); }
.jshot.has { border-style: solid; border-color: var(--line); background: var(--panel); }
.jshot .thumbs { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; }
.jshot .thumbs a { display: block; width: 44px; height: 44px; border: 1px solid var(--line3); border-radius: 6px; overflow: hidden; }
.jshot .thumbs a:hover { border-color: var(--amber2); }
.jshot .thumbs img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* The plumber and when, open: a name over each of the three When boxes, and the month of days opening over what is under it. */
.whenlabels, html.office .jobpage .seg.when { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, .8fr); gap: 8px; }
.whenbox { position: relative; }
.whenbox .cal { position: absolute; z-index: 30; top: calc(100% + 4px); left: 0; right: 0; box-shadow: 0 10px 30px rgba(0, 0, 0, .5); }
.jobpage .calgrid button { min-height: 34px; }
html.office .jobpage .seg.when select.in { padding-left: 6px; padding-right: 2px; }
@media (max-width: 760px) {
  .jhead .jmeta { align-items: flex-start; margin-left: 0; padding-top: 0; }
  .jchips, .jhead .jacts { justify-content: flex-start; }
  .jfields, .jfields.two { grid-template-columns: minmax(0, 1fr); }
  .jfields .span2 { grid-column: auto; }
}

/* ── The Jobs list, after a Claude Design layout (Chris, 2026-10-05). The bar runs the width of the window; what is
   under it sits in from both edges (about a sixteenth of the window a side at a desk, never less than the other
   screens' 26px). A heading with the shop's time beside it, the search and New job at its right. Then one line of
   ways to narrow the table: All, Active and Closed as one switch, the pipeline's stages in a menu, the plumbers,
   and at the far right By day or All days. Then the week, and the jobs. ── */
@media (min-width: 561px) { html.office .screen.office.joblist { padding-left: max(26px, calc((100vw - max(1328px, 88vw)) / 2)); padding-right: max(26px, calc((100vw - max(1328px, 88vw)) / 2)); } }
.joblist #attn:empty { display: none; }
.joblist .attn { margin: 0; }
.jl-head { display: flex; align-items: center; justify-content: space-between; gap: 12px 20px; flex-wrap: wrap; }
.jl-title { display: flex; align-items: baseline; gap: 12px; }
html.office .jl-title h1 { font-size: 24px; }
.jl-find { flex: 1 1 320px; display: flex; align-items: center; justify-content: flex-end; gap: 14px; min-width: 0; }
.jl-find .search { flex: 0 1 374px; }
.jl-find .search span { display: grid; }
.jl-find .search svg { width: 14px; height: 14px; }
html.office .jl-find .btn.primary { gap: 7px; height: 36px; padding: 0 16px 0 13px; font-size: 13.5px; }
.jl-find .btn svg { width: 14px; height: 14px; }
.jl-bar { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.jl-bar .sep { flex: none; width: 1px; height: 20px; margin: 0 7px; background: var(--line); }
.jl-seg { display: flex; gap: 2px; padding: 3px; border: 1px solid var(--line); border-radius: 10px; }
.jl-bar .tab { height: 36px; gap: 8px; padding: 0 8px 0 14px; border-radius: 18px; font: 500 13px var(--body); }
.jl-bar .tab .n { min-width: 20px; padding: 0 6px; border-radius: 10px; background: var(--raised); font: 10.5px/20px var(--mono); }
.jl-bar .tab.on { background: var(--hover); background: color-mix(in srgb, var(--amber) 18%, transparent); border-color: var(--amber); color: var(--ink); font-weight: 600; }
.jl-bar .tab.on .n { background: var(--amber); color: var(--on-amber); }
.jl-bar .tab.alert { border-color: var(--red); color: #FCA5A5; }
.jl-bar .tab.alert .n { background: var(--red); color: #fff; }
.jl-seg .tab { height: 28px; padding: 0 5px 0 12px; border: 0; border-radius: 7px; }
.jl-seg .tab.on { background: var(--raised); }
/* The stages: a button that wears the stage picked, and its menu, a row a stage with its stops and its count */
.jl-stage { position: relative; }
.jl-bar .tab.drop { gap: 7px; padding: 0 11px 0 14px; border-radius: 10px; }
.jl-bar .tab.drop svg { width: 13px; height: 13px; color: var(--dim); }
.jl-menu { position: absolute; top: calc(100% + 6px); left: 0; z-index: 5; display: flex; flex-direction: column; min-width: 240px; padding: 5px; border: 1px solid var(--line3); border-radius: 10px; background: var(--card); box-shadow: 0 14px 34px rgba(0, 0, 0, .5); }
.jl-menu button { display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 10px; border: 0; border-radius: 6px; background: transparent; color: var(--mid); font: 13px var(--body); text-align: left; white-space: nowrap; }
.jl-menu button:hover, .jl-menu button:focus-visible { background: var(--hover); }
.jl-menu button.on { background: var(--raised); color: var(--ink); font-weight: 600; }
.jl-menu button.zero { color: var(--dim); }
.jl-menu .n { margin-left: auto; padding-left: 14px; font: 10.5px var(--mono); color: var(--dim); }
.jl-menu button.alert, .jl-menu button.alert .n { color: #FCA5A5; }
/* A narrow window: the bar's clock drops to a line of its own, and the search takes the width under the heading. */
@media (max-width: 760px) {
  .oside { flex-wrap: wrap; height: auto; min-height: 56px; gap: 8px 10px; padding: 9px 14px; }
  .oside .clockslot { order: 1; flex: 1 0 100%; justify-content: space-between; }
  .oside .me { margin-left: auto; }
  .jl-find { flex-basis: 100%; }
  .jl-find .search { flex: 1 1 auto; }
}
/* Book a job: the X top right (Save as draft or Delete) */
.bookhead { position: relative; padding-right: 150px; }
.bookacts { position: absolute; top: 0; right: 0; display: flex; gap: 8px; }
html.office .bookacts .btn.primary { height: 40px; padding: 0 18px; }
.techlist { flex-direction: column; }
html.office .techlist .btn { justify-content: flex-start; gap: 10px; padding: 11px 14px; }
.techlist .btn i { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.techlist .btn i.none { border: 1px dashed var(--muted); }
html.office .techlist .btn.on[data-tech=""] { background: var(--panel); border: 1px dashed var(--muted); color: var(--text, #fff); }
.xclose { width: 40px; height: 40px; display: grid; place-items: center; border-radius: 10px; border: 1px solid var(--line); background: var(--card); color: var(--muted); cursor: pointer; }
.xclose:hover { color: var(--text, inherit); border-color: var(--muted); }
.xclose svg { width: 14px; height: 14px; }
.ask .btn.danger { border-color: var(--red); color: var(--red); background: transparent; }

/* The internal notes card: its head in three parts, spread with even gaps, each on one line */
.cardhead.nhead { justify-content: space-between; }
.cardhead.nhead > * { white-space: nowrap; }
/* Images on the internal notes */
.nimgs { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 10px; }
.nimg { position: relative; display: block; width: 72px; height: 56px; }
.nimg a { display: block; width: 100%; height: 100%; border: 1px solid var(--line); border-radius: 7px; overflow: hidden; }
.nimg a:hover { border-color: var(--amber); }
.nimg img { display: block; width: 100%; height: 100%; object-fit: cover; }
.nimg .nx { position: absolute; top: -7px; right: -7px; width: 20px; height: 20px; display: grid; place-items: center; padding: 0; border-radius: 50%; border: 1px solid var(--line); background: var(--panel); color: var(--muted); font-size: 13px; line-height: 1; cursor: pointer; }
.nimg .nx:hover { color: var(--red); border-color: var(--red); }
html.office .nimgs .nadd { cursor: pointer; }

/* The web address's sign-in: a small card in the middle of the page, a desk's size as much as a phone's. */
.signin { height: 100%; display: grid; place-items: center; padding: 24px; overflow: auto; }
.signin form { width: 100%; max-width: 320px; display: grid; gap: 14px; padding: 28px; background: var(--card); border: 1px solid var(--line); border-radius: 10px; }
.signin h1 { margin: 0 0 4px; font: 600 18px var(--display); }
.signin label { display: grid; gap: 5px; font-size: 13px; color: var(--mid); }
.signin input:not([type=checkbox]) { height: 36px; padding: 0 10px; border: 1px solid var(--line); border-radius: 6px; background: var(--card); color: var(--ink); font: 16px var(--body); outline: none; }
.signin input:not([type=checkbox]):focus { border-color: var(--accent); }
.signin .rem { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.signin .rem input { width: 15px; height: 15px; margin: 0; accent-color: var(--accent); }
.signin button { height: 36px; border: 0; border-radius: 6px; background: var(--accent); color: #fff; font: 600 14px var(--body); cursor: pointer; }
.signin button:disabled { opacity: .6; }
.py-bonus { width: 100%; margin-top: 8px; }
