/* Handy Hub — mobile-first. One scroll container (#main). Tap targets ≥44px. */
:root {
  /* Direction C — navy gravitas + teal identity on a warm off-white canvas. */
  --bg: #f5f6f4;            /* warm off-white canvas (not cold gray) */
  --card: #ffffff;
  --ink: #16263b;           /* navy ink — headings + structure */
  --muted: #61707f;         /* navy-leaning gray for secondary text */
  --line: #e7eaec;          /* warm hairline */
  --line-soft: #eef0f1;
  --accent: #0f9a72;        /* teal — the color of everything you tap */
  --accent-ink: #ffffff;
  --accent-soft: #e2f4ed;   /* teal tint for soft fills / icon chips */
  --accent-deep: #0b6e53;   /* deep teal text on tint */
  --navy: #16263b;          /* structure: dark money cards, desktop rail */
  --navy-soft: #24384f;
  --navy-ink: #eaf1f8;      /* light text on navy */
  --danger: #c0263a;
  --amber: #92500b;
  --amber-bg: #fbeecf;
  --shadow: 0 1px 2px rgba(22, 38, 59, 0.05), 0 1px 8px rgba(22, 38, 59, 0.04);
  --radius: 16px;
  --radius-sm: 11px;
  --nav-h: 64px;
}

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
  /* Native-app feel: no text selection or iOS long-press callout on the UI chrome
     or message/job content — highlightable text gives the web-page game away.
     Re-enabled on real form fields below so typing and editing still work. */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
input, textarea, select, [contenteditable="true"] {
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}
html, body { height: 100%; }
body {
  margin: 0;
  font-family: -apple-system, system-ui, 'Segoe UI', Roboto, sans-serif;
  background: var(--bg);
  color: var(--ink);
  overflow: hidden; /* single-scroll rule: #main owns scrolling */
}
body.locked #main { overflow: hidden; }

#app { display: flex; flex-direction: column; height: 100dvh; }
#main {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 14px 14px calc(var(--nav-h) + env(safe-area-inset-bottom, 0px) + 20px);
  overscroll-behavior: contain;
}

/* bottom tabs */
#nav {
  position: fixed; left: 0; right: 0; bottom: 0;
  height: calc(var(--nav-h) + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
  display: flex;
  background: var(--card);
  border-top: 1px solid var(--line);
  z-index: 30;
}
.nav-btn {
  flex: 1; min-height: 44px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  background: none; border: 0; font: inherit; font-size: 12px; color: var(--muted); cursor: pointer;
}
.nav-btn.on { color: var(--accent); font-weight: 600; }
.nav-icon { font-size: 20px; line-height: 1; }
.nav-icon svg { width: 24px; height: 24px; display: block; }
body.desktop .nav-icon svg { width: 21px; height: 21px; }

/* Center Quote FAB: an action (not a tab) wedged between Book and Jobs. It takes a
   flex slot like the tabs so spacing stays even, but its circle is raised above the
   bar with a negative top margin + a soft ring so it reads as the primary action. */
.nav-fab {
  flex: 1; min-height: 44px;
  display: flex; align-items: flex-start; justify-content: center;
  background: none; border: 0; padding: 0; cursor: pointer;
}
.nav-fab-icon {
  display: flex; align-items: center; justify-content: center;
  width: 54px; height: 54px; margin-top: -18px; border-radius: 50%;
  background: var(--accent); color: var(--accent-ink);
  box-shadow: 0 0 0 4px var(--card), 0 6px 14px rgba(15, 154, 114, 0.36);
}
.nav-fab-icon svg { width: 26px; height: 26px; display: block; }
.nav-fab:active .nav-fab-icon { transform: translateY(1px); }
/* Desktop sidebar: the FAB is a normal left-aligned row (teal circle + a "New quote"
   label) — the raised center-circle only makes sense against the mobile bar's top edge,
   so drop the flex:1 stretch + the negative lift and reveal the label. */
body.desktop .nav-fab { flex: 0 0 auto; align-items: center; justify-content: flex-start; padding: 4px 12px; gap: 11px; }
body.desktop .nav-fab-icon { width: 40px; height: 40px; margin-top: 0; box-shadow: none; }
body.desktop .nav-fab-icon svg { width: 20px; height: 20px; }
.nav-fab-label { display: none; }
body.desktop .nav-fab-label { display: inline; font-size: 15px; font-weight: 600; color: var(--accent); }

