/* ==========================================================================
   Project Book: the look (slice 7). One stylesheet for every page.
   Brand: Tranquility Designs (clients/tranquilitydesigns/DESIGN.md):
   navy ink on paper, teal = money in / good, copper = money out / due,
   Fraunces for names and big numbers, DM Sans for everything else.
   Phone first (he opens it from a WhatsApp link); the laptop gets columns.
   The 2026-09-29 redesign (design/ux/UX.md, approved) is the last section:
   Today, the job page, the Fix something sheet, the client page, the chat.
   ========================================================================== */

@font-face {
  font-family: "Fraunces";
  src: url("/static/fonts/fraunces-latin.woff2") format("woff2");
  font-weight: 300 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "DM Sans";
  src: url("/static/fonts/dm-sans-latin.woff2") format("woff2");
  font-weight: 300 800; font-style: normal; font-display: swap;
}

:root {
  --navy: #1b2a4a;
  --ink-soft: #4b5878;
  --ink-faint: #7d879d;
  --paper: #f4f5f9;
  --paper-2: #e9ecf3;
  --card: #ffffff;
  --line: #e1e5ee;
  --teal: #43bd99;        /* bars, dots, fills */
  --teal-ink: #1d7e62;    /* teal text, readable on white */
  --teal-wash: #e3f5ee;
  --copper: #d38b59;
  --copper-ink: #9c5627;
  --copper-wash: #fbeee4;
  --radius: 16px;
  --shadow: 0 1px 2px rgba(27, 42, 74, .05), 0 4px 16px rgba(27, 42, 74, .05);
  --display: "Fraunces", "Iowan Old Style", Georgia, serif;
  --body: "DM Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--paper); color: var(--navy);
  font: 400 17px/1.5 var(--body);
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; }
input, select, textarea { font-family: var(--body); }
h1, h2, h3 { margin: 0; font-weight: 500; }
.num { font-variant-numeric: lining-nums tabular-nums; }

/* ---- top: the mark and nothing to manage (no nav: Today links to the rest) */
.top {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 20px 6px; max-width: 1060px; margin: 0 auto;
}
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; min-width: 0; }
.brand img { height: 34px; width: auto; display: block; }
.top .when { font-size: 15px; color: var(--ink-soft); }
.top .back { margin: 0; font-size: 16px; }
.vh { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.wrap { max-width: 1060px; margin: 0 auto; padding: 24px 20px 48px; }
.page-title { font: 500 34px/1.1 var(--display); letter-spacing: -.01em; }
.lede { color: var(--ink-soft); margin: 6px 0 0; }
.back { display: inline-flex; align-items: center; min-height: 44px; text-decoration: none; color: var(--ink-soft); font-weight: 600; margin-bottom: 14px; }

.card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 20px;
}
.label {
  font-size: 12px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-faint);
}
.section { margin-top: 28px; }
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.section-head h2 { font: 500 24px/1.2 var(--display); }

/* the stage: a small teal heading over the job's name, so it reads first (Michael picked it,
   2026-10-01: the grey bubble with a dot wrapped "Design & Engineering" onto two lines; the dot was
   teal on every job and meant nothing more). Teal ink on white is 5.0:1. */
.chip {
  display: block; margin: 0 0 6px;
  font: 700 12px/1.3 var(--body); letter-spacing: .08em; text-transform: uppercase; color: var(--teal-ink);
}

/* ---- jobs list ---------------------------------------------------------- */
.jobs { display: grid; gap: 16px; margin-top: 22px; }
.job-card { display: block; text-decoration: none; transition: border-color .15s, transform .15s; }
.job-card:hover { border-color: #c9cfdc; transform: translateY(-1px); }
.job-card h2 { font: 500 25px/1.2 var(--display); }
.job-card .who { color: var(--ink-soft); margin: 4px 0 12px; }
/* the finished jobs (Closed, nothing owed), folded under the rest: a native <details> */
.jobs-done { margin-top: 28px; }
.jobs-done > summary {
  display: inline-flex; align-items: center; gap: 10px; min-height: 44px; padding: 0 4px;
  list-style: none; cursor: pointer; font-weight: 700; font-size: 17px; color: var(--ink-soft); border-radius: 10px;
}
.jobs-done > summary::-webkit-details-marker { display: none; }
.jobs-done > summary::before {
  content: ""; width: 8px; height: 8px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(-45deg); transition: transform .15s;
}
.jobs-done[open] > summary::before { transform: rotate(45deg); }
.jobs-done > summary:hover { color: var(--navy); }
.jobs-done > summary:focus-visible { outline: 2px solid var(--teal-ink); outline-offset: 2px; }
.jobs-done > .jobs { margin-top: 12px; }
.trio { display: grid; grid-template-columns: 1fr 1fr 1.2fr; gap: 8px; margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line); }
.trio div { min-width: 0; }
.trio .in, .trio .out, .trio .profit { display: block; font: 500 20px/1.2 var(--display); margin-top: 2px; font-variant-numeric: lining-nums tabular-nums; overflow-wrap: anywhere; }
.trio .in { color: var(--teal-ink); }
.trio .out { color: var(--copper-ink); }
.trio .profit { font-size: 23px; font-weight: 600; }
@media (min-width: 760px) { .trio .in, .trio .out { font-size: 24px; } .trio .profit { font-size: 28px; } }
.next-due { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-top: 14px; }
.next-due .next { text-align: right; }
.next-due .next b { font: 500 18px/1.2 var(--display); color: var(--teal-ink); font-variant-numeric: lining-nums tabular-nums; }
.next-due .sub { display: block; font-size: 13px; color: var(--ink-soft); }
.next-due.none .label { color: var(--ink-faint); }
.next-due.is-late .next b, .next-due .sub.late { color: var(--copper-ink); }   /* late as Today says it */
.next-due .sub.late { font-weight: 600; }
.totals { margin-top: 22px; }
.totals .trio { margin-top: 10px; padding-top: 10px; }
.totals .t-in, .totals .t-out, .totals .t-profit, .totals .t-give, .totals .t-after { display: block; font: 500 20px/1.2 var(--display); margin-top: 2px; font-variant-numeric: lining-nums tabular-nums; overflow-wrap: anywhere; }
.totals .t-in { color: var(--teal-ink); }
.totals .t-out { color: var(--copper-ink); }
.totals .t-profit { font-weight: 600; }

/* the year-end spreadsheet (app/export.asm): plain words and two links, no card */
.export { margin-top: 26px; }
.export .sub { color: var(--ink-soft); margin: 6px 0 0; font-size: 15px; }
.export .links { display: flex; flex-wrap: wrap; gap: 10px; margin: 12px 0 0; }

/* ---- job page ----------------------------------------------------------- */
.job-head .client { font-size: 18px; margin: 8px 0 0; }
.facts { display: flex; flex-wrap: wrap; gap: 6px 18px; margin: 10px 0 0; padding: 0; list-style: none; color: var(--ink-soft); font-size: 15px; }
.facts li { white-space: nowrap; }
.facts b { font-weight: 600; color: var(--navy); }

.stage-card { margin-top: 20px; }
.stage-now { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.stage-now strong { display: block; font: 500 26px/1.2 var(--display); margin-top: 2px; }
/* phone: a short vertical timeline; laptop: one row */
.steps { margin: 16px 0 0; padding: 12px 16px; list-style: none; }
.steps li { position: relative; padding: 3px 0 3px 22px; font-size: 15px; color: var(--ink-faint); }
.steps li::before { content: ""; position: absolute; left: 3px; top: 11px; width: 9px; height: 9px; border-radius: 50%; background: var(--paper-2); border: 2px solid #c9cfdc; }
.steps li.done, .steps li.current { color: var(--navy); }
.steps li.done::before { background: var(--teal); border-color: var(--teal); }
.steps li.current { font-weight: 700; }
.steps li.current::before { background: var(--navy); border-color: var(--navy); }
.steps .when { display: block; }
.steps .when, .row-main .due { font-size: 13px; font-weight: 400; color: var(--ink-soft); }

/* the money block (design/MONEY-BLOCK.md): profit is the headline, one bar is
   the money that came in, copper = what went out, teal = what he keeps */
.keep { margin-top: 22px; }
.keep .kicker { font-size: 16px; color: var(--ink-soft); }
.keep .hero { display: block; font: 500 64px/1 var(--display); letter-spacing: -.02em; font-variant-numeric: lining-nums tabular-nums; margin-top: 6px; color: var(--navy); }
.keep .bar { display: flex; height: 14px; border-radius: 7px; overflow: hidden; margin: 22px 0 12px; background: var(--paper-2); }
.keep .bar .b-out { background: var(--copper); }
.keep .bar .b-keep { background: var(--teal); }
.keep .legend { display: flex; justify-content: space-between; gap: 12px; font-size: 16px; color: var(--ink-soft); }
.keep .legend b { font: 500 22px/1.2 var(--display); color: var(--navy); font-variant-numeric: lining-nums tabular-nums; display: block; }
.keep .legend .r { text-align: right; }
.keep .legend .dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 6px; vertical-align: 1px; background: var(--copper); }
.keep.is-loss .kicker, .keep.is-loss .hero { color: var(--copper-ink); }

/* rows: a line ABOVE every visible row except the first of its own side, so a
   hidden row (the other side of the inst loop) never leaves a stray line, and
   the list does not clip (the correction forms open as a card over the page) */
.rows { list-style: none; margin: 0; padding: 0 18px; }
.rows li {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 14px;
  padding: 16px 0;
}
.list-in .side-in ~ .side-in, .list-out .side-out ~ .side-out, .list-out .rem ~ .rem, #notes li ~ li { border-top: 1px solid var(--line); }
.list-out li { grid-template-columns: 1fr auto; }
.list-in .side-out, .list-out .side-in { display: none; }
.seq {
  width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center;
  background: var(--paper-2); font-weight: 700; font-size: 15px;
}
.row-main { min-width: 0; }
.row-main .amt { font: 500 22px/1.2 var(--display); font-variant-numeric: lining-nums tabular-nums; }
.row-main .sub { font-size: 14px; color: var(--ink-soft); }
.row-main .who { font-weight: 600; font-size: 18px; }
.row-main .sub { margin-top: 4px; }
.out-amt { font: 500 22px/1.2 var(--display); font-variant-numeric: lining-nums tabular-nums; color: var(--copper-ink); margin-right: 4px; }
.paid-amt { display: none; }
.rows li:has(.st-partial) .paid-amt { display: inline; }
.row-acts { display: flex; align-items: center; gap: 8px; }

.pill { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 13px; font-weight: 700; text-transform: capitalize; }
.st-paid { background: var(--teal-wash); color: var(--teal-ink); }
.st-open { background: var(--copper-wash); color: var(--copper-ink); }
.st-partial { background: var(--copper-wash); color: var(--copper-ink); }
.st-void { background: var(--paper-2); color: var(--ink-faint); text-decoration: line-through; }
/* the invoice button only makes sense on a payment still to come */
.list-in li:has(.st-paid) .btn-invoice, .list-in li:has(.st-void) .btn-invoice { display: none; }
.inline-form { display: inline; margin: 0; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 44px; padding: 0 16px; border-radius: 12px; border: 1px solid var(--line);
  background: var(--card); color: var(--navy); font: 600 15px/1 var(--body);
  text-decoration: none; cursor: pointer;
}
.btn-primary { background: var(--navy); border-color: var(--navy); color: #fff; }
/* a button that takes something away (Cancel the job, Delete the job): outlined copper, never the
   filled navy of Save, so a thumb that means "Save" cannot land on it by habit */
.btn-danger { background: var(--card); border: 2px solid var(--copper-ink); color: var(--copper-ink); }
.btn-danger:hover, .btn-danger:focus-visible { background: var(--copper-wash); }
.btn-icon { width: 44px; padding: 0; }
.btn svg { width: 18px; height: 18px; }

.two { display: grid; gap: 0 20px; }
.empty { margin: 0; color: var(--ink-soft); }
.row-main .sub .job-link { color: var(--ink-soft); }
.actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 28px; }

/* ---- not wired yet: shown, dashed, and says what it needs --------------- */
.soon { border-style: dashed !important; border-color: #b9c0d0 !important; }
.btn.soon { background: transparent; color: var(--ink-soft); cursor: not-allowed; }
.ph {
  border: 1.5px dashed #b9c0d0; border-radius: 12px; padding: 14px 16px;
  color: var(--ink-soft); font-size: 15px; background: rgba(255,255,255,.5);
}
.ph .needs { display: block; margin-top: 6px; font-size: 12px; color: var(--ink-faint); font-family: ui-monospace, "JetBrains Mono", monospace; }
.tag-soon {
  display: inline-block; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-faint); border: 1px dashed #b9c0d0; border-radius: 6px; padding: 1px 6px;
}

.draft {
  margin: 28px auto 0; max-width: 1060px; padding: 0 20px 28px;
  font-size: 13px; color: var(--ink-faint); text-align: center;
}

/* ---- login -------------------------------------------------------------- */
.login { min-height: 100vh; display: grid; place-items: center; padding: 28px 20px; }
.login-box { width: 100%; max-width: 400px; }
.login-logo { display: block; width: 240px; max-width: 70%; height: auto; margin: 0 auto 28px; }
.login h1 { font: 500 30px/1.15 var(--display); text-align: center; }
.login .lede { text-align: center; margin-bottom: 22px; }
.field { display: block; margin-bottom: 16px; }
.field span { display: block; font-weight: 600; font-size: 15px; margin-bottom: 6px; }
.field input, .composer input {
  width: 100%; min-height: 52px; padding: 0 16px; border-radius: 12px;
  border: 1px solid #cfd5e2; background: #fff; color: var(--navy); font: 400 18px var(--body);
}
/* a checkbox in a field (Settings: Zelle, Check, Card) is a box beside its word, not a
   full-width input: the rule above drew it 300 px wide on its own line (2026-09-30) */
.field textarea { width: 100%; min-height: 84px; padding: 12px 16px; border-radius: 12px; border: 1px solid #cfd5e2; background: #fff; font: 400 16px var(--body); color: var(--navy); resize: vertical; }
.field textarea:focus { outline: 3px solid rgba(67, 189, 153, .35); border-color: var(--teal); }
.note-box { margin-bottom: 8px; }
.field input[type=checkbox] { width: 24px; height: 24px; min-height: 0; padding: 0; margin: 0; flex: none; accent-color: var(--teal); }
.field span:has(> input[type=checkbox]) { display: flex; align-items: center; gap: 12px; min-height: 44px; margin: 0; font-size: 17px; }
.field input:focus, .composer input:focus { outline: 3px solid rgba(67, 189, 153, .35); border-color: var(--teal); }
.login .btn { width: 100%; min-height: 54px; font-size: 17px; margin-top: 6px; }
.error {
  background: var(--copper-wash); color: var(--copper-ink); border-radius: 12px;
  padding: 12px 16px; font-weight: 600; margin-bottom: 16px;
}

/* ---- the test chat (a WhatsApp stand-in) -------------------------------- */
.chat-page { background: var(--paper-2); }
.chat-layout { max-width: 1060px; margin: 0 auto; display: grid; gap: 20px; }
.chat {
  display: flex; flex-direction: column; min-height: calc(100vh - 55px);
  background: var(--paper-2);
}
.chat-head {
  display: flex; align-items: center; gap: 12px; padding: 12px 16px;
  background: var(--navy); color: #fff;
}
.avatar {
  width: 42px; height: 42px; border-radius: 50%; background: #fff;
  display: grid; place-items: center; flex: none;
}
.avatar img { width: 32px; height: auto; }
.chat-head strong { display: block; font-size: 17px; }
.chat-head small { color: #aeb8cf; font-size: 13px; }
.transcript { flex: 1; padding: 18px 14px 8px; display: flex; flex-direction: column; gap: 8px; }
.day {
  align-self: center; background: rgba(255,255,255,.8); color: var(--ink-soft);
  font-size: 13px; padding: 4px 12px; border-radius: 8px; margin-bottom: 6px; text-align: center; max-width: 90%;
}
.msg {
  margin: 0; max-width: 82%; padding: 9px 13px 10px; border-radius: 16px; font-size: 17px; line-height: 1.4;
  white-space: pre-line; overflow-wrap: anywhere; box-shadow: 0 1px 1px rgba(27,42,74,.08);
}
.msg.in { align-self: flex-end; background: #d6f1e6; border-bottom-right-radius: 5px; }
.msg.out { align-self: flex-start; background: #fff; border-bottom-left-radius: 5px; }
.msg.in + .msg.out, .msg.out + .msg.in { margin-top: 6px; }
/* an invoice the book made: the PDF he forwards */
.msg-file { display: block; margin-top: 8px; font-weight: 700; color: var(--teal-ink); text-decoration: none; }
.msg-file::before { content: "PDF  "; font-size: 12px; letter-spacing: .06em; color: var(--copper-ink); }
/* a voice note rides ABOVE the text it speaks: one bubble with the player in it */
.msg.voice { display: flex; flex-direction: column; gap: 6px; width: min(82%, 360px); padding: 8px 10px 10px; }
.msg.voice + .msg.out { margin-top: -2px; }
.voice-cap { color: var(--ink-soft); font-size: 13px; }
.msg.voice audio { width: 100%; height: 40px; }
.composer {
  position: sticky; bottom: 0; display: flex; gap: 8px; align-items: center;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom)); background: var(--paper-2);
}
.composer input { border-radius: 999px; min-height: 50px; border-color: #d3d8e4; }
.send {
  flex: none; width: 50px; height: 50px; border-radius: 50%; border: 0;
  background: var(--teal); color: #fff; display: grid; place-items: center; cursor: pointer;
}
.send svg { width: 22px; height: 22px; }
/* Undo is the LAST button in the source (Enter must press Send) and the FIRST on screen */
.undo {
  order: -1; flex: none; width: 50px; height: 50px; border-radius: 50%;
  border: 1px solid #d3d8e4; background: transparent; color: var(--ink-soft);
  display: grid; place-items: center; cursor: pointer;
}
.undo svg { width: 22px; height: 22px; }
.undo:hover, .undo:focus-visible { background: #fff; color: var(--navy); }

.panel { padding: 0 14px 28px; }
.panel details { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); }
.panel summary { cursor: pointer; padding: 14px 16px; font-weight: 700; list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.panel summary::-webkit-details-marker { display: none; }
.panel dl { margin: 0; padding: 0 16px 14px; display: grid; grid-template-columns: auto 1fr; gap: 8px 16px; font-size: 15px; }
.panel dt { color: var(--ink-faint); }
.panel dd { margin: 0; font-weight: 600; overflow-wrap: anywhere; }
.panel .hint { padding: 0 16px 16px; margin: 0; font-size: 13px; color: var(--ink-faint); }

/* ---- laptop ------------------------------------------------------------- */
@media (min-width: 760px) {
  .top { padding: 18px 32px 6px; }
  .wrap { padding: 36px 32px 56px; }
  .draft { padding: 0 32px 28px; }
  .page-title { font-size: 44px; }
  .jobs { grid-template-columns: 1fr 1fr; gap: 20px; }
  .job-card { padding: 24px; }
  .job-head h1 { font-size: 48px; }
  .two { grid-template-columns: 1fr 1fr; }
  .steps { display: flex; gap: 6px; padding: 14px 16px; }
  .steps li { flex: 1 1 0; padding: 12px 0 0; font-size: 13px; border-top: 4px solid var(--paper-2); }
  .steps li::before { display: none; }
  .chat-layout { grid-template-columns: minmax(0, 1fr) 320px; padding: 24px 32px; align-items: start; }
  .chat { min-height: calc(100vh - 110px); border-radius: var(--radius); overflow: hidden; border: 1px solid var(--line); background: #e7eaf1; }
  .chat-page { background: var(--paper); }
  .composer { background: #e7eaf1; }
  .panel { padding: 0; position: sticky; top: 90px; }
  .transcript { padding: 24px 28px 10px; }
  .msg { max-width: 70%; }
}

/* ---- the job page's edit forms (app/edit.asm): a <details> per form, the
   form opening as a card under its button; no JavaScript ----------------- */
.edit { position: relative; }
.edit > summary { list-style: none; }
.edit > summary::-webkit-details-marker { display: none; }
.edit-form { margin-top: 10px; padding: 18px; max-width: 460px; }
.row-edit .edit-form { position: absolute; right: 0; top: 50px; z-index: 5; width: 320px; box-shadow: 0 12px 32px rgba(20, 30, 60, .16); }
.edit-form .field select {
  width: 100%; min-height: 52px; padding: 0 12px; border-radius: 12px;
  border: 1px solid #cfd5e2; background: #fff; color: var(--navy); font: 400 18px var(--body);
}
.edit-form .btn { width: 100%; }
.job-head .edit { margin-top: 14px; }

/* the job page's client link: a 32-character token wraps on a phone */
#client-link{overflow-wrap:anywhere;word-break:break-all}

/* ==========================================================================
   The redesign (design/ux/UX.md, 2026-09-29, approved). Built from the
   mocks' mock.css: sections are a plain word in Fraunces, lists are white
   rounded cards, teal only means paid/kept, copper only due/late/out. No
   pills, no side borders, no uppercase labels, no stat cards.
   ========================================================================== */
.p-today .wrap, .p-job .wrap, .p-client .wrap { max-width: 640px; padding: 8px 20px 120px; }
.p-today h1, .p-job h1, .p-client h1 { font: 500 34px/1.1 var(--display); letter-spacing: -.01em; margin: 6px 0 0; }
.sec { margin-top: 34px; }
.sec > h2 { font: 500 23px/1.2 var(--display); margin: 0 0 12px; }
.sec > h2 .sum { float: right; font-variant-numeric: lining-nums tabular-nums; }
.tot { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin: 0 0 12px; }
.tot h2 { font: 500 23px/1.2 var(--display); margin: 0; }
.big { font: 500 30px/1 var(--display); letter-spacing: -.02em; font-variant-numeric: lining-nums tabular-nums; }

/* "needs you": one sentence, at most two buttons */
.need { background: var(--card); border-radius: 18px; padding: 18px; box-shadow: var(--shadow); }
.need + .need { margin-top: 12px; }
.need p { margin: 0; font-size: 18px; line-height: 1.4; }
.need p b { font-weight: 600; }
.need .go { margin-top: 14px; display: flex; gap: 10px; flex-wrap: wrap; }
.need .go form { margin: 0; }
.p-today .btn, .p-job .btn, .p-client .btn { min-height: 48px; padding: 0 18px; border-radius: 14px; font-size: 16px; }
.btn-wide { width: 100%; min-height: 56px !important; font-size: 17px !important; }

/* a money list: who, when, amount */
.list { background: var(--card); border-radius: 18px; padding: 2px 18px; box-shadow: var(--shadow); list-style: none; margin: 0; }
.list > li { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 15px 0; }
.list > li + li { border-top: 1px solid var(--line); }
.list .who { font-weight: 600; font-size: 17px; }
.list .sub { font-size: 15px; color: var(--ink-soft); margin-top: 1px; }
.hist .sub::first-letter { text-transform: uppercase; }
.list .late { color: var(--copper-ink); font-weight: 600; }
.list .amt { font: 500 23px/1.1 var(--display); white-space: nowrap; font-variant-numeric: lining-nums tabular-nums; }
.list a.row { display: flex; align-items: center; justify-content: space-between; gap: 14px; width: 100%; text-decoration: none; }
.list .r { text-align: right; }
.jobs-t .who { font: 500 20px/1.2 var(--display); }
.jobs-t .amt { font-size: 21px; color: var(--teal-ink); }
.jobs-t .amt.minus { color: var(--copper-ink); }
.month p { margin: 0; font-size: 18px; line-height: 1.5; }
.month b { font-weight: 600; }
.month .kept { color: var(--teal-ink); }
.month .over { color: var(--copper-ink); }
.month a { display: inline-block; margin-top: 12px; font-weight: 600; font-size: 16px; text-underline-offset: 4px; }
.quiet { text-align: center; margin-top: 30px; font-size: 15px; color: var(--ink-soft); }
.quiet a { display: inline-flex; align-items: center; min-height: 44px; color: var(--ink-soft); font-weight: 600; text-underline-offset: 4px; }
.quiet form { display: inline; margin: 0; }
.quiet button { min-height: 44px; background: none; border: 0; padding: 0; font: inherit; font-weight: 600; color: var(--ink-soft); text-decoration: underline; text-underline-offset: 4px; cursor: pointer; }

/* the one thumb button, always at the bottom */
.dock { position: fixed; left: 0; right: 0; bottom: 0; padding: 12px 20px calc(22px + env(safe-area-inset-bottom)); background: linear-gradient(rgba(244,245,249,0), var(--paper) 35%); z-index: 20; }
.dock .btn { display: flex; width: 100%; max-width: 600px; margin: 0 auto; min-height: 58px; font-size: 18px; border-radius: 16px; background: var(--card); color: var(--navy); border: 1.5px solid var(--navy); box-shadow: 0 6px 20px rgba(27,42,74,.12); }
.dock .btn svg { width: 20px; height: 20px; }

/* ---- the job page ---- */
.p-job .facts { display: block; color: var(--ink-soft); font-size: 16px; margin: 8px 0 0; }
.p-job #job-facts > span + span::before { content: " · "; }
.fixrows .sub > .pd:not(:first-child)::before { content: " · "; }   /* "$0 paid" leads with no dot when the row has no day (2026-09-30) */   /* a dot only BETWEEN facts: none leads when the kind is empty */
.stage { margin-top: 18px; }
.stage .now { font-size: 17px; }
.stage .now b { font-weight: 600; }
.dots { display: flex; gap: 6px; margin: 10px 0 0; padding: 0; list-style: none; }
.dots i, .dots li { flex: 1; height: 6px; border-radius: 3px; background: var(--paper-2); }
.dots i.done, .dots li.done { background: var(--teal); }
.dots i.current, .dots li.current { background: var(--navy); }
.stage .next { font-size: 15px; color: var(--ink-soft); margin-top: 8px; }
.keep { margin-top: 26px; }
.hist .amt { font-size: 20px; }
.hist .plus { color: var(--teal-ink); }
.hist .minus { color: var(--copper-ink); }
.coming li { flex-wrap: wrap; }
.coming .go { flex-basis: 100%; margin: 10px 0 0; }
.coming .go .btn { min-height: 44px; font-size: 15px; }
.note { background: var(--card); border-radius: 18px; padding: 16px 18px; box-shadow: var(--shadow); list-style: none; }
.note + .note { margin-top: 10px; }
.notes { margin: 0; padding: 0; }
.note p { margin: 0; font-size: 17px; }
.note .sub { font-size: 14px; color: var(--ink-soft); margin-top: 4px; }
.share { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.share p { margin: 0; font-size: 16px; color: var(--ink-soft); }
.share p b { color: var(--navy); font-weight: 600; display: block; font-size: 17px; }
.share form { margin: 0; }
.share .btn { flex: none; white-space: nowrap; }   /* "Send link" on one line beside a long description */
.fixlink { display: flex; align-items: center; justify-content: center; width: fit-content; min-height: 44px; margin: 36px auto 0; font-weight: 600; font-size: 17px; color: var(--navy); text-underline-offset: 5px; }
.fixhint { text-align: center; color: var(--ink-faint); font-size: 14px; margin: 6px 0 0; }

/* ---- Fix something: a bottom sheet per step, opened by its #id (no JS) ---- */
.sheet-wrap { display: none; position: fixed; inset: 0; z-index: 40; }
.sheet-wrap:target { display: block; }
.sheet-wrap .dim { position: absolute; inset: 0; background: rgba(27,42,74,.45); }
.sheet { position: absolute; left: 0; right: 0; bottom: 0; max-width: 640px; margin: 0 auto; max-height: 92vh; overflow-y: auto; background: var(--paper); border-radius: 24px 24px 0 0; padding: 10px 20px calc(28px + env(safe-area-inset-bottom)); box-shadow: 0 -10px 40px rgba(27,42,74,.2); }
.grab { width: 44px; height: 5px; border-radius: 3px; background: #c9cfdc; margin: 0 auto 16px; }
.sheet h2 { font: 500 26px/1.15 var(--display); margin: 0; }
.sheet h3 { font: 500 20px/1.2 var(--display); margin: 26px 0 10px; }
.sheet .lede { font-size: 16px; }
.sheet .bk { font-weight: 600; color: var(--ink-soft); text-decoration: none; font-size: 16px; display: inline-block; margin-bottom: 10px; }
.opts { list-style: none; margin: 18px 0 0; padding: 2px 18px; background: var(--card); border-radius: 18px; }
.opts li + li { border-top: 1px solid var(--line); }
.opts a span span { display: inline; margin: 0; font-size: inherit; }
.opts a { display: flex; justify-content: space-between; align-items: center; padding: 16px 0; font-size: 18px; font-weight: 600; text-decoration: none; }
.opts a span { font-weight: 400; font-size: 15px; color: var(--ink-soft); display: block; margin-top: 2px; }
.opts svg { width: 20px; height: 20px; color: var(--ink-faint); flex: none; }
.undo-row { margin-top: 14px; display: flex; justify-content: space-between; align-items: center; gap: 12px; background: var(--card); border-radius: 18px; padding: 14px 18px; }
.undo-row p { margin: 0; font-size: 15px; color: var(--ink-soft); }
.undo-row p b { display: block; color: var(--navy); font-size: 17px; font-weight: 600; }
.undo-row form { margin: 0; }
.close { display: flex; align-items: center; justify-content: center; width: fit-content; min-height: 44px; margin: 18px auto 0; font-weight: 600; color: var(--ink-soft); text-decoration: none; }
/* big tappable rows: the chosen one outlined navy */
.pick { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 8px; }
.pick label { display: flex; justify-content: space-between; align-items: center; gap: 12px; background: var(--card); border: 1.5px solid var(--line); border-radius: 14px; padding: 12px 16px; cursor: pointer; }
.pick input { position: absolute; opacity: 0; pointer-events: none; }
.pick input:checked + label { border-color: var(--navy); box-shadow: 0 0 0 1px var(--navy) inset; }
.pick input:focus-visible + label { outline: 3px solid rgba(67,189,153,.35); }
.pick b { font-weight: 600; font-size: 17px; display: block; }
.pick span { font-size: 14px; color: var(--ink-soft); }
.pick .a { font: 500 21px/1 var(--display); color: var(--navy); font-variant-numeric: lining-nums tabular-nums; }
.pick .paid, .pick .paid-on { color: var(--teal-ink); }
.sheet .field input, .sheet .field select { min-height: 54px; font: 500 20px var(--body); font-variant-numeric: lining-nums tabular-nums; }
.sheet .field input[type=text]:not([inputmode]) , .sheet .field input[type=date] { font: 400 18px var(--body); }
.sheet form { margin: 0; }
.sheet .save { margin-top: 18px; }
.fixrows { list-style: none; margin: 0; padding: 2px 18px; background: var(--card); border-radius: 18px; }
.fixrows > li { padding: 14px 0; }
.fixrows > li + li { border-top: 1px solid var(--line); }
.fixrows .head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.fixrows .head b { font-weight: 600; }
.fixrows .head .a { font: 500 20px/1 var(--display); font-variant-numeric: lining-nums tabular-nums; }
.fixrows .sub { font-size: 14px; color: var(--ink-soft); margin-top: 2px; }
.fixrows .due { font-size: 14px; color: var(--ink-soft); }
.fixrows .paid-on { color: var(--teal-ink); }
.fixrows .acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.fixrows details > summary { list-style: none; display: inline-flex; }
.fixrows details > summary::-webkit-details-marker { display: none; }
.fixrows details[open] > summary { display: none; }
.fixrows details form { margin-top: 6px; }
.fixrows .btn { min-height: 42px !important; font-size: 15px !important; }
.fixrows .row2 { display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: end; }
.fixrows .row2 .field { margin: 0; }
.fixrows .row2 .field input { min-height: 46px; }

/* ---- the client page (design/ux/client.html): his logo, where it is, the one
   amount due now, the plan. Never "late", never his costs or profit. ---- */
.p-client .wrap { padding-bottom: 40px; }
.ctop { background: #fff; padding: 18px 20px 14px; display: flex; justify-content: center; border-bottom: 1px solid var(--line); }
.ctop img { width: 220px; max-width: 100%; height: auto; display: block; }
@media (max-width: 600px) { .ctop img { width: 180px; } }
.hi { font-size: 16px; color: var(--ink-soft); margin: 22px 0 0; }
.where { margin-top: 20px; }
.where .now { font: 500 26px/1.2 var(--display); }
.where .next { font-size: 16px; color: var(--ink-soft); margin-top: 8px; }
.duenow { margin-top: 28px; background: var(--card); border-radius: 20px; padding: 22px 20px 20px; box-shadow: 0 1px 2px rgba(27,42,74,.05), 0 6px 22px rgba(27,42,74,.07); }
.duenow .kicker { font-size: 16px; color: var(--ink-soft); display: block; }
.duenow .big { font-size: 56px; margin-top: 6px; display: block; }
.duenow .what { font-size: 16px; color: var(--ink-soft); margin: 8px 0 18px; }
.duenow form { margin: 0; }
.duenow .other { text-align: center; font-size: 14px; color: var(--ink-faint); margin: 12px 0 0; }
.plan .amt { font-size: 21px; }
.plan .paid-on { color: var(--teal-ink); }
.plan .sub { color: var(--ink-soft); }
.plan .sub:has(.paid-on) { color: var(--teal-ink); }
.plan form { margin: 4px 0 0; }
.linkbtn { background: none; border: 0; padding: 0; font: 600 14px var(--body); color: var(--navy); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.tot3 { display: flex; justify-content: space-between; gap: 8px; font-size: 16px; color: var(--ink-soft); margin-top: 12px; padding: 0 4px; }
.tot3 b { color: var(--navy); font-weight: 600; }
.tot3 .refunded { display: block; font-style: normal; font-size: 14px; color: var(--ink-faint); margin-top: 2px; }
.contact { text-align: center; margin-top: 34px; font-size: 16px; color: var(--ink-soft); }
.contact b { display: block; font-weight: 600; font-size: 18px; color: var(--navy); margin-top: 4px; }

/* ---- the chat (design/ux/chat.html): WhatsApp's own look, he never learns a
   new app; only the book's words are ours. The staff panel is off unless the
   process runs with CLX_PB_STAFF=1. ---- */
.wa, .wa .chat, .wa .composer { background: #efeae2; }
.wa .chat-layout { max-width: 760px; padding: 0; display: block; }
.wa .chat { min-height: 100vh; border: 0; border-radius: 0; }
.wa-head { position: sticky; top: 0; z-index: 3; display: flex; align-items: center; gap: 12px; padding: 10px 14px; background: #fff; border-bottom: 1px solid #e3e3e3; }
.wa-head .chev { font-size: 30px; line-height: 1; color: #111b21; text-decoration: none; display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; margin: 0 -12px 0 -14px; }   /* the way back: a 44 px target, not the 8 px glyph (2026-09-30) */
.wa-head .av { width: 40px; height: 40px; border-radius: 50%; background: var(--paper); display: grid; place-items: center; flex: none; }
.wa-head .av img { width: 30px; height: auto; }
.wa-head b { display: block; font-size: 17px; font-weight: 600; color: #111b21; }
.wa-head small { color: #667781; font-size: 13px; }
.wa .transcript { padding: 12px 10px 16px; gap: 6px; }
.wa .day { background: #fff; color: #54656f; font-size: 13px; padding: 5px 12px; border-radius: 8px; box-shadow: 0 1px 1px rgba(0,0,0,.06); }
.wa .msg { max-width: 84%; padding: 7px 10px 6px; border-radius: 10px; font-size: 16.5px; line-height: 1.38; color: #111b21; box-shadow: 0 1px 1px rgba(0,0,0,.08); }
.wa .msg.in { background: #d9fdd3; border-bottom-right-radius: 10px; }
.wa .msg.out { background: #fff; border-bottom-left-radius: 10px; }
.wa .msg .t { float: right; font-size: 11.5px; color: #667781; margin: 8px 0 -4px 10px; white-space: nowrap; }
.wa .msg-file { display: flex; align-items: center; gap: 10px; background: #f5f6f6; border-radius: 8px; padding: 10px; margin: 8px 0 2px; color: #111b21; font-weight: 600; font-size: 15px; white-space: normal; }
.wa .msg-file::before { content: none; }
.wa .msg-file .ic { width: 36px; height: 44px; border-radius: 4px; background: #e25141; color: #fff; font: 700 10px var(--body); display: grid; place-items: end center; padding-bottom: 5px; flex: none; }
.wa .composer { padding: 8px 8px calc(22px + env(safe-area-inset-bottom)); }
.wa .composer input { border: 0; min-height: 46px; border-radius: 24px; font-size: 16px; }
.wa .send { background: #1daa61; width: 48px; height: 48px; }
.wa .undo { width: 46px; height: 46px; background: #fff; border: 0; }
.wa .panel { max-width: 760px; margin: 16px auto; padding: 0 14px 28px; position: static; }
@media (min-width: 760px) { .wa .chat-layout { padding: 24px 0; } .wa .chat { min-height: calc(100vh - 48px); border-radius: 16px; overflow: hidden; } .wa .msg { max-width: 70%; } }

/* ---- the installed app (templates/_head.html, _install.html; static/pb-app.js):
   the notch and the home bar, the Home Screen guide, the chat's camera and mic ---- */
body { padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right); }
.top { padding-top: max(14px, env(safe-area-inset-top)); }
.wa-head { padding-top: max(10px, env(safe-area-inset-top)); }
.install { max-width: 1060px; margin: 8px auto 0; display: flex; gap: 12px; align-items: flex-start; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); padding: 14px 16px; margin-left: 20px; margin-right: 20px; }
.install[hidden] { display: none; }
.install img { width: 52px; height: 52px; border-radius: 12px; border: 1px solid var(--line); flex: none; }
.install b { font-weight: 700; }
.install p { margin: 4px 0 0; font-size: 15px; color: var(--ink-soft); }
.install .share-ic { display: inline-grid; place-items: center; vertical-align: -4px; width: 22px; height: 22px; color: #0a84ff; }
.install .share-ic svg { width: 20px; height: 20px; }
.pushon form { margin-top: 10px; }
.pushon .push-note { color: var(--navy); font-weight: 600; }
.install-x { flex: none; align-self: center; border: 0; background: var(--paper-2); color: var(--navy); font: 600 15px var(--body); border-radius: 999px; padding: 10px 14px; min-height: 44px; cursor: pointer; }
.cam, .mic { flex: none; width: 46px; height: 46px; border-radius: 50%; display: grid; place-items: center; cursor: pointer; color: #54656f; background: transparent; border: 0; position: relative; }
.cam svg, .mic svg { width: 24px; height: 24px; }
.cam input { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; cursor: pointer; }
.cam:has(input:focus-visible) { outline: 3px solid rgba(67, 189, 153, .55); outline-offset: 2px; }   /* the camera by Tab: its input is see-through */
.wa .mic { background: #1daa61; color: #fff; width: 48px; height: 48px; touch-action: none; -webkit-user-select: none; user-select: none; }
.mic.rec { background: #e25141; animation: pb-rec 1.2s ease-in-out infinite; }
.mic.rec.paused { animation: none; }
@keyframes pb-rec { 50% { box-shadow: 0 0 0 8px rgba(226, 81, 65, .2); } }
/* the chat mic's Pause / Resume, beside it while a tapped recording runs */
.mic-pause { flex: none; width: 48px; height: 48px; border-radius: 50%; display: grid; place-items: center; cursor: pointer; border: 0; background: #fff; color: #3b4a54; box-shadow: 0 1px 2px rgba(11, 20, 26, .15); }
.mic-pause[hidden] { display: none; }
.mic-pause svg { width: 22px; height: 22px; }
.mic-pause .ic-resume { color: #e25141; }
.mic-pause .ic-resume, .mic-pause.paused .ic-pause { display: none; }
.mic-pause.paused .ic-resume { display: block; }
.mic-pause:focus-visible { outline: 3px solid rgba(67, 189, 153, .55); outline-offset: 2px; }
.composer.js:not(.has-text) .send { display: none; }
.composer.js.has-text .mic { display: none; }
.msg-photo { display: block; max-width: 240px; max-height: 320px; width: auto; height: auto; border-radius: 8px; }

/* ---- the status charts (Emanol, 2026-09-29: "looks beautiful ... has charts,
   it's easy to read"). Every width is the handler's (app/jobs.asm, pb_bar3);
   the page draws plain bars, no chart library, no script. In: teal = paid,
   navy = due now, pale teal = later. Out: copper = spent, pale copper = still
   to pay. On the job page both bars share one scale, so in and out compare. */
.chart { margin-top: 26px; background: var(--card); border-radius: 18px; box-shadow: var(--shadow); padding: 18px 18px 6px; }
.ch-row { padding-bottom: 14px; }
.ch-row + .ch-row { border-top: 1px solid var(--line); padding-top: 16px; }
.ch-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.ch-head span { font-size: 16px; font-weight: 600; }
.ch-head b { font: 500 26px/1.1 var(--display); font-variant-numeric: lining-nums tabular-nums; }
.ch-bar { display: flex; height: 18px; border-radius: 9px; overflow: hidden; margin: 10px 0 12px; background: var(--paper); }
.ch-bar span { display: block; height: 100%; }
.ch-bar span + span { box-shadow: -2px 0 0 var(--card); }
.s-paid, .k-paid { background: var(--teal); }
.s-now, .k-now { background: var(--navy); }
.s-later, .k-later { background: #bfe6d8; }
.s-spent, .k-spent { background: var(--copper); }
.s-topay, .k-topay { background: #f1cfb6; }
.ch-key { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px 12px; margin: 0; padding: 0; list-style: none; font-size: 14px; color: var(--ink-soft); }
.ch-key li { min-width: 0; }
.ch-key.k4 { grid-template-columns: repeat(2, 1fr); }
.k-given { background: var(--paper); box-shadow: inset 0 0 0 1.5px var(--ink-soft); }
.ch-key i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 6px; vertical-align: 0; }
.ch-key b { display: block; font: 500 20px/1.2 var(--display); color: var(--navy); font-variant-numeric: lining-nums tabular-nums; margin-top: 2px; }
.ch-empty { margin: 0 0 12px; color: var(--ink-soft); font-size: 16px; }

/* where the job is: every stage, done ones dated, his stage marked; each row
   has room under its name for a deadline line (.tk-due) */
.stage .track { list-style: none; margin: 14px 0 0; padding: 4px 18px; background: var(--card); border-radius: 18px; box-shadow: var(--shadow); }
.track li { position: relative; display: flex; align-items: flex-start; gap: 12px; padding: 11px 0; color: var(--ink-faint); }
.track li + li { border-top: 1px solid var(--line); }
.track .tk-dot { flex: none; width: 14px; height: 14px; margin-top: 5px; border-radius: 50%; border: 2px solid #c9cfdc; background: var(--card); }
.track .tk-body { flex: 1; min-width: 0; }
.track .tk-name { display: block; font-size: 17px; }
.track .tk-due { display: block; font-size: 14px; color: var(--copper-ink); font-weight: 600; margin-top: 1px; }
.track .tk-when { flex: none; font-size: 14px; margin-top: 2px; font-variant-numeric: lining-nums tabular-nums; }
.track li.done { color: var(--ink-soft); }
.track li.done .tk-dot { border-color: var(--teal); background: var(--teal); }
.track li.current { color: var(--navy); }
.track li.current .tk-dot { border-color: var(--navy); background: var(--navy); box-shadow: 0 0 0 4px var(--paper-2); }
.track li.current .tk-name { font-weight: 700; }

/* Still to come in, split: Due now first, then Coming up */
.coming .grp { font: 600 15px/1.2 var(--body); color: var(--ink-soft); letter-spacing: .02em; margin: 16px 0 8px; display: flex; justify-content: space-between; }
.coming .grp.is-now { color: var(--navy); }
.coming .grp .sum { font-variant-numeric: lining-nums tabular-nums; }
.coming h2 + .grp { margin-top: 4px; }

/* the jobs list: each card's contract as a mini bar */
.mini { margin-top: 14px; }
.mini .ch-bar { height: 10px; border-radius: 5px; margin: 6px 0 0; }
.mini .mini-cap { display: flex; justify-content: space-between; gap: 10px; font-size: 14px; color: var(--ink-soft); }
.mini .mini-cap b { color: var(--navy); font-weight: 600; font-variant-numeric: lining-nums tabular-nums; }
.jobs-t a.row { flex-wrap: wrap; }
.jobs-t a.row > div:first-child { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* the stage line over the job's name, as on the jobs list (the markup keeps name, then stage) */
.jobs-t a.row > div:first-child > .sub { order: -1; margin-bottom: 4px; font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--teal-ink); }
.jobs-t .mini-row { flex-basis: 100%; height: 8px; border-radius: 4px; margin: 2px 0 0; }
@media (min-width: 760px) { .chart { padding: 22px 24px 8px; } .chart .ch-bar { height: 20px; } }
.msg.pending, .wa .msg.pending { opacity: .6; }

/* ==========================================================================
   The desktop (Michael, 2026-09-30, on a 1920 px screen: "it's very mobile
   centric, I want to see a nice desktop design as well"). Nothing here reaches
   a phone: below 1024 px the side navigation and the chat page's header are
   display:none and every other rule sits in a min-width query, so the phone
   look above is untouched. From 1024 px the header becomes a white side
   navigation (the same destinations Today already links to, their own words),
   the floating "Text the book" button moves into it, and each page uses the
   width: Today in two columns, the jobs list as a table from 1280 px, the job
   page's money beside its lists. From 1400 px Today and a job page dock the
   chat on the right (static/pb-desk.js), so he texts the book while he looks.
   ========================================================================== */
.side-nav, .chat-dock { display: none; }
.p-chat > .top { display: none; }
.in-dock .wa-head .chev { display: none; }

@media (min-width: 1024px) {
  :root { --side: 236px; --dock: 380px; }
  body:has(> .top) { padding-left: var(--side); }

  /* the side navigation: the logo, the date, four places, one button */
  .top, .p-chat > .top {
    position: fixed; top: 0; bottom: 0; left: 0; z-index: 30; width: var(--side); max-width: none; margin: 0;
    display: flex; flex-direction: column; align-items: stretch; justify-content: flex-start; gap: 0;
    padding: 28px 16px 24px; background: var(--card); border-right: 1px solid var(--line); overflow-y: auto;
  }
  .top .brand { padding: 0 12px; }
  .top .brand img { height: auto; width: 172px; }   /* the full logo, his name under the house */
  .top .when { padding: 0 12px; margin-top: 14px; font-size: 14px; color: var(--ink-faint); }
  .top .back { display: none; }
  .side-nav { display: flex; flex-direction: column; gap: 2px; margin-top: 26px; }
  .side-nav a {
    display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 0 12px; border-radius: 12px;
    text-decoration: none; font: 600 16px/1 var(--body); color: var(--ink-soft);
  }
  .side-nav a svg { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
  .side-nav a:hover { background: var(--paper); color: var(--navy); }
  /* Log out, quiet, under Text the book (Michael, 2026-10-01: "a logout button in the sidepanel?") */
  .side-nav .nv-out { margin: 18px 0 0; }
  .side-nav .nv-out button {
    display: flex; align-items: center; gap: 12px; width: 100%; min-height: 44px; padding: 0 12px; border: 0; border-radius: 12px;
    background: none; cursor: pointer; font: 600 15px/1 var(--body); color: var(--ink-faint);
  }
  .side-nav .nv-out button:hover { background: var(--paper); color: var(--navy); }
  .side-nav .nv-out svg { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
  /* the page he is on, on every page: its body class says it (no script needed; static/pb-desk.js
     adds aria-current="page" for a screen reader). A job's own page and its result pages are Jobs;
     Settings shares the job page's look (p-job) but is its own place (p-set). */
  .side-nav a[aria-current], .p-today .nv-today, .p-jobs .nv-jobs, .p-job:not(.p-set) .nv-jobs, .p-people .nv-ppl,
  .p-inv .nv-inv, .p-vn .nv-vn, .p-rem .nv-rem, .p-set .nv-set { background: var(--paper-2); color: var(--navy); }
  .side-nav a[aria-current] svg, .p-today .nv-today svg, .p-jobs .nv-jobs svg, .p-job:not(.p-set) .nv-jobs svg, .p-people .nv-ppl svg,
  .p-inv .nv-inv svg, .p-vn .nv-vn svg, .p-rem .nv-rem svg, .p-set .nv-set svg { stroke: var(--copper); }
  .side-nav a.nv-chat, .side-nav a.nv-chat[aria-current] {
    margin-top: 22px; justify-content: center; min-height: 50px; border-radius: 14px;
    background: var(--navy); color: #fff; box-shadow: 0 6px 18px rgba(27, 42, 74, .16);
  }
  .side-nav a.nv-chat:hover { background: #26395f; color: #fff; }
  .side-nav .nv-chat svg { stroke: #fff !important; }
  .dock { display: none; }

  /* the pages: wider, more air */
  .wrap, .p-today .wrap, .p-job .wrap, .p-client .wrap { max-width: 1180px; padding: 40px 48px 64px; }
  .p-job .wrap:not(:has(.jcol)) { max-width: 820px; }      /* a job's result pages: a reading width */
  .p-today h1, .p-job h1 { font-size: 42px; }
  .draft { padding: 0 48px 28px; }
  .install { margin-left: 48px; margin-right: 48px; }

  /* Today: what needs him first, Owed and You owe side by side, the jobs as cards */
  .p-today .wrap { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 28px; align-content: start; }
  .p-today .wrap > * { grid-column: 1 / -1; }
  .p-today #owed:has(+ #owe), .p-today #owed + #owe,
  .p-today #coming:has(+ #month), .p-today #coming + #month { grid-column: auto; }
  .p-today #needs { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 14px; }
  .p-today .need + .need { margin-top: 0; }
  .p-today .jobs-t .list { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 16px; padding: 0; background: none; box-shadow: none; border-radius: 0; }
  .p-today .jobs-t .list > li { padding: 20px 22px 18px; background: var(--card); border-radius: 18px; box-shadow: var(--shadow); transition: box-shadow .15s, transform .15s; }
  .p-today .jobs-t .list > li + li { border-top: 0; }
  .p-today .jobs-t .list > li:hover { transform: translateY(-1px); box-shadow: 0 2px 4px rgba(27, 42, 74, .06), 0 10px 28px rgba(27, 42, 74, .10); }
  .p-today .jobs-t a.row { align-items: flex-start; height: 100%; }
  .p-today .jobs-t .mini-row { align-self: flex-end; margin-top: 14px; }
  .p-today .month { padding-top: 0; }

  /* the job page: its name across, the money on the left, the lists on the right */
  .p-job .fixlink { margin-top: 30px; }
  .sheet-wrap .sheet {
    top: 50%; bottom: auto; transform: translateY(-50%); max-height: 86vh; border-radius: 24px;
    padding: 26px 30px 28px; margin-left: calc(50% - 320px + var(--side) / 2);
  }
  .sheet-wrap .grab { display: none; }
}

@media (min-width: 1200px) {
  .p-job .wrap:has(.jcol) { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 40px; align-items: start; }
  .p-job .job-head { grid-column: 1 / -1; }
  .jcol-b > .sec:first-child, .jcol-b > .sec:first-child { margin-top: 26px; }
}

/* the jobs list as a table: one row a job, the same figures the cards show */
.jobs-head { display: none; }
@media (min-width: 1280px) {
  .p-jobs .jobs {
    grid-template-columns: 1fr; gap: 0; background: var(--card); border: 1px solid var(--line);
    border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden;
  }
  .p-jobs .jobs-head, .p-jobs .job-card {
    display: grid; align-items: center; column-gap: 16px; padding: 18px 24px;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1.3fr) 96px 96px 108px 130px;
  }
  .p-jobs .jobs-head {
    padding-top: 13px; padding-bottom: 12px; background: var(--paper); border-bottom: 1px solid var(--line);
    font-size: 12px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-faint);
  }
  .p-jobs .jobs-head span:nth-child(n+3) { text-align: right; }
  /* the first column: the stage over the name over the client; the rest span all three lines */
  .p-jobs .job-card { grid-template-rows: auto auto auto; border: 0; border-radius: 0; box-shadow: none; transition: background .15s; }
  .p-jobs .job-card + .job-card { border-top: 1px solid var(--line); }
  .p-jobs .job-card:hover { transform: none; background: #f9fafc; }
  .p-jobs .job-card .chip { grid-column: 1; grid-row: 1; margin: 0 0 3px; font-size: 11.5px; }
  .p-jobs .job-card h2 { grid-column: 1; grid-row: 2; font-size: 20px; }
  .p-jobs .job-card .who { grid-column: 1; grid-row: 3; margin: 2px 0 0; font-size: 15px; }
  .p-jobs .job-card h2:last-of-type:not(:has(+ .who)) { grid-row: 2 / span 2; }
  .p-jobs .job-card .mini { grid-column: 2; grid-row: 1 / span 3; margin: 0; }
  .p-jobs .job-card .trio { display: contents; }
  .p-jobs .job-card .trio > div { grid-row: 1 / span 3; text-align: right; }
  .p-jobs .job-card .trio > div:nth-child(1) { grid-column: 3; }
  .p-jobs .job-card .trio > div:nth-child(2) { grid-column: 4; }
  .p-jobs .job-card .trio > div:nth-child(3) { grid-column: 5; }
  .p-jobs .job-card .trio .in, .p-jobs .job-card .trio .out { font-size: 20px; margin: 0; }
  .p-jobs .job-card .trio .profit { font-size: 22px; margin: 0; }
  .p-jobs .job-card .trio .label, .p-jobs .job-card .next-due:not(.none) > .label {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
  }
  .p-jobs .job-card .next-due { grid-column: 6; grid-row: 1 / span 3; display: block; margin: 0; text-align: right; }
  .p-jobs .job-card .next-due.none .label { font-size: 14px; font-weight: 500; letter-spacing: 0; text-transform: none; line-height: 1.3; }
  .p-jobs .totals { max-width: 640px; }
}

/* the chat docked on the right of Today and a job page */
@media (min-width: 1400px) {
  .has-dock body { padding-right: var(--dock); }
  .has-dock .wrap, .has-dock .p-today .wrap, .has-dock .p-job .wrap { padding-left: 40px; padding-right: 40px; }
  .chat-dock { display: block; position: fixed; top: 0; right: 0; bottom: 0; z-index: 30; width: var(--dock); border-left: 1px solid var(--line); background: #efeae2; }
  .chat-dock iframe { display: block; width: 100%; height: 100%; border: 0; }
}

/* the chat page on a desktop: the WhatsApp card on the app's paper, beside the navigation */
@media (min-width: 1024px) {
  body.wa.p-chat { background: var(--paper); }
  .p-chat .chat-layout { max-width: 860px; padding: 28px 0; }
  .p-chat .chat { min-height: calc(100vh - 56px); border: 1px solid var(--line); box-shadow: var(--shadow); }
}

/* ---- the desk's + Payment / + Expense (job page) and a reminder's Change time ---- */
.money-acts { display: flex; gap: 10px; margin: 28px 0 -10px; }
.money-acts .btn { flex: 1; text-align: center; }
.field[hidden] { display: none; }
.row-acts { flex-wrap: wrap; justify-content: flex-end; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.sheet .field select { width: 100%; padding: 0 12px; border-radius: 12px; border: 1px solid #cfd5e2; background: #fff; color: var(--navy); }
.sheet .field input[type=datetime-local] { font: 400 18px var(--body); }
@media (max-width: 520px) {
  .p-rem .rem { grid-template-columns: 1fr; gap: 10px; }
  .p-rem .rem .row-acts { justify-content: flex-start; }
}   /* this brace was missing (2026-10-01): every rule below sat inside the phone query,
       so the desktop never saw People's rows, the + menu's icons or its nav highlights */

/* ==========================================================================
   Outside the chat box (Michael, 2026-10-01: "how about outside of the chat
   box"): the + on every page and its menu, the "Which job?" sheets, New job,
   a new reminder, People and Invoices (app/plus.asm). Built from the parts
   above: the bottom sheets, .opts rows, white rounded lists, Fraunces names
   and amounts, teal = paid, copper = due or late. Nothing new to learn.
   ========================================================================== */
/* the thumb bar: Text the book, and the one + beside it (filled navy: the action) */
.plus-dock .dock-in { display: flex; gap: 10px; max-width: 600px; margin: 0 auto; }
.plus-dock .dock-in .btn { margin: 0; }
.plus-dock .chat-btn { flex: 1; width: auto; }
.dock.plus-dock .plus-btn { flex: none; width: 58px; padding: 0; background: var(--navy); border-color: var(--navy); color: #fff; }
.dock.plus-dock .plus-btn svg { width: 26px; height: 26px; }
.p-jobs .wrap, .p-rem .wrap, .p-people .wrap, .p-inv .wrap, .p-vn .wrap { padding-bottom: 120px; }

/* the menu: an icon, the word, a chevron */
.plus-opts a { justify-content: flex-start; gap: 14px; min-height: 60px; padding: 10px 0; }
.plus-opts a > div { flex: 1; }
.plus-opts .ic { flex: none; width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; background: var(--paper-2); color: var(--navy); }
.plus-opts .ic svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; color: inherit; }
.plus-opts .ic-in { background: var(--teal-wash); color: var(--teal-ink); }
.plus-opts .ic-out { background: var(--copper-wash); color: var(--copper-ink); }
.pick-job { max-height: 62vh; overflow-y: auto; }
.pick-job a { min-height: 56px; }
.plus-empty { margin: 14px 0 16px; }

/* a page's title with its one add button (Jobs: New job; Reminders: Reminder) */
.page-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.page-head .head-add { flex: none; margin-top: 4px; min-height: 48px; border-radius: 14px; font-size: 16px; padding: 0 18px 0 14px; }
.page-head .head-add svg { width: 20px; height: 20px; }
@media (max-width: 559px) {
  .page-head { flex-direction: column; gap: 0; }
  .page-head .head-add { margin-top: 16px; }
}

/* the two forms: phone fields at 16 px and up, 44 px and up to tap */
.sheet .plus-form { margin-top: 18px; }
.plus-form .field select { width: 100%; min-height: 54px; padding: 0 12px; border-radius: 12px; border: 1px solid #cfd5e2; background: #fff; color: var(--navy); font: 400 18px var(--body); }
.plus-form .field input[type=date], .plus-form .field input[type=time] { font: 400 18px var(--body); min-height: 54px; -webkit-appearance: none; appearance: none; }
.sheet .plus-form .field input[type=text]:not([inputmode]) { font: 400 18px var(--body); }
.plus-form .field[hidden] { display: none; }
.plan-prev { background: var(--card); border-radius: 16px; padding: 12px 16px 6px; margin: 2px 0 6px; }
.plan-prev .plan-h { display: block; font-size: 15px; font-weight: 600; color: var(--ink-soft); }
.plan-prev ul { list-style: none; margin: 6px 0 0; padding: 0; }
.plan-prev li { display: grid; grid-template-columns: minmax(0, 1fr) 112px auto; align-items: center; gap: 8px; padding: 8px 0; font-size: 16px; }
.plan-prev .pl-name { min-width: 0; overflow-wrap: anywhere; }
.plan-prev .pl-name small { display: block; font-size: 13px; color: var(--ink-soft); }
.plan-prev input { min-width: 0; width: 100%; box-sizing: border-box; min-height: 44px; padding: 0 10px; border-radius: 10px; border: 1px solid #cfd5e2; background: #fff; color: var(--navy); font: 400 16px var(--body); }
.plan-prev input.pl-amt { text-align: right; font-variant-numeric: lining-nums tabular-nums; }
.plan-prev input[readonly] { background: transparent; border-color: transparent; font-weight: 600; }
.plan-prev button { min-height: 44px; padding: 0 6px; border: 0; background: none; color: var(--ink-soft); font: 500 14px var(--body); text-decoration: underline; cursor: pointer; }
.plan-prev button[hidden] { visibility: hidden; display: block; }
.plan-prev .pl-add { display: block; margin: 0 0 6px; padding: 0; color: var(--navy); font-size: 16px; text-decoration: none; font-weight: 600; }
.plan-prev .pl-over { margin: 2px 0 6px; color: #c0392b; font-size: 15px; font-weight: 600; }
.plan-prev .pl-over[hidden] { display: none; }
.plan-prev li + li { border-top: 1px solid var(--line); }
.when-picks { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1.15fr); gap: 8px; margin: 0 0 14px; }
.when-picks[hidden] { display: none; }
.when-picks .btn { min-height: 44px; padding: 0 4px; font-size: 14px; border-radius: 999px; white-space: nowrap; }
.when-picks .btn.on { border-color: var(--navy); box-shadow: 0 0 0 1px var(--navy) inset; }
.when-row { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: 10px; }
.when-row .field input { min-width: 0; padding: 0 12px; }

/* People: who, their jobs, the money now, and Call / Text */
.ppl-sum b { color: var(--navy); font-weight: 600; font-variant-numeric: lining-nums tabular-nums; }
.ppl > li { flex-wrap: wrap; align-items: flex-start; }
.ppl .ppl-main { flex: 1; min-width: 0; }
.ppl .who { font: 500 20px/1.2 var(--display); }
.ppl .ppl-edit { display: inline-block; color: inherit; text-decoration: none; min-height: 44px; padding: 10px 0; margin: -10px 0; }
.ppl .ppl-edit:hover { text-decoration: underline; }
.ppl .r { text-align: right; }
.ppl .amt { font-size: 22px; }
.ppl .ppl-acts { flex-basis: 100%; display: flex; gap: 8px; margin-top: 2px; }
.ppl .ppl-acts .btn { min-height: 44px; font-size: 15px; padding: 0 14px; }
.ppl .ppl-acts .btn svg { width: 17px; height: 17px; }

/* Invoices: the folio, its job and client, the state in words, the PDF */
.invs > li { align-items: flex-start; }
.invs .inv-main { flex: 1; min-width: 0; }
.invs .sub .job-link { color: var(--ink-soft); text-underline-offset: 3px; }
.invs .r { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.invs .r .btn { min-height: 44px; font-size: 15px; }
.invs .st-w { color: var(--copper-ink); font-weight: 600; }
.invs .paid-w { color: var(--teal-ink); font-weight: 600; }
.invs li.gone .who, .invs li.gone .amt { color: var(--ink-faint); }
.invs li.gone .amt { text-decoration: line-through; }

@media (min-width: 1024px) {
  .p-jobs .wrap, .p-rem .wrap, .p-people .wrap, .p-inv .wrap, .p-vn .wrap { padding-bottom: 64px; }
  /* Invoices, Voice notes and Reminders share Jobs' and People's 1180 px column, so every
     page's title starts at the same place (they sat in a centred 820 px one, 2026-10-01) */
  .p-inv .wrap, .p-vn .wrap, .p-rem .wrap { max-width: 1180px; }
  /* Add: a small square + beside Text the book, on its row, as on the phone (Michael, 2026-10-01: "I like
     the current mobile version", shape 2 of three). "Add" shows over it on hover and by Tab, and is its
     name for a screen reader. Only where the page has the menu; without it Text the book takes the row. */
  .side-nav { display: grid; grid-template-columns: minmax(0, 1fr) 48px; column-gap: 8px; row-gap: 2px; }
  .side-nav > * { grid-column: 1 / -1; }
  .side-nav a.nv-chat, .side-nav a.nv-plus + a.nv-chat { grid-column: 1; grid-row: 8; margin-top: 22px; padding: 0 6px; gap: 8px; }
  body:not(:has(#plus)) .side-nav a.nv-chat { grid-column: 1 / -1; }
  .side-nav a.nv-plus {
    grid-column: 2; grid-row: 8; position: relative; margin-top: 22px; width: 48px; min-height: 50px; padding: 0;
    justify-content: center; border: 0; border-radius: 14px; background: var(--paper-2); color: var(--navy);
  }
  .side-nav a.nv-plus:hover { background: #dde2ec; }
  .side-nav a.nv-plus svg { width: 22px; height: 22px; stroke: var(--navy); stroke-width: 2.4; }
  .side-nav a.nv-plus .nv-t {
    position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%); padding: 5px 10px; border-radius: 8px;
    background: var(--navy); color: #fff; font: 600 13px/1 var(--body); white-space: nowrap; pointer-events: none;
    opacity: 0; transition: opacity .12s;
  }
  .side-nav a.nv-plus:hover .nv-t, .side-nav a.nv-plus:focus-visible .nv-t { opacity: 1; }
  body:not(:has(#plus)) .side-nav a.nv-plus { display: none; }
  .invs .r { flex-direction: row; align-items: center; gap: 16px; }
}

/* People from a tablet up (owner, 2026-10-01: the amounts wandered left and right with the name and
   the buttons): every row is the same three tracks, so the figures stand in one right-aligned column
   down the list. A row with no amount or no phone leaves its track empty; a row with both "owes you"
   and "you owe" stacks them in the amount track. Clients, then Helpers and vendors, one under the
   other: side by side at 1200 px the name track was left ~60 px. */
@media (min-width: 760px) {
  .ppl > li {
    display: grid; grid-template-columns: minmax(0, 1fr) 12rem 9.5rem; column-gap: 28px; row-gap: 0;
    align-items: center; padding: 16px 0;
  }
  .ppl .ppl-main { grid-column: 1; grid-row: 1 / span 2; }
  .ppl .r { grid-column: 3; }
  .ppl .ppl-acts { grid-column: 2; grid-row: 1 / span 2; justify-content: flex-end; gap: 10px; margin: 0; }
}

/* the answer buttons under the book's newest question (static/pb-app.js, #asks) */
.asks { display: flex; flex-wrap: wrap; gap: 8px; padding: 2px 14px 10px; }
.asks[hidden] { display: none; }
.ask {
  min-height: 44px; padding: 10px 20px; border-radius: 22px; border: 1.5px solid var(--teal-ink);
  background: #fff; color: var(--teal-ink); font: 600 16px/1.25 var(--body); cursor: pointer;
  text-align: center; overflow-wrap: anywhere; max-width: 100%;
}
.ask-primary { background: var(--teal-ink); color: #fff; }
.ask:active { opacity: .8; }

/* Voice notes: the player takes the card's width, the words under it */
.vn { display: block; }
.vn-main { width: 100%; }
.vn audio { display: block; width: 100%; margin: 8px 0 4px; }
.vn-text { margin: 4px 0 0; }

/* ---- A job's photos (templates/_photos.html, static/pb-photos.js, 2026-10-01): their own
   section above the notes, newest first, three square tiles a row, the day said once over
   its tiles. A tile keeps its square before the photo arrives (aspect-ratio, width/height),
   so nothing below it moves. Past nine tiles the ninth says "+N" and the viewer has the rest.
   The viewer is a popover (back.js: the phone's back button closes it): the photo whole on
   near-black, swipe between them (scroll-snap), the X and the bin at the top. */
.ph-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
/* Add photos (templates/_photos.html #add-photos): above the section, there with no photos yet */
.ph-add { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 18px 0 0; }
.ph-add-btn { cursor: pointer; }
.ph-add [hidden] { display: none; }                 /* the script sends on pick: no Save button */
.ph-add-btn:focus-within { outline: 2px solid var(--navy); outline-offset: 2px; }
/* a note with photos: the Note forms' picker (static/pb-notephotos.js) and the list's thumbnails */
.np-pick { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 0 0 12px; }
.np-pick[hidden], .np-shown[hidden] { display: none; }
.np-add { cursor: pointer; }
.np-add:focus-within { outline: 2px solid var(--navy); outline-offset: 2px; }
.np-mic[hidden], .np-said[hidden] { display: none; }
.np-mic { cursor: pointer; font-variant-numeric: tabular-nums; }
.np-mic svg { fill: currentColor; stroke: none; }
.np-mic.rec { background: #e25141; border-color: #e25141; color: #fff; animation: pb-rec 1.2s ease-in-out infinite; }
.np-mic.rec.paused { animation: none; background: #a83a2e; border-color: #a83a2e; }
.np-pause[hidden] { display: none; }
.np-pause { cursor: pointer; min-width: 96px; }
@media (prefers-reduced-motion: reduce) { .mic.rec, .np-mic.rec { animation: none; } }
.np-said { flex-basis: 100%; margin: 0; font-size: 14px; color: #8a3a2f; }
.np-shown { display: flex; flex-wrap: wrap; gap: 6px; }
.np-shown img { width: 48px; height: 48px; object-fit: cover; border-radius: 8px; display: block; }
.note-ph { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.nthumb { position: relative; display: block; width: 64px; height: 64px; border-radius: 10px; overflow: hidden; background: var(--paper-2); -webkit-tap-highlight-color: transparent; }
.nthumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.nthumb:focus-visible { outline: 3px solid rgba(67, 189, 153, .55); outline-offset: 2px; }
.nthumb[data-more]::after {
  content: attr(data-more); position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(27, 42, 74, .55); color: #fff; font: 500 18px/1 var(--display); font-variant-numeric: lining-nums tabular-nums;
}
.photo-undo { margin: 0 0 14px; scroll-margin-top: 90px; }
.ph-day { grid-column: 1 / -1; margin: 12px 0 2px; font-size: 14px; font-weight: 600; color: var(--ink-soft); }
.ph-day:first-child { margin-top: 0; }
.ph-day::first-letter, .pv-day::first-letter { text-transform: uppercase; }
.ptile { position: relative; display: block; aspect-ratio: 1 / 1; border-radius: 12px; overflow: hidden; background: var(--paper-2); box-shadow: var(--shadow); -webkit-tap-highlight-color: transparent; }
.ptile img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ptile:focus-visible { outline: 3px solid rgba(67, 189, 153, .55); outline-offset: 2px; }
.ptile:active img { opacity: .85; }
.ptile[hidden], .ph-day[hidden] { display: none; }
.ph-none { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; width: 100%; height: 100%; min-width: 64px; min-height: 64px; color: var(--ink-soft); font-size: 13px; text-decoration: none; }
.ph-none small { font-size: 12px; text-decoration: underline; }
.ptile[data-more]::after {
  content: attr(data-more); position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(27, 42, 74, .55); color: #fff; font: 500 26px/1 var(--display); font-variant-numeric: lining-nums tabular-nums;
}
.pv {
  position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none;
  margin: 0; padding: 0; border: 0; background: #0e1526; color: #fff; overflow: hidden;
}
.pv:popover-open { display: flex; flex-direction: column; }
html.pv-on { overflow: hidden; }                 /* the page behind the viewer stays put */
.pv-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: calc(10px + env(safe-area-inset-top)) 12px 10px; }
.pv-btn {
  flex: none; width: 48px; height: 48px; border-radius: 50%; border: 0; padding: 0; cursor: pointer;
  display: grid; place-items: center; background: rgba(255, 255, 255, .12); color: #fff;
}
.pv-btn svg { width: 22px; height: 22px; }
.pv-btn:focus-visible { outline: 3px solid rgba(67, 189, 153, .7); outline-offset: 2px; }
.pv-n { font: 600 16px/1 var(--body); font-variant-numeric: lining-nums tabular-nums; color: rgba(255, 255, 255, .85); }
.pv-track {
  flex: 1; min-height: 0; display: flex; overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory; overscroll-behavior: contain; scrollbar-width: none;
}
.pv-track::-webkit-scrollbar { display: none; }
.pv-slide { position: relative; flex: 0 0 100%; margin: 0; scroll-snap-align: center; scroll-snap-stop: always; }
.pv-slide img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.pv-day { margin: 0; text-align: center; padding: 12px 20px calc(18px + env(safe-area-inset-bottom)); font-size: 16px; color: rgba(255, 255, 255, .78); }
/* a photo saved with a note: the note's words above its day */
.pv-words { margin: 0 auto; max-width: 640px; text-align: center; padding: 14px 20px 0; font-size: 17px; line-height: 1.4; color: #fff;
  overflow-wrap: anywhere; max-height: 30vh; overflow-y: auto; }
.pv-words[hidden] { display: none; }
.pv-words:not([hidden]) + .pv-day { padding-top: 6px; }
.pv-prev, .pv-next { display: none; }
@media (hover: hover) and (pointer: fine) {
  /* solid, so an arrow still shows over a white wall or a bright sky */
  .pv-prev, .pv-next { display: grid; position: absolute; top: 50%; transform: translateY(-50%);
    background: rgba(14, 21, 38, .82); box-shadow: 0 0 0 1px rgba(255, 255, 255, .35), 0 2px 10px rgba(0, 0, 0, .35); }
  .pv-prev { left: 16px; }
  .pv-next { right: 16px; }
  .pv-prev:disabled, .pv-next:disabled { opacity: .25; cursor: default; }
}
.pv-ask { position: absolute; inset: 0; z-index: 2; }
.pv-ask[hidden] { display: none; }
.pv-ask .dim { position: absolute; inset: 0; background: rgba(0, 0, 0, .5); }
.pv-ask .sheet { color: var(--navy); }
.pv-ask .close { width: 100%; min-height: 44px; background: none; border: 0; padding: 12px 0 0; font: inherit; font-weight: 600; cursor: pointer; }

/* ---- Jobs and Settings on a desktop (owner, 2026-10-01: the jobs page "could be better"; Settings
   was one narrow column floating in an empty page). Nothing here reaches a phone. */
@media (min-width: 1024px) {
  /* Jobs: the title, then all jobs' money as one band across the page, then the jobs, then the
     accountant's spreadsheets on the left and Log out on the right under one line. The order is
     the page's (flex order); the markup keeps the phone's order. */
  .p-jobs .wrap { display: flex; flex-wrap: wrap; align-items: stretch; }
  .p-jobs .wrap > * { flex: 1 1 100%; min-width: 0; }
  .p-jobs .page-head { order: 0; }
  .p-jobs .totals { order: 1; }
  .p-jobs .jobs { order: 2; margin-top: 20px; }
  .p-jobs .jobs-done { order: 2; margin-top: 24px; }
  .p-jobs .jobs-done > .jobs { margin-top: 12px; }
  .p-jobs .export, .p-jobs .wrap > .actions { order: 3; margin-top: 40px; padding-top: 24px; border-top: 1px solid var(--line); }
  .p-jobs .export { flex: 1 1 auto; }
  .p-jobs .wrap > .actions { flex: 0 0 auto; align-items: flex-end; padding-left: 24px; }
  .p-jobs .totals { display: flex; align-items: stretch; max-width: none; margin-top: 26px; padding: 0; overflow: hidden; }
  .p-jobs .totals > .label { flex: 0 0 150px; align-self: center; padding: 0 24px; }
  .p-jobs .totals .trio { display: contents; }
  .p-jobs .totals .trio > div { flex: 1 1 0; min-width: 0; padding: 18px 24px 20px; border-left: 1px solid var(--line); }
  .p-jobs .totals .t-in, .p-jobs .totals .t-out, .p-jobs .totals .t-profit,
  .p-jobs .totals .t-give, .p-jobs .totals .t-after { font-size: 26px; margin-top: 6px; }

  /* Settings: the same content width as every other page; each section's name on the left, its
     fields on the right, one line between sections, Save under the fields */
  .p-job.p-set .wrap:not(:has(.jcol)) { max-width: 1180px; }
  .p-set .lede, .p-set .wrap > .card { max-width: 908px; }
  .p-set .edit-form { max-width: none; padding: 0; margin-top: 18px; }
  .p-set .edit-form .section {
    display: grid; grid-template-columns: 260px minmax(0, 600px); column-gap: 48px;
    margin: 0; padding: 30px 0 14px; border-top: 1px solid var(--line);
  }
  .p-set .edit-form .section-head { grid-column: 1; grid-row: 1 / span 30; align-self: start; margin: 0; }
  .p-set .edit-form .section > .field { grid-column: 2; }
  .p-set .edit-form .save { width: 100%; max-width: 600px; margin: 18px 0 0 308px; }
}

/* a stage in the job page's list opens Where the job is with it picked (templates/job.html) */
.track a.tk-name { color: inherit; text-decoration: none; }
.track a.tk-name:hover { text-decoration: underline; text-underline-offset: 3px; }

/* the desktop (reviewer 2026-10-01): a pointer gets the side nav's hover on buttons and rows;
   the side panel's Log out is the one, so the Jobs page's and Today's footer one go */
@media (hover: hover) {
  .btn:hover { background: var(--paper); color: var(--navy); }
  .btn-primary:hover { background: #26395f; border-color: #26395f; color: #fff; }
  .btn-danger:hover { background: var(--copper-wash); color: var(--copper-ink); }
  .opts { overflow: hidden; }
  .opts a:hover { background: var(--paper); margin: 0 -18px; padding-left: 18px; padding-right: 18px; }
  .invs > li:hover { background: var(--paper); margin: 0 -12px; padding-left: 12px; padding-right: 12px; border-radius: 12px; }
}
@media (min-width: 1024px) {
  .wrap form.out { display: none; }
}
/* A text note's Edit and Delete (job page): quiet words, each a 44px target */
.note-acts { display: flex; gap: 4px; margin: 6px 0 -10px -10px; }
.note-act { display: inline-flex; align-items: center; min-height: 44px; min-width: 44px; padding: 0 10px; border-radius: 10px; font-size: 15px; font-weight: 600; color: var(--ink-soft); text-decoration: none; }
.note-act:hover { color: var(--navy); text-decoration: underline; }
.note-act:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
/* "Saved." and its Undo (templates/_saved.html): above the dock, wherever the form landed */
.saved-row { position: fixed; left: 16px; right: 16px; bottom: calc(100px + env(safe-area-inset-bottom)); z-index: 30; max-width: 568px; margin: 0 auto; box-shadow: 0 8px 28px rgba(27,42,74,.18); }
.saved-row p { color: var(--navy); font-size: 16px; }
@media (min-width: 1024px) { .saved-row { bottom: 24px; } }
/* it fades out on its own after 6 s (static/pb-app.js) */
.saved-row { transition: opacity .35s ease, transform .35s ease; }
.saved-row.saved-out { opacity: 0; transform: translateY(8px); pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .saved-row { transition: none; } }
/* the login page's quiet help line */
.login-help { text-align: center; margin: 20px 0 0; font-size: 15px; color: var(--ink-soft); }
/* the + by Tab: the app's teal ring, on the phone's + and the side panel's Add */
.dock.plus-dock .plus-btn:focus-visible, .side-nav a.nv-plus:focus-visible { outline: 3px solid rgba(67, 189, 153, .6); outline-offset: 2px; }