/* Shared inline line-icon (icons.js). Inherits text color; size via --ic-size. */
.ic { display: inline-flex; align-items: center; justify-content: center; vertical-align: middle; color: inherit; flex: none; }
.ic svg { width: var(--ic-size, 20px); height: var(--ic-size, 20px); display: block; }

/* view header */
.view-head { display: flex; align-items: center; gap: 10px; margin: 2px 0 14px; }
.view-head h1 { font-size: 26px; font-weight: 800; letter-spacing: -0.015em; margin: 0; color: var(--navy); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grow { flex: 1; min-width: 0; }
/* Job-detail header: the editable title reads as the page heading, the customer as a tight
   subtitle beneath it, and status as a compact color-coded pill — not three stacked form
   boxes. (Title previously also carried `.input`, whose border/fill clobbered these.) */
.title-input { font-size: 21px; font-weight: 800; color: var(--navy); letter-spacing: -0.015em; line-height: 1.2; border: 0; background: transparent; padding: 2px 0; width: 100%; }
.title-input:focus { outline: none; border-bottom: 2px solid var(--accent); }
.job-cust { display: inline-flex; align-items: center; min-height: 0; font-size: 13px; margin-top: 1px; }
.status-select {
  flex: 0 0 auto; width: auto; align-self: center;
  font: inherit; font-size: 13px; font-weight: 700; text-transform: capitalize;
  border: 1px solid var(--line); border-radius: 999px;
  padding: 7px 30px 7px 13px; background-color: var(--card);
  -webkit-appearance: none; appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2361707f' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center;
}
.status-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* inputs */
.input, .search {
  width: 100%; min-height: 46px;
  font: inherit; font-size: 16px; color: var(--ink);
  background: var(--card);
  border: 1px solid var(--line); border-radius: 10px;
  padding: 10px 12px;
}
.input:focus, .search:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
/* Keyboard-focus ring (a11y): visible on keyboard/switch nav, not on mouse/touch. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* .segmented/.stepper set overflow:hidden, which clips a child's outer focus ring —
   inset the ring on their buttons so it stays visible (the "How it's billed" toggle etc.). */
.seg-btn:focus-visible, .step-btn:focus-visible { outline-offset: -2px; }
textarea.input { min-height: 70px; resize: vertical; }
select.input { width: auto; }
.search { margin-bottom: 10px; }
.field { display: block; margin-bottom: 12px; }
.field-label { display: block; font-size: 13px; font-weight: 600; color: var(--muted); margin-bottom: 5px; }
.field-hint { display: block; font-size: 12px; color: var(--muted); margin-top: 4px; }
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.check-row { display: flex; align-items: center; gap: 10px; min-height: 44px; font-size: 14px; margin-bottom: 10px; }
.check-row input { width: 22px; height: 22px; accent-color: var(--accent); }

/* buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: 10px 18px;
  font: inherit; font-size: 16px; font-weight: 600;
  color: var(--accent-ink); background: var(--accent);
  border: 0; border-radius: 12px; cursor: pointer;
}
.btn.small { min-height: 44px; font-size: 14px; padding: 8px 14px; }
.btn.tiny { min-height: 36px; font-size: 13px; padding: 6px 12px; border-radius: 9px; }
.btn.block { display: flex; width: 100%; margin-top: 6px; }
.btn.ghost { background: transparent; color: var(--accent); border: 1px solid var(--line); }
.btn.danger { background: var(--danger); }
.danger-text, .btn.ghost.danger-text { color: var(--danger); }
.btn:active { transform: scale(0.98); }
.icon-btn {
  min-width: 44px; min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 0; font-size: 20px; color: var(--muted); cursor: pointer;
}
.icon-btn:disabled { cursor: default; }
.icon-btn.busy { opacity: 0.45; animation: ic-pulse 1s ease-in-out infinite; }
@keyframes ic-pulse { 50% { opacity: 0.85; } }
/* Accent used as TEXT uses the deeper teal (--accent-deep #0b6e53, 6.2:1 on white)
   so small links clear WCAG AA — the soft --accent #0f9a72 (3.6:1) stays for icons,
   borders, and the active-tab indicator, where the 3:1 UI threshold applies. */
.link { color: var(--accent-deep); text-decoration: none; font-weight: 600; background: none; border: 0; font: inherit; cursor: pointer; padding: 0; }
.link.small { font-size: 13px; display: inline-flex; align-items: center; min-height: 44px; }

/* chips */
.chips { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 6px; margin-bottom: 8px; scrollbar-width: none; }
.chips::-webkit-scrollbar { display: none; }
.chip {
  flex-shrink: 0; min-height: 38px; padding: 7px 14px;
  font: inherit; font-size: 14px; color: var(--ink);
  background: var(--card); border: 1px solid var(--line); border-radius: 999px; cursor: pointer;
}
.chip.on { background: var(--ink); color: #fff; border-color: var(--ink); }
/* Book filters are two-tone so the hierarchy reads at a glance: the TRADE row is the primary
   level (bold; solid navy when on), the CATEGORY row the secondary level (teal-soft when on).
   navy = which trade · teal = which section. */
.chips.trade-filter .chip { font-weight: 600; }
.chips.cat-filter .chip.on { background: var(--accent-soft); color: var(--accent-deep); border-color: var(--accent-soft); }

/* Category picker: an expanded trade shows its subsections as a horizontal side-scroll
   (so you never scroll a long flat list); the inline add-trade/subsection form sits in-place. */
.cat-subscroll { display: flex; gap: 8px; overflow-x: auto; padding: 8px 12px 12px; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; }
.cat-subscroll .chip { flex: 0 0 auto; }
.cat-subscroll .chip.on { background: var(--accent-soft); color: var(--accent-deep); border-color: var(--accent-soft); }
.cat-add { padding: 10px 12px 12px; }
/* The trade the edited item lives in — softly highlighted so its "home" reads at a glance. */
.row.cat-cur { background: var(--accent-soft); }
.row.cat-cur .row-title { color: var(--accent-deep); }

/* lists & rows */
.list { display: flex; flex-direction: column; gap: 8px; }
.list-label { margin: 16px 2px 8px; font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.07em; }
.row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  min-height: 60px; padding: 11px 14px; text-align: left;
  font: inherit; color: inherit; cursor: pointer;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.row.flat { border: 0; border-bottom: 1px solid var(--line); border-radius: 0; padding: 10px 2px; min-height: 54px; background: transparent; box-shadow: none; }
.row.flat:last-of-type { border-bottom: 0; }
.row-main { flex: 1; min-width: 0; }
.row-title { font-weight: 600; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.row-sub { font-size: 13px; color: var(--muted); margin-top: 2px; }
.row-price { text-align: right; display: flex; flex-direction: column; align-items: flex-end; }
.row-chev { color: var(--muted); font-size: 22px; }
.empty { color: var(--muted); text-align: center; padding: 28px 16px; margin: 0; }
.empty.small { padding: 8px 0; text-align: left; font-size: 14px; }

/* cards */
.card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 15px; margin-bottom: 12px;
  box-shadow: var(--shadow);
}
.card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.inline-row { display: flex; align-items: center; gap: 10px; min-height: 40px; }
.totals .total-line { border-top: 1px solid var(--line); margin-top: 6px; padding-top: 10px; font-size: 18px; }
.banner {
  margin-top: 10px; padding: 10px 12px; border-radius: 10px;
  background: var(--amber-bg); color: var(--amber); font-size: 14px; font-weight: 600;
}
.banner.est-ok { background: #ecfdf5; color: #065f46; margin: 0 0 10px; }

/* tags & status */
.tag {
  font-size: 11px; font-weight: 600; color: var(--muted);
  background: var(--bg); border: 1px solid var(--line);
  padding: 2px 7px; border-radius: 999px; white-space: nowrap;
}
/* Channel badge for WhatsApp threads — its recognizable brand green, kept small so it reads as a
   channel marker, not a UI accent (the app's own accent stays navy/teal). */
.tag.wa { color: #fff; background: #25d366; border-color: #1da851; }
/* "or" divider between the Google button and the email/password form on the login screen. */
.login-or { display: flex; align-items: center; text-align: center; color: var(--muted); font-size: 13px; margin: 14px 0; }
.login-or::before, .login-or::after { content: ''; flex: 1; border-bottom: 1px solid var(--line); }
.login-or span { padding: 0 10px; }

/* Hard email-confirmation gate — full-screen blocker for a brand-new account until it confirms. */
#verify-gate { position: fixed; inset: 0; z-index: 200; background: var(--bg); display: flex; align-items: center; justify-content: center; padding: 24px; overflow: auto; }
.verify-card { max-width: 420px; width: 100%; text-align: center; }
.verify-card h1 { margin: 0 0 6px; }

/* WhatsApp send button (assisted-send sheet + composer) — brand green so it reads as "WhatsApp". */
.btn.wa { background: #25d366; border-color: #1da851; color: #fff; }
.btn.wa:hover { background: #1da851; }
.wa-link { color: #1da851; }
/* An <a> styled as a button but with no href (no recipient yet) shouldn't look/act clickable. */
a.btn.disabled { opacity: 0.5; pointer-events: none; }
.status { font-weight: 600; text-transform: capitalize; }
.s-lead { color: #6d28d9; } .s-estimating { color: #b45309; } .s-quoted { color: #0369a1; }
.s-scheduled { color: #047857; } .s-in_progress { color: #b91c1c; } .s-done { color: #334155; } .s-paid { color: #15803d; }

/* line items */
.line-item { display: flex; align-items: center; gap: 8px; padding: 10px 0; border-bottom: 1px solid var(--line); }
.line-item:last-of-type { border-bottom: 0; }
.line-item.optional { opacity: 0.75; }
.line-main { flex: 1; min-width: 0; text-align: left; background: none; border: 0; font: inherit; color: inherit; cursor: pointer; padding: 0; }
.line-total { min-width: 64px; text-align: right; }
.stepper { display: flex; align-items: center; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.step-btn { width: 40px; height: 40px; background: var(--bg); border: 0; font-size: 20px; cursor: pointer; }
.step-val { min-width: 34px; text-align: center; font-weight: 700; }

/* segmented */
.segmented { display: flex; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.seg-btn { flex: 1; min-height: 44px; background: var(--card); border: 0; font: inherit; font-size: 14px; cursor: pointer; }
.seg-btn.on { background: var(--accent); color: #fff; font-weight: 600; }

/* bottom sheet */
.sheet-wrap { position: fixed; inset: 0; z-index: 50; }
.sheet-backdrop { position: absolute; inset: 0; background: rgba(13, 22, 31, 0.45); }
.sheet {
  position: absolute; left: 0; right: 0; bottom: 0;
  max-height: 86dvh; display: flex; flex-direction: column;
  background: var(--card); border-radius: 18px 18px 0 0;
  padding-bottom: env(safe-area-inset-bottom, 0px);
  animation: rise 0.18s ease-out;
}
@keyframes rise { from { transform: translateY(30px); opacity: 0.6; } }
.sheet-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 8px 8px 18px; }
.sheet-body { overflow-y: auto; padding: 4px 18px 20px; }
/* Desktop: a full-width bottom sheet wastes a wide window — center it as a width-capped
   modal with all corners rounded. Mobile keeps the bottom-sheet behavior. */
body.desktop .sheet {
  left: 50%; right: auto; bottom: auto; top: 50%;
  transform: translate(-50%, -50%);
  width: min(560px, calc(100vw - 48px));
  border-radius: 18px;
  animation: sheet-pop 0.16s ease-out;
}
@keyframes sheet-pop { from { opacity: 0; transform: translate(-50%, -46%); } }

/* toast */
#toast {
  position: fixed; left: 50%; bottom: calc(var(--nav-h) + 24px);
  transform: translate(-50%, 20px);
  max-width: 86vw; padding: 11px 18px;
  background: var(--ink); color: #fff; font-size: 14px; border-radius: 12px;
  opacity: 0; pointer-events: none; transition: all 0.2s; z-index: 60;
}
#toast.show { opacity: 1; transform: translate(-50%, 0); }
#toast.bad { background: var(--danger); }

/* login */
#login { display: flex; align-items: center; justify-content: center; min-height: 100dvh; padding: 20px; }
#login[hidden], #app[hidden] { display: none; }
.login-box { width: 100%; max-width: 360px; background: var(--card); border: 1px solid var(--line); border-radius: 18px; padding: 26px; }
.login-box h1 { margin: 0 0 4px; }

.muted { color: var(--muted); }
.small { font-size: 13px; }
.center { text-align: center; }
.ok-text { color: #15803d; }
.warn-text { color: var(--amber); }

/* nav badges + More menu */
.nav-icon { position: relative; }
.nav-badge {
  position: absolute; top: -4px; right: -12px;
  min-width: 16px; height: 16px; padding: 0 4px;
  background: var(--danger); color: #fff;
  font-size: 10px; font-weight: 700; line-height: 16px;
  border-radius: 999px; text-align: center;
}
#sync-strip {
  position: fixed; left: 0; right: 0;
  bottom: calc(var(--nav-h) + env(safe-area-inset-bottom, 0px));
  padding: 7px 14px; font-size: 13px; font-weight: 600; text-align: center;
  z-index: 25;
}
#sync-strip.offline { background: var(--amber-bg); color: var(--amber); }
#sync-strip.syncing { background: #dbeafe; color: #1e40af; }
#sync-strip.failed { background: var(--danger); color: #fff; cursor: pointer; }

/* Service-worker update banner — sits just above the tabs like the sync strip,
   but with a tap target so it must clear the sync-strip's z-index. */
#sw-update {
  position: fixed; left: 0; right: 0;
  bottom: calc(var(--nav-h) + env(safe-area-inset-bottom, 0px));
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: 9px 14px calc(9px + env(safe-area-inset-bottom, 0px));
  background: var(--accent); color: var(--accent-ink);
  font-size: 14px; font-weight: 600;
  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.12);
  z-index: 26;
}
.sw-update-btn {
  min-height: 36px; padding: 6px 16px;
  font: inherit; font-size: 13px; font-weight: 700;
  color: var(--accent); background: #fff;
  border: 0; border-radius: 9px; cursor: pointer;
}
.sw-update-btn:active { transform: scale(0.98); }
.sw-update-btn:disabled { opacity: 0.7; }
body.desktop #sw-update { left: 216px; }

/* Settings logo preview thumbnail (bounded so a tall/wide source can't blow out the row). */
.logo-thumb { max-height: 32px; max-width: 120px; width: auto; height: auto; object-fit: contain; border-radius: 6px; border: 1px solid var(--line); background: #fff; }

/* More-menu rows: a soft teal tile holding a line icon — the high-end list look. */
.more-icon {
  width: 36px; height: 36px; border-radius: 10px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent-soft); color: var(--accent-deep);
}
.more-icon svg { width: 20px; height: 20px; display: block; }
.count-pill {
  min-width: 22px; padding: 2px 7px; border-radius: 999px;
  background: var(--bg); border: 1px solid var(--line);
  font-size: 12px; font-weight: 700; color: var(--muted); text-align: center;
}

/* Reviews hub: scoreboard + buckets */
.rvw-stats { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; margin-bottom: 6px; }
.rvw-stat { background: var(--card, #fff); border: 1px solid var(--line); border-radius: var(--radius-sm); box-shadow: var(--shadow); padding: 14px 6px; text-align: center; }
.rvw-stat b { display: block; font-size: 24px; font-weight: 800; color: var(--navy); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.rvw-stat span { display: block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); margin-top: 3px; }
.rvw-row { gap: 10px; }
.rvw-actions { display: flex; gap: 6px; flex: none; }
.rvw-star { width: 32px; height: 32px; flex: none; border-radius: 9px; display: inline-flex; align-items: center; justify-content: center; background: var(--accent-soft); color: var(--accent-deep); }
.btn-ic { display: inline-flex; align-items: center; gap: 5px; }
.setup-card { border-color: var(--accent); }

/* Per-job profitability card */
.prof-line { min-height: 32px; }
.prof-val { font-variant-numeric: tabular-nums; }
.prof-total { border-top: 1px solid var(--line); margin-top: 6px; padding-top: 10px; font-size: 18px; }
.prof-rate { margin-top: 12px; padding: 12px 14px; border-radius: var(--radius-sm); display: flex; flex-direction: column; gap: 2px; }
.prof-rate strong { font-size: 22px; letter-spacing: -0.01em; }
.prof-rate.good { background: var(--accent-soft); color: var(--accent-deep); }
.prof-rate.bad { background: var(--amber-bg); color: var(--amber); }
.prof-rate .small { opacity: 0.85; font-weight: 600; }

/* Online-booking request awaiting the owner's confirm (scheduler agenda row) */
.sched-pending { background: var(--amber-bg); border-radius: 12px; padding-right: 8px; }
.sched-actions { display: flex; gap: 6px; flex: none; align-items: center; }
.tag-req { background: var(--amber-bg); color: var(--amber); border-color: transparent; }

/* Numbers screen: stat grid, revenue bar chart, AR aging */
.num-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px; }
.num-stat { text-align: center; padding: 4px; }
.num-stat-val { font-size: 19px; font-weight: 800; font-variant-numeric: tabular-nums; }
.num-stat-label { font-size: 12px; color: var(--muted); margin-top: 2px; }

.rev-chart { display: flex; align-items: flex-end; gap: 4px; height: 150px; padding-top: 6px; }
.rev-col { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; height: 100%; }
.rev-amt { font-size: 9px; color: var(--muted); height: 12px; line-height: 12px; font-variant-numeric: tabular-nums; }
.rev-bar-wrap { flex: 1; width: 100%; display: flex; align-items: flex-end; justify-content: center; }
.rev-bar { width: 72%; min-height: 2px; background: var(--accent); border-radius: 4px 4px 0 0; opacity: 0.55; transition: height 0.2s; }
.rev-bar.peak { opacity: 1; }
.rev-label { font-size: 10px; color: var(--muted); margin-top: 4px; white-space: nowrap; }

.age-row { display: flex; gap: 6px; }
.age-chip { flex: 1; text-align: center; padding: 8px 4px; border: 1px solid var(--line); border-radius: 10px; background: var(--bg); }
.age-chip.warn { background: var(--amber-bg); border-color: #fde68a; }
.age-amt { font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; }
.age-chip.warn .age-amt { color: var(--amber); }
.age-label { font-size: 10px; color: var(--muted); margin-top: 2px; }

/* =========================================================================
   DESKTOP (body.desktop, set by the JS layout layer at ≥900px):
   left sidebar nav + two-pane master-detail. Mobile keeps the single column. */
body.desktop #app { flex-direction: row; }

/* bottom tabs → left sidebar */
body.desktop #nav {
  position: relative; left: auto; right: auto; bottom: auto;
  order: -1; flex-direction: column; align-items: stretch;
  width: 216px; height: 100dvh; flex: 0 0 216px;
  padding: 14px 10px; gap: 3px;
  border-top: 0; border-right: 0;
  background: var(--navy);
}
body.desktop .nav-btn {
  flex-direction: row; justify-content: flex-start; gap: 13px;
  min-height: 46px; padding: 0 14px; border-radius: 10px; font-size: 15px;
  color: rgba(234, 241, 248, 0.72);
}
body.desktop .nav-btn.on { background: rgba(255, 255, 255, 0.10); color: #fff; }
body.desktop .nav-btn.on .nav-icon { color: var(--accent); }
body.desktop .nav-icon { font-size: 19px; }
body.desktop .nav-badge { position: static; margin-left: auto; }

/* content area fills the rest */
body.desktop #main { flex: 1; min-width: 0; height: 100dvh; padding: 0; overflow: hidden; }

/* single-view surfaces: a roomy, readable centered column */
body.desktop #main:not(.two-pane) {
  overflow-y: auto;
  padding: 24px 32px calc(env(safe-area-inset-bottom, 0px) + 32px);
}
body.desktop #main:not(.two-pane) > * { max-width: 860px; margin-left: auto; margin-right: auto; }

/* two-pane master-detail: list (fixed) + detail (fills) */
body.desktop #main.two-pane { display: flex; overflow: hidden; }
.pane-list { width: 380px; flex: 0 0 380px; height: 100%; overflow-y: auto; padding: 18px; border-right: 1px solid var(--line); }
.pane-detail { flex: 1; min-width: 0; height: 100%; overflow-y: auto; padding: 20px 28px; }
.pane-empty { display: flex; align-items: center; justify-content: center; height: 100%; text-align: center; padding: 48px; }
body.desktop .row.active { border-color: var(--accent); background: var(--accent-soft); }
/* the list is always visible on desktop — the in-pane Back button is redundant */
body.desktop .pane-detail .view-head > .icon-btn[aria-label="Back"] { display: none; }
body.desktop #sync-strip { left: 216px; }

/* --- Job-site address (tap-to-navigate) + appointment context card --- */
.addr-row { display: flex; align-items: center; gap: 10px; text-decoration: none; color: var(--ink); padding: 4px 0; min-width: 0; }
.addr-row .addr-text { font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
.addr-row .addr-pin { color: var(--accent-deep); flex: none; display: flex; }
.addr-row .addr-go { color: var(--accent); flex: none; display: flex; }
.addr-row:active { opacity: .6; }
.addr-card { padding: 14px; }
.prop-row { padding: 10px 0; border-top: 1px solid var(--line); }
.prop-row:first-child { border-top: 0; }
.appt-context:not(:empty) { margin: 2px 0 4px; padding: 12px; background: var(--accent-soft); border-radius: var(--radius-sm); }
.appt-context .addr-row { color: var(--accent-deep); }

/* --- Book screen: centered column + sub-tabs; Founder dashboard stats --- */
.pb-center { max-width: 720px; margin: 0 auto; }
/* Override the app-wide desktop content cap (860, line ~364) so the Book is a clean,
   clearly-centered 720 column on desktop too — not a sprawling wide list. */
body.desktop #main:not(.two-pane) > .pb-center { max-width: 720px; margin-left: auto; margin-right: auto; }
/* Keep the Book header one action-row tall on BOTH sub-tabs. The Price-book tab has
   CSV + "Custom job" buttons (44px row); the Pricing tab has none, so without this it
   collapses to bare-text height and the "Book" title + tabs jump up ~13px when you
   switch. min-height pins the row so the title and tabs stay put across tabs. */
.pb-center .view-head { min-height: 44px; }
.pb-tabs { margin: 0 0 14px; }
/* --- Book → Trades manager (add / hide whole starter packs) --- */
.trade-list { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.trade-row { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: #fff; }
.trade-row.on { border-color: var(--accent-soft); background: var(--accent-soft); }
.trade-row-main { flex: 1; min-width: 0; }
.trade-row-title { font-weight: 700; color: var(--navy); display: flex; align-items: center; gap: 8px; }
.trade-row-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.trade-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); flex: none; }
.f-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.f-stat-val { font-size: 26px; font-weight: 800; letter-spacing: -.02em; }
.f-stat-label { margin-top: 2px; }
.f-stat-sub { margin-top: 1px; }

/* --- Today home (the daily-driver landing screen) --- */
/* Card titles are real h2 headings (so screen-reader users can jump card to card),
   styled to read like the old bold <strong> label. */
.card-title { margin: 0; font-size: 16px; font-weight: 700; letter-spacing: -.01em; color: var(--navy); }
.today-wrap > .view-head h1 { line-height: 1.12; white-space: normal; }
.today-date { margin-top: 2px; }
/* a "3 new" pill in a card head + a count pill on a row */
.today-count { background: var(--accent-soft); color: var(--accent-deep); font-weight: 700; font-size: 12px; padding: 2px 10px; border-radius: 999px; }
.today-pill { background: var(--accent-soft); color: var(--accent-deep); font-weight: 700; font-size: 13px; min-width: 24px; text-align: center; padding: 1px 8px; border-radius: 999px; }
.today-when { white-space: nowrap; margin-left: 8px; }
/* booking-request alert row borrows the amber accent */
.today-alert { background: var(--amber-bg); }
.today-alert .row-title { color: var(--amber); }
/* an appointment = the tappable row + its tap-to-navigate address underneath */
.today-appt .addr-row { margin: 4px 0 0; padding-left: 14px; }
.today-time { font-weight: 700; color: var(--navy); min-width: 62px; }
/* outstanding-money headline line */
.today-owed { display: flex; align-items: baseline; justify-content: space-between; margin: 4px 0 10px; }
.today-owed strong { font-size: 22px; letter-spacing: -.01em; color: var(--navy); }
/* this-week 3-up stat strip */
.today-stats { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; text-align: center; }
.today-stat-val { font-size: 20px; font-weight: 800; color: var(--navy); letter-spacing: -.01em; }
.today-stat-label { margin-top: 2px; }

/* Money-first header band: navy block with the greeting + two money tiles. The
   headline numbers a solo operator opens the app for, above every card. */
.today-band {
  background: var(--navy); color: var(--navy-ink);
  border-radius: var(--radius); padding: 16px 16px 14px; margin-bottom: 12px;
}
.today-band-head { margin-bottom: 12px; }
.today-band-greet { margin: 0; font-size: 24px; font-weight: 800; letter-spacing: -.02em; color: #fff; line-height: 1.1; }
.today-band-date { margin-top: 2px; font-size: 13px; color: var(--navy-ink); opacity: .72; }
.today-band-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.today-band-tile {
  text-align: left; background: var(--navy-soft); border: 0; border-radius: 12px;
  padding: 12px 14px; cursor: pointer; color: inherit; font: inherit;
}
.today-band-tile:active { background: rgba(255, 255, 255, 0.06); }
.today-band-label { font-size: 12px; color: var(--navy-ink); opacity: .72; }
.today-band-val { margin-top: 4px; font-size: 22px; font-weight: 800; letter-spacing: -.01em; color: #fff; font-variant-numeric: tabular-nums; }

/* Persistent search pill: looks like an input, behaves like a button that opens
   the global search view (which owns the real field + keyboard). */
.today-search {
  display: flex; align-items: center; gap: 10px; width: 100%;
  margin-bottom: 14px; padding: 12px 14px;
  background: var(--card); border: 1px solid var(--line); border-radius: 999px;
  color: var(--muted); font: inherit; font-size: 15px; text-align: left; cursor: pointer;
}
.today-search:active { background: var(--bg); }
.today-search-ic { display: inline-flex; flex: none; color: var(--muted); }
.today-search-ic svg { width: 18px; height: 18px; display: block; }
.today-search-ph { color: var(--muted); }

/* Unified contact screen — one customer header + Messages|Jobs|Details tabs. The body
   fills the remaining height so the embedded thread keeps its pinned-composer layout
   (it reuses .thread-wrap, whose height:100% + the #main:has(.thread-wrap) rule already
   seat the composer above the fixed nav). Jobs/Details simply scroll in the body. */
.contact-wrap { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.contact-wrap > .view-head { flex: 0 0 auto; margin-bottom: 6px; }
.contact-wrap > .view-head h1 { font-size: 22px; }
.contact-sub { font-size: 13px; color: var(--muted); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.contact-tabs { flex: 0 0 auto; margin: 0 0 12px; }
.contact-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.contact-body > .thread-wrap { height: 100%; }
/* Swipe between Messages/Jobs/Details: the incoming panel slides in from the side you
   flicked toward. Resting state already equals the keyframe's `to`, so no fill-mode needed. */
.contact-body.cb-enter-r { animation: cb-enter-r 0.2s ease; }
.contact-body.cb-enter-l { animation: cb-enter-l 0.2s ease; }
@keyframes cb-enter-r { from { transform: translateX(22px); opacity: 0.45; } to { transform: none; opacity: 1; } }
@keyframes cb-enter-l { from { transform: translateX(-22px); opacity: 0.45; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .contact-body.cb-enter-r, .contact-body.cb-enter-l { animation: none; }
}
/* Messages: thread-wrap fills + composer self-clears the nav (the #main:has(.thread-wrap)
   rule zeroes #main's bottom padding). Jobs/Details have no thread-wrap, so #main keeps
   its own nav-clearing bottom padding and the body simply scrolls — no extra padding. */

/* Tappable Today cards — the whole card surface opens its screen (taps on inner rows keep
   their own target). cursor + a soft pressed state signal it; rows manage their own :active. */
.card-tap { cursor: pointer; }
.card-tap:active { background: var(--bg); }
.card-tap:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Customize-home: the band's edit button + the add/remove/drag-reorder sheet rows. */
.today-band-head { display: flex; align-items: flex-start; gap: 10px; }
.today-band-edit { flex: 0 0 auto; background: rgba(255, 255, 255, 0.12); border: 0; border-radius: 10px; color: var(--navy-ink); padding: 7px; cursor: pointer; }
.today-band-edit:active { background: rgba(255, 255, 255, 0.22); }
.today-band-edit-ic svg { width: 20px; height: 20px; display: block; }
.cz-list { display: flex; flex-direction: column; gap: 8px; }
.cz-row { display: flex; align-items: center; gap: 10px; min-height: 52px; padding: 8px 12px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-sm); }
.cz-row.cz-dragging { border-color: var(--accent); box-shadow: var(--shadow); }
.cz-row.cz-locked { background: var(--bg); }
.cz-grip { display: inline-flex; color: var(--muted); cursor: grab; touch-action: none; padding: 4px; margin: -4px 0 -4px -4px; }
.cz-grip:active { cursor: grabbing; }
.cz-grip-ic svg { width: 20px; height: 20px; display: block; }
.cz-row.cz-locked .cz-grip-ic { color: var(--muted); opacity: 0.55; }
.cz-label { flex: 1; min-width: 0; font-weight: 600; font-size: 15px; }
.cz-badge { flex: none; font-size: 11px; font-weight: 600; color: var(--accent-deep); background: var(--accent-soft); padding: 2px 9px; border-radius: 999px; }
.cz-remove { flex: none; background: none; border: 0; color: var(--muted); font-size: 17px; cursor: pointer; padding: 4px 8px; }
.cz-remove:active { color: var(--danger); }
