:root {
  --blue: #1E90FF;
  --grass: #5CDB3A;
  --red: #E23B2F;
  --orange: #F08A24;
  --ink: #111111;
  --paper: #F2F3F5;
  --line: #D9DBDE;
  --muted: #6A6E74;
  --navy: #163A5F;
  --teal: #1E90FF;
  --bg: #F2F3F5;
  --card: #fff;
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body { margin: 0; font: var(--fs-base, 14px)/1.45 "Segoe UI", system-ui, sans-serif; background: var(--paper); color: var(--ink); -webkit-tap-highlight-color: transparent; }
a { color: var(--blue); text-decoration: none; }
/* [Shared] Links (RULES UI-03): no default underline; hover and keyboard focus underline. Any link class that sets its own text-decoration wins. */
a:where(:hover, :focus-visible) { text-decoration: underline; }
.side {
  width: 220px;
  background: var(--ink);
  color: #fff;
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0; left: 0; bottom: 0;
  z-index: 5;
  overflow: auto;
  overscroll-behavior: contain;
  padding-bottom: env(safe-area-inset-bottom, 0px); /* keep Log out + version above the iPhone home indicator */
  border-right: 3px solid var(--grass);
}
.brand-row { display: flex; align-items: center; justify-content: space-between; }
.brand { color: #fff; font-weight: 650; text-decoration: none; font-size: 1.05rem; padding: 16px 8px 12px 18px; letter-spacing: -.02em; }
.gear { color: #c8c8c8; display: flex; align-items: center; padding: 16px 14px 12px 8px; }
.gear:hover, .gear.active { color: var(--blue); }
.settings-jump { position: sticky; top: 0; z-index: 4; display: flex; flex-wrap: wrap; gap: 8px; background: var(--paper); padding: 4px 0 12px; }
.settings-jump a { background: #fff; border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px; text-decoration: none; color: var(--ink); font-weight: 600; }
/* [Settings] Settings (plans/settings-cleanup-plan.md): one row style everywhere (Outlook-like one line), Save on top and bottom. */
.set-search { margin: 0 0 14px; }
.card.set-list { padding: 0; overflow: hidden; }
.set-list > h2 { margin: 0; padding: 14px 18px 6px; font-size: .78rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.set-list > .form-grid { padding: 6px 18px 16px; } /* Settings search: a setting's own control under its category line (assets/js/set-search.js) */
.set-logo { max-height: 48px; max-width: 200px; border-radius: 6px; } /* Settings > Company logo preview (was inline) */
.set-row { display: flex; align-items: center; gap: 12px; min-height: 52px; padding: 10px 18px; border-top: 1px solid var(--line); color: var(--ink); text-decoration: none; margin: 0; }
.set-list > h2 + .set-row, .set-list > .set-row:first-child { border-top: 0; }
a.set-row:hover { background: var(--paper); }
.set-row > .ico { flex: 0 0 20px; width: 20px; height: 20px; }
.set-txt { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 10px; }
.set-txt b { flex: none; font-weight: 650; }
.set-txt .muted { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .9rem; }
.set-row .badge { flex: none; }
.set-row .gear-link { flex: none; white-space: nowrap; }
.set-row > .set-end { flex: 0 0 156px; display: flex; align-items: center; justify-content: flex-end; gap: 8px; white-space: nowrap; } /* status pill and Run in one fixed column, so the link after it lines up on every row (Procedures) */
.set-chev { flex: none; color: var(--muted); font-size: 1.3rem; line-height: 1; }
.set-switch { flex: none; appearance: none; -webkit-appearance: none; position: relative; width: 42px !important; height: 24px; margin: 0; border-radius: 999px; background: var(--line); cursor: pointer; transition: background .15s ease; }
.set-switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(17, 17, 17, .3); transition: left .15s ease; }
.set-switch:checked { background: var(--grass); }
.set-switch:checked::after { left: 21px; }
.set-switch:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.set-savebar { position: sticky; top: 0; z-index: 4; display: flex; align-items: center; justify-content: space-between; gap: 10px; background: var(--paper); padding: 2px 0 12px; }
/* [Route] Service icons (includes/svc_icons.php): Services list, Service page, Route stop list and sheet */
.svc-ico { width: 16px; height: 16px; flex: none; vertical-align: -3px; margin-right: 6px; color: var(--grass-ink, #2E7D32); }
/* [Estimates] Estimates Type column: the work icons on one line, then +N (svc_icons_line) */
.svc-ico-line { display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; }
.svc-ico-line .svc-ico { margin-right: 0; }
.svc-ico-tip { display: inline-flex; }
.svc-name { display: inline-flex; align-items: center; }
.svc-ico-pick { display: flex; align-items: center; gap: 10px; }
.svc-ico-pick select { flex: 1; min-width: 0; }
.svc-ico-now { display: grid; place-items: center; width: 38px; height: 38px; flex: none; border: 1px solid var(--line); border-radius: 10px; background: #fff; }
.svc-ico-now .svc-ico { width: 22px; height: 22px; margin: 0; }
/* [Settings] Settings > Style > Theme: color rows (swatch + #hex) and the preview (a plain bordered frame, not a card) */
.set-color { display: flex; gap: 8px; align-items: center; }
.set-color input[type=color] { flex: none; width: 42px; height: 38px; padding: 2px; border: 1px solid var(--line); border-radius: 10px; background: #fff; cursor: pointer; }
.set-color input:not([type=color]) { min-width: 0; flex: 1; text-transform: uppercase; }
.st-preview { margin: 14px 0 4px; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; max-width: 520px; }
.st-pv-menu { display: flex; align-items: center; gap: 8px; padding: 10px 14px; background: var(--pv-menu); color: #fff; border-bottom: 3px solid var(--pv-accent); }
.st-pv-dot { width: 14px; height: 14px; border-radius: 50%; background: var(--pv-accent); }
.st-pv-body { background: var(--pv-paper); padding: 14px; }
.st-pv-card { background: #fff; border: 1px solid var(--card-edge, var(--line)); border-radius: var(--pv-r); padding: var(--card-pad, 12px 14px); box-shadow: var(--card-shadow, none); }
.st-pv-table { width: 100%; margin: 0 0 10px; }
.st-pv-table .pill { border-radius: var(--pill-radius, var(--pv-b)); }
.st-pick-btns { flex-wrap: nowrap; margin-top: 8px; } /* Undo and Reset: one line at every width */
.st-pv-card p { margin: 6px 0 10px; }
.st-pv-card a { color: var(--pv-brand); }
.st-pv-card .badge.done { background: var(--pv-accent); border-radius: var(--pv-b); }
.st-pv-btn { display: inline-block; background: var(--pv-brand); color: #fff; font-weight: 650; padding: 7px 16px; border-radius: var(--pv-b); }
.set-savebar:not(.mc-bar) { justify-content: flex-end; } /* no-JS fallback: just the Save button (no breadcrumb) */
.top .set-topsave { white-space: nowrap; }
@media (max-width: 520px) { .top .set-topsave-n { display: none; } } /* phones: just Save, the page name is beside it */
.set-words { margin: 0 0 14px; }
.set-word { display: grid; grid-template-columns: minmax(190px, 1fr) minmax(120px, 1.3fr) minmax(130px, 1.1fr) 72px; gap: 10px; align-items: center; padding: 5px 0; border-top: 1px solid var(--line); }
.set-words > .set-word:first-child { border-top: 0; }
.set-word > b.one-line { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* Tracker 885: a long word label stays on one line */
.set-word > input { min-height: 34px; padding-top: 5px; padding-bottom: 5px; }
.set-plural { min-width: 0; font-size: .86rem; color: var(--muted); }
.set-plural summary { cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; list-style: none; }
.set-plural summary::-webkit-details-marker { display: none; }
.set-plural summary b { color: var(--ink); font-weight: 600; text-decoration: underline dotted; text-underline-offset: 3px; }
.set-plural[open] summary { display: none; }
.set-plural input { min-height: 34px; padding-top: 5px; padding-bottom: 5px; width: 100%; }
.set-word button { min-height: 34px; padding: 4px 10px; }
@media (max-width: 800px) {
  .set-row { padding: 10px 14px; gap: 10px; }
  .set-txt { flex-direction: column; align-items: stretch; gap: 0; }
  .set-txt .muted { font-size: .85rem; }
  .set-row .gear-link span { display: none; }
  .set-row .badge { display: none; }
  .set-row > .set-end { flex-basis: 64px; }
  .set-word { grid-template-columns: minmax(0, 1fr) auto; row-gap: 3px; } /* Tracker 885: the label gets its own line on a phone */
  .set-word > b.one-line { grid-column: 1 / -1; }
  .set-word > input { grid-column: 1; grid-row: 2; }
  .set-word > :last-child:not(b) { grid-column: 2; grid-row: 2; }
  .set-word > .set-plural { grid-column: 1; grid-row: 3; font-size: .8rem; }
}
.hint { margin: 4px 0 0; font-size: .75rem; }
/* [Help and Docs] Card help (includes/help_text.php, docs/procedures/help-text.md): one line under a card title; when the entry
   has more to say it ends in a small More pill with a chevron, which opens What It Does / What It Changes / How to Use
   as labelled sections in the tip look (grass edge on paper), with the Help Article link. An entry with nothing more is
   just the line (.hint-plain: no pill, no panel, no Got It). Got It shrinks a card's hint to a small icon at its top right. */
.hint-box { margin: -2px 0 10px; font-size: .78rem; color: var(--muted); }
.hint-box > summary { display: flex; align-items: center; gap: 8px; min-width: 0; cursor: pointer; list-style: none; }
.hint-box > summary::-webkit-details-marker { display: none; }
.hint-line { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hint-plain .hint-line { white-space: normal; overflow: visible; }
.hint-box[open] .hint-line { white-space: normal; color: var(--ink); } /* opened: the whole sentence reads like a sentence */
.hint-more { flex: none; display: inline-flex; align-items: center; gap: 5px; height: 20px; padding: 0 8px 0 9px; border: 1px solid var(--line); border-radius: 999px; background: var(--card); color: var(--muted); font-size: .7rem; font-weight: 650; line-height: 1; white-space: nowrap; transition: color .15s, border-color .15s, background .15s; }
.hint-chev { width: 5px; height: 5px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-1px) rotate(45deg); transition: transform .15s; }
.hint-box[open] .hint-chev { transform: translateY(1px) rotate(-135deg); }
.hint-more-c, .hint-box[open] .hint-more-o { display: none; }
.hint-box[open] .hint-more-c { display: inline; }
.hint-box > summary:hover .hint-more, .hint-box[open] .hint-more { color: var(--blue); border-color: var(--blue); }
.hint-box > summary:focus-visible { outline: none; }
.hint-box > summary:focus-visible .hint-more { outline: 2px solid var(--blue); outline-offset: 1px; }
.hint-ico { display: none; }
.hint-body { margin-top: 8px; padding: 12px 14px; border: 1px solid var(--line); background: var(--paper); border-radius: 10px; color: var(--ink); }
/* [Help and Docs] one green bar: help fly-outs and the Website Build My Site card (.card.web-build beats each Style's .card border) */
.hint-body, .card.web-build { border-left: 3px solid var(--grass); }
.hint-dl { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px 22px; margin: 0; }
.hint-sec { min-width: 0; }
.hint-dl dt { font-size: .66rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.hint-dl dd { margin: 3px 0 0; min-width: 0; font-size: .8rem; line-height: 1.45; }
.hint-foot { display: flex; align-items: center; gap: 14px; margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line); white-space: nowrap; }
.hint-dl:empty + .hint-foot, .hint-body > .hint-foot:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.hint-foot a { font-weight: 650; }
.hint-foot a::after { content: " \2192"; }
.hint-foot .hint-seen { height: 28px; min-height: 28px; padding: 0 12px; font-size: .75rem; margin-left: auto; }
.hint-box .hint-seen[data-hint-seen="0"], .hint-box.is-seen .hint-seen[data-hint-seen="1"] { display: none; }
.hint-box.is-seen .hint-seen[data-hint-seen="0"] { display: inline-flex; }
.card:has(> .hint-box.is-seen) { position: relative; }
.card:has(> .hint-box.is-seen) > h2 { padding-right: 34px; }
.hint-box.is-seen:not([open]) { margin: 0; }
.hint-box.is-seen:not([open]) .hint-line, .hint-box.is-seen:not([open]) .hint-more { display: none; }
.hint-box.is-seen .hint-ico { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; color: var(--muted); }
.card > .hint-box.is-seen .hint-ico { position: absolute; top: 14px; right: 14px; }
.hint-field { margin: 4px 0 0; font-size: .75rem; }
.hint-field > summary { display: block; }
.hint-field .hint-line { white-space: normal; overflow: visible; }
.hint-field .hint-more { margin-left: 6px; height: 18px; padding: 0 7px 0 8px; font-size: .66rem; vertical-align: 1px; }
.hint-field[open] .hint-line { color: var(--muted); }
.hint-field .hint-body { margin-top: 6px; padding: 10px 12px; }
.hint-field .hint-dl { grid-template-columns: minmax(0, 1fr); gap: 8px; }
.hint-box.is-seen .hint-ico:hover, .hint-box.is-seen[open] .hint-ico { color: var(--blue); background: var(--paper); }
.hint-ico .ico { width: 18px; height: 18px; }
@media (max-width: 520px) {
  .hint-dl { grid-template-columns: minmax(0, 1fr); gap: 10px; }
}
.hint.bad { color: var(--red); }
.hint.good { color: #2f8f1c; }
.hint.bad a { color: inherit; font-weight: 600; }
.hint.bad a:hover { text-decoration: underline; }
.brand .twisted { color: var(--blue); }
.brand span { color: var(--grass); }
/* [Top Bar and Menus] Menu brand with the mascot: mascot on top, the name on its own line under it (one line; long names a size smaller, then an ellipsis). The gear stays beside the mascot. */
.brand.brand-stack { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; flex: 1 1 auto; min-width: 0; padding: 14px 8px 12px 18px; }
.brand-stack .ttm.ttm-logo { --ttm-size: 30px; margin: 0; }
.brand-stack .brand-name { display: block; max-width: 100%; white-space: normal; overflow-wrap: break-word; line-height: 1.2; } /* names show in full: long ones wrap */
.brand-stack .brand-name span { color: var(--grass); }
.brand-stack .brand-name .twisted { color: var(--blue); }
.brand-name.long { font-size: .92rem; }
.brand-name.xlong { font-size: .8rem; }
.brand-stack + .gear { align-self: flex-start; padding-top: 21px; }
.ico { width: 16px; height: 16px; flex: none; }
.side nav a, .logout { display: flex; align-items: center; gap: 8px; }
.top h1 { display: flex; align-items: center; gap: 8px; }
.stat span:not(.badge), .profit-top h2 { display: flex; align-items: center; gap: 6px; }
.calc-label { margin: 18px 0 4px; font-size: 1rem; }
.menu-btn { display: none; width: 40px; height: 40px; padding: 0; border: 0; background: transparent; color: var(--ink); }
.menu-btn svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.nav-shade { display: none; }
.nav-fold { margin: 2px 0 0; }
.nav-fold summary {
  list-style: none; cursor: pointer; color: #9a9a9a; margin: 0; padding: 10px 12px; border-radius: 8px;
  font-size: .68rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  display: flex; align-items: center; justify-content: space-between; line-height: 1.2;
}
.nav-fold summary::-webkit-details-marker { display: none; }
.nav-fold summary::after {
  content: ""; width: 6px; height: 6px; border-right: 2px solid #888; border-bottom: 2px solid #888;
  transform: rotate(45deg) translateY(-2px); flex: none;
}
.nav-fold[open] summary::after { transform: rotate(-135deg) translateY(-1px); }
.nav-fold summary:hover { background: rgba(255,255,255,.06); color: #fff; }
/* Folding sections inside a group (menu cleanup, Oct 23 2026: Money > Estimates, Pricing ...; Base > Tickets): one step in, lighter title */
.nav-subfold { margin: 0 0 0 10px; border-left: 1px solid rgba(255,255,255,.08); }
.nav-subfold > summary { padding: 7px 10px; font-size: .74rem; font-weight: 600; letter-spacing: .02em; text-transform: none; color: #bdbdbd; }
.nav-subfold > a { padding-left: 10px; }
.dw-menu-nav .nav-subfold > summary { text-transform: none; }
.phone-dock { display: none; }
.side > * { flex-shrink: 0; } /* scroll the menu instead of squashing items */
.side nav { display: flex; flex-direction: column; padding: 8px; gap: 2px; }
/* [Top Bar and Menus] Twisted Turf parent CRM button at the top of the side menu (the platform owner only): a small house quiet button, one line */
.side .btn.side-parent, .field-menu .btn.side-parent { display: flex; align-self: stretch; justify-content: flex-start; margin: 4px 8px 2px; height: 30px; min-height: 30px; padding: 0 12px; gap: 6px;
  font-size: .72rem; white-space: nowrap; overflow: hidden; min-width: 0; }
.field-menu .btn.side-parent { width: auto; margin: 4px 0 8px; } /* the Route menu (phone More): same standout pill, same as the side menu */
.side .btn.side-parent span, .field-menu .btn.side-parent span { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.side nav a { color: #eee; text-decoration: none; padding: 10px 12px; border-radius: 8px; }
/* [Shared] One highlighted row: hover only where a mouse can hover (a tap never leaves a second lit row), and sub rows use the same active look as top rows */
@media (hover: hover) { .side nav a:not(.active):hover { background: rgba(255,255,255,.06); } }
.side nav a.active, .side nav a.sub.active { background: var(--navy); color: #fff; box-shadow: inset 3px 0 0 var(--blue); }
.side nav a.sub {
  margin: 0 8px; padding: 4px 8px 4px 22px;
  font-size: 12px; line-height: 1.25; color: #c8c8c8;
  box-shadow: none;
}
.logout { margin: auto 8px 0; padding: 10px 12px; border-radius: 8px; color: #c8c8c8; text-decoration: none; font-size: .68rem; font-weight: 700; line-height: 1.2; }
.logout:hover { background: rgba(255,255,255,.06); color: #fff; }
.logout.logout-all { margin-top: 0; padding: 4px 12px 8px 34px; color: #8a8a8a; font-weight: 600; }
.version { margin: 0 8px 12px; padding: 4px 12px; color: #c8c8c8; font-size: 12px; line-height: 1.25; text-decoration: none; display: flex; align-items: center; gap: 8px; }
.version:hover { color: #fff; }
.content { margin-left: 220px; min-width: 0; }
/* [Top Bar and Menus] Toasts keep their spot under the top bar but float over the page, so one arriving or leaving never shoves the page.
   Sticky: a toast stays in view wherever the page is scrolled (a save that returns to #card far down the page still shows it). */
.notices { position: sticky; top: 0; z-index: 40; display: flow-root; height: 0; padding: 0 22px; }
.notices > .toast { box-shadow: 0 8px 24px rgba(16, 24, 40, .12); }
.notices > .toast:first-child { margin-top: 12px; }
.notices:empty { display: none; }
.top {
  padding: 0 22px; min-height: 48px; display: flex; align-items: center; justify-content: space-between; gap: 16px;
  background: var(--top-bg, #fff); border-bottom: 1px solid var(--top-line, var(--line));
  position: sticky; top: 0; z-index: 8; /* the page-top bar (Back, title, Save) stays pinned while the page scrolls, every page (Oct 18, 2026) */
}
/* [Top Bar and Menus] --top-h: the pinned bar's height (lmn.css sets its own). Toasts and in-page sticky strips sit just under it, not behind it. */
:root { --top-h: 48px; }
.content > .notices { top: var(--top-h); }
.settings-jump, .set-savebar, .dw-bar { top: var(--top-h); } /* estimate.css does .est-bar and .est-bulk */
.top-title { display: flex; flex-direction: row; align-items: center; gap: 8px; min-width: 0; }
.top h1 { margin: 0; display: flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 600; letter-spacing: 0; min-width: 0; }
.top h1 > span:not(.pc-test) { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* page titles never wrap (Oct 17, 2026) */
/* [Billing and Plans] Names are always shown in full (plans/naming.md): a long title wraps to a second line, never an ellipsis. */
.top h1 span { min-width: 0; white-space: normal; overflow-wrap: break-word; line-height: 1.15; }
.top-title.has-back h1 {
  height: 32px; padding: 0 12px; border-radius: 999px;
  background: var(--paper); border: 1px solid var(--line); font-size: 13px; font-weight: 650;
}
/* [Top Bar and Menus] Title + Test mode badge + top pills (Send Safety): hide the title badge (banner already says Test mode) and the page
   icon so "Send Safety" stays one line with spare room at tablet widths (Oct 17 2026). */
.top:has(.top-pills) .top-title > a.pc-test { display: none; }
.top:has(.top-pills) .top-title h1 > .ico, .top:has(.top-pills) .top-title h1 > svg { display: none; }
.back-link {
  display: inline-flex; align-items: center; gap: 2px; height: 32px;
  padding: 0 12px 0 6px; border-radius: 999px; border: 1px solid var(--line); background: #fff; color: var(--blue);
  text-decoration: none; font-size: 13px; font-weight: 650; white-space: nowrap;
}
.gear-link { display: inline-flex; align-items: center; gap: 4px; text-decoration: none; }
.gear-link:hover { text-decoration: underline; color: var(--ink); }
.back-link svg { width: 16px; height: 16px; }
.back-phone .back-link { display: none; } /* phone-only back (an open email/text conversation); desktop shows the list beside it */
.top-action { margin-left: auto; height: 32px; min-height: 32px; }
.back-link:hover { color: var(--ink); }
.live-clock { color: var(--muted); font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
main { padding: 16px 22px 48px; }
.stats { display: flex; gap: 12px; flex-wrap: wrap; margin: 8px 0 16px; }
.stats:has(+ p.muted) { margin-bottom: 0; }
.stat, .card { background: var(--card); border: 1px solid var(--card-edge, var(--line)); border-radius: 12px; box-shadow: none; }
.stat { padding: 14px 16px; min-width: 140px; }
.stat b { display: block; font-size: 1.35rem; min-height: 1.2em; font-weight: 650; }
/* [Estimates] A whole tile that is a link (Invoices, Estimates): same tile, no underline, blue border on hover (as in the portal). */
a.stat { color: var(--ink); text-decoration: none; }
a.stat:hover { border-color: var(--blue); }
.stat b a { text-decoration: none; }
.stat b a:hover { text-decoration: underline; }
.stat span:not(.badge), .muted, th { color: var(--muted); }
.card { padding: var(--card-pad, 18px 20px); margin-bottom: 16px; box-shadow: var(--card-shadow, 0 1px 2px rgba(17, 17, 17, .04)); }
h2 { font-size: calc(.95rem * var(--fs-scale, 1)); margin: 18px 0 10px; }
.card > h2:first-child { margin-top: 0; }
.card > .stats:first-child { margin-top: 0; }
.toast {
  position: relative; z-index: 40;
  display: flex; align-items: center; gap: 12px;
  margin: 0 0 10px; padding: 12px 12px 12px 16px;
  border-radius: 12px; font-weight: 650;
  border: 1px solid var(--line); overflow: hidden;
  animation: toast-in .22s ease; background: #fff; color: var(--ink);
}
.toast span { flex: 1; min-width: 0; }
.toast::before {
  content: ""; width: 9px; height: 9px; border-radius: 50%; flex: none;
}
.toast::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  transform-origin: left; animation: toast-life var(--toast-life, 6s) linear forwards;
}
.toast:hover::after { animation-play-state: paused; }
.toast.ok::before, .toast.ok::after { background: var(--grass); }
.toast.bad { background: var(--red); color: #fff; border-color: var(--red); }
.toast.bad::before, .toast.bad::after { background: #fff; }
.toast.warn { background: var(--orange); color: var(--ink); border-color: var(--orange); }
.toast.warn::before, .toast.warn::after { background: var(--ink); }
/* [Tasks and Tracker] Persistent warning (overdue steps): in normal flow above the card, one line with ellipsis, never floating. */
.alert-banner {
  display: block; margin: 0 0 12px; padding: 12px 16px; border-radius: 12px;
  background: var(--orange); color: var(--ink); border: 0;
  font-weight: 650; text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}
.alert-banner:hover { background: #d97706; color: var(--ink); }
/* Paused (Travis, Oct 21 2026 10:58 PM CT): red = Parent CRM turned it on, orange = the company did. One banner, one pill. */
.alert-banner.paused-parent { background: var(--red); color: #fff; }
.alert-banner.paused-parent:hover { background: var(--red); color: #fff; filter: brightness(.92); }
.badge.paused-parent { background: var(--red); color: #fff; }
.badge.paused-company { background: var(--orange); color: var(--ink); }
/* [Shared] Desktop (1280): one line with ellipsis. Phones: sentences may flow (Test Mode / Safe Mode). */
@media (max-width: 800px) {
  .alert-banner.wrap { white-space: normal; }
}
/* .toast-x: drawn by the shared X close (.x-close, Tracker 880). */
@keyframes toast-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
@keyframes toast-life { from { transform: scaleX(1); } to { transform: scaleX(0); } }
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: var(--t-pad, 11px 10px); border-bottom: 1px solid var(--t-line, var(--line)); vertical-align: middle; }
th { font-size: .72rem; letter-spacing: .05em; text-transform: uppercase; }
/* [Settings] Style tokens with no default (plans/site-and-style-editor.md step 1): zero specificity, so unset = today's look */
:where(th) { background-color: var(--t-head-bg); }
:where(tbody tr:nth-child(even) > td) { background-color: var(--t-stripe); }
tbody tr:hover td, table tr:hover td { background: var(--paper); }
th a { color: var(--muted); text-decoration: none; }
th a:hover { color: var(--ink); }
label { display: block; margin: 0 0 6px; color: var(--muted); font-size: .8rem; font-weight: 650; }
input:not([type="hidden"]) + label,
select + label,
textarea + label,
p + label,
select + button,
textarea + button,
p + button { margin-top: 14px; }
p + button.note-add { margin-top: 0; }
input, select, textarea {
  width: 100%;
  padding: var(--in-pad, 9px 11px);
  border: 1px solid var(--in-line, #d5deea);
  border-radius: var(--in-radius, 8px);
  font: inherit;
  color: var(--ink);
  background: #fff;
}
textarea { min-height: 84px; resize: vertical; }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--in-focus, var(--blue));
  box-shadow: 0 0 0 3px rgba(30, 144, 255, .16);
}
.stat b, td.num, .profit-figure, .list-count { font-variant-numeric: tabular-nums; }
button, .btn, .back-link, .side nav a { transition: background .15s ease, color .15s ease, border-color .15s ease; }
[hidden] { display: none !important; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 18px; align-items: start; }
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 0 18px; }
.split > div { display: grid; gap: 14px; align-content: start; }
.form-grid > div { min-width: 0; }
.tbc-line { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
#tbc-switch { margin: 0; }
.tbc-dates { display: flex; align-items: center; gap: 14px; }
.tbc-dates label { display: flex; align-items: center; gap: 8px; margin: 0; color: var(--ink); font-size: .85rem; font-weight: 650; }
.tbc-dates input { width: 64px; min-width: 64px; max-width: 64px; height: 36px; margin: 0; flex: none; }
.span-2 { grid-column: 1 / -1; }
.kpi-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 14px 0; }
.kpi-tile { display: flex; gap: 12px; align-items: center; min-width: 0; border: 1px solid var(--line); border-radius: 14px; padding: 12px 14px; background: linear-gradient(180deg, var(--paper), #fff); }
.kpi-tile > div { min-width: 0; }
.kpi-tile b { display: block; font-size: 1.15rem; }
.kpi-tile span, .kpi-tile em { display: block; color: var(--muted); font-style: normal; font-size: .8rem; }
.kpi-tile .badge { display: inline-block; margin-top: 6px; white-space: normal; }
.ring { width: 72px; height: 72px; flex: none; display: block; }
.chart-box { max-width: 100%; }
.chart-box svg { width: 100%; height: auto; display: block; overflow: visible; }
.legend { display: flex; flex-wrap: wrap; gap: 14px; margin: 0 0 8px; font-weight: 650; }
.legend i { display: inline-block; width: 10px; height: 10px; border-radius: 99px; margin-right: 6px; }
.hbar-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; margin: 8px 0 16px; }
.hbar-grid h3 { margin: 0 0 10px; font-size: .95rem; }
.hbar { display: grid; grid-template-columns: minmax(90px, 1.2fr) 2fr auto; gap: 10px; align-items: center; margin: 8px 0; }
.hbar span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hbar-track { display: block; height: 12px; background: var(--paper); border-radius: 99px; overflow: hidden; }
.hbar-track span { display: block; height: 100%; border-radius: 99px; }
.stand-head { display: flex; gap: 16px; align-items: center; margin-bottom: 8px; }
.rank-ring { width: 88px; height: 88px; flex: none; }
.rank-ring text:first-of-type { font-size: 18px; font-weight: 750; fill: var(--ink); }
.rank-ring text:last-of-type { font-size: 10px; fill: var(--muted); }
.split-bar { display: flex; height: 14px; border-radius: 99px; overflow: hidden; background: var(--paper); margin: 8px 0; }
.split-bar span { display: block; height: 100%; }
@media (max-width: 800px) {
  .kpi-tiles, .hbar-grid { grid-template-columns: 1fr; }
  .property-views { grid-template-columns: minmax(0, 1fr); }
}
a.lock, button.lock, .btn.lock { color: var(--red) !important; }
button.danger, .btn.danger { background: var(--red); color: #fff !important; border: 1px solid var(--red); }
button.danger:hover, .btn.danger:hover { background: #c42f24; color: #fff !important; border-color: #c42f24; }
.override-block {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  margin-top: 14px; padding: 14px 16px; border: 1px solid var(--line); border-radius: 14px;
  background: linear-gradient(180deg, var(--paper), #fff);
}
.override-block h4 { margin: 0 0 2px; font-size: .95rem; }
.bill-switch { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 12px 0; padding: 10px 12px; background: var(--paper); border: 1px solid var(--line); border-radius: 12px; }
.bill-switch span { font-size: .85rem; font-weight: 700; }
.override-field { display: flex; align-items: center; gap: 8px; }
.override-field span { font-weight: 750; color: var(--muted); }
.override-field input { width: 120px; height: 40px; margin: 0; }
.override-field button { height: 40px; }
.override-note { color: var(--muted); font-size: .75rem; font-weight: 650; }
table.roster td { vertical-align: middle; }
.list-bar {
  display: flex; flex-direction: row; align-items: center; gap: 10px; margin: 0 0 14px; flex-wrap: wrap;
  background: var(--paper); border: 1px solid var(--line); border-radius: 16px; padding: 8px;
}
.list-results { transition: opacity .15s ease; }
.list-results.is-loading, .sheet.is-loading { opacity: .45; }
.list-bar label, .list-bar p { margin: 0; }
.list-bar input[type="month"] {
  height: 42px; border-radius: 999px; background: #fff; border: 1px solid transparent; padding: 0 14px; font: inherit; width: auto;
}
.sheet tr.due-total td { font-weight: 750; background: var(--paper); }
.list-search, .list-size { position: relative; margin: 0; display: flex; align-items: center; }
.list-search { flex: 1; min-width: 180px; }
.status-filter { position: relative; }
.status-filter summary {
  list-style: none; height: 42px; padding: 0 16px; border-radius: 999px; background: var(--paper);
  display: flex; align-items: center; cursor: pointer; font-weight: 650; white-space: nowrap; max-width: 280px; overflow: hidden;
}
.status-filter summary::-webkit-details-marker { display: none; }
.status-filter[open] summary { background: #fff; box-shadow: inset 0 0 0 1px var(--teal); }
.status-menu {
  position: absolute; z-index: 6; top: 48px; left: 0; min-width: 230px; padding: 10px 12px;
  background: #fff; border: 1px solid var(--line); border-radius: 14px; box-shadow: 0 12px 30px rgba(11, 42, 69, .12);
}
.status-menu .check { display: flex; margin: 6px 0; }
.status-menu { max-width: calc(100vw - 24px); max-height: min(70vh, 520px); overflow-y: auto; box-sizing: border-box; }
.status-menu.is-right { left: auto; right: 0; }
.list-search span, .list-size span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.list-search input, .list-size select {
  height: 42px; margin: 0; border-radius: 999px; background: var(--paper); border: 1px solid transparent;
}
.list-search input { padding-left: 16px; }
.list-search input:focus, .list-size select:focus { background: #fff; border-color: var(--teal); outline: none; }
.list-size select { width: 118px; }
.command .list-bar:not(.lb) select {
  width: auto; height: 42px; margin: 0; padding: 0 32px 0 16px;
  border-radius: 999px; background: var(--paper); border: 1px solid transparent; font-weight: 650; text-align: left;
}
.command .list-bar:not(.lb) select:focus { background: #fff; border-color: var(--teal); outline: none; }
.list-count { margin: 0 0 0 auto; color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.pager { display: flex; gap: 6px; justify-content: flex-end; flex-wrap: wrap; margin-top: 14px; }
.pager a, .pager .gap {
  min-width: 36px; height: 36px; padding: 0 10px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 10px; background: var(--paper); color: var(--ink); text-decoration: none; font-weight: 650;
}
.pager a.on { background: var(--blue); color: #fff; }
.pager a:hover { background: #e5eef6; }
.profile h2, .profile h3 { margin: 0 0 4px; }
.badge { display: inline-block; background: var(--paper); color: var(--ink); border-radius: var(--pill-radius, 99px); padding: var(--pill-pad, 3px 10px); font-size: var(--pill-fs, .8rem); font-weight: 650; white-space: nowrap; }
a.badge { text-decoration: none; color: var(--ink); }
p.muted {
  margin: 4px 0 12px;
  font-size: .75rem;
  line-height: 1.35;
}
.card > h2 + p.muted,
.card > h3 + p.muted { margin-top: -2px; margin-bottom: 8px; }
/* Clickable status dot (Oct 22 2026, Travis 7:49 PM "a clickable status DOT/circle (like the existing green status dot... reuse that CSS)"):
   a <button class="sx-dot ok|down"> is the same dot, as a button. */
button.sx-dot, .card button.sx-dot { flex: none; border: 0; padding: 0; width: .75rem; height: .75rem; min-width: 0; min-height: 0; box-shadow: none; vertical-align: middle; cursor: pointer; margin: 0 .25rem; background: var(--grass); }
button.sx-dot.down, .card button.sx-dot.down { background: var(--red); }
button.sx-dot:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.badge.overdue { background: var(--pill-overdue, var(--red)); color: #fff; }
.badge.waiting, .badge.lump { background: var(--pill-waiting, #fff); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
.badge.planned, .badge.next, .badge.monthly { background: var(--pill-planned, var(--blue)); color: #fff; }
.badge.done { background: var(--pill-done, var(--grass)); color: var(--ink); }
.badge.each { background: var(--pill-done, var(--grass)); color: var(--ink); }
/* [Estimates] Palette badges (the Tags colors): company-picked colors for Estimate Statuses and Service Types (pal-<key>, st_colors()). Same hex as tag_colors() in every Style; a Style only changes its own UI colors. */
:root { --pal-blue: #1E90FF; --pal-green: #5CDB3A; --pal-orange: #F08A24; --pal-red: #E23B2F; --pal-navy: #163A5F; --pal-gray: #6A6E74; --pal-black: #111111; --pal-purple: #8B5CF6; --pal-blue-strong: #1673D1; }
.badge.pal-blue { background: var(--pal-blue); color: #fff; }
.badge.pal-green { background: var(--pal-green); color: var(--pal-black); }
.badge.pal-orange { background: var(--pal-orange); color: var(--pal-black); }
.badge.pal-red { background: var(--pal-red); color: #fff; }
.badge.pal-navy { background: var(--pal-navy); color: #fff; }
.badge.pal-gray { background: var(--pal-gray); color: #fff; }
.badge.pal-black { background: var(--pal-black); color: #fff; }
.badge.pal-white { background: #fff; color: var(--pal-black); box-shadow: inset 0 0 0 1px var(--pal-gray); }
/* .rt-line .badge: shared pill size (Tracker 880) */
.when-overdue { color: var(--red); font-weight: 700; }
.tabs { display: flex; gap: 8px; flex-wrap: nowrap; overflow-x: auto; margin: 0 0 14px; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tabs a { flex: none; padding: 8px 14px; border-radius: 999px; background: #fff; border: 1px solid var(--line); color: var(--ink); text-decoration: none; font-weight: 700; }
.tabs a.on { background: var(--blue); border-color: var(--blue); color: #fff; }
.week-picks { display: flex; flex-wrap: wrap; gap: 8px 16px; }
.week-picks .check { margin: 0; max-width: 100%; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* one line each, "…" on phones (no wrapping, Oct 17, 2026) */
.week-picks.ttl-tricks { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 330px), 1fr)); gap: 2px 16px; } /* Settings > Sprout tricks: one even column per trick, no ragged rows (Oct 17, 2026) */
.week-picks.ttl-tricks .check > input { flex: none; }
.ttl-picks { flex-wrap: wrap; gap: 6px; } /* Settings > Sprout: one small chip per trick (Oct 19 2026) */
.ttl-picks > .status-filter.ttl-pick > summary { height: 30px; padding: 0 12px; font-size: .82rem; }
.ttl-picks > .status-filter.ttl-pick .status-menu { top: 36px; min-width: 180px; }
.ttm-preview .tabs.sides { margin: 0; min-width: 170px; grid-template-columns: repeat(3, auto); flex-wrap: nowrap; }
button.quiet.ttl-play { flex: none; height: var(--btn-h-sm); min-height: var(--btn-h-sm); padding: var(--btn-pad-sm); } /* Play, then Stop (■) while that trick runs */
button.quiet.ttl-play.on { border-color: var(--blue); color: var(--blue); }
button.quiet.ttl-play.ttl-pv { margin-top: 6px; }
.rank-medal, .rank-plain {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; height: 26px; padding: 0 8px; border-radius: 999px;
  font-size: 12px; font-weight: 750; line-height: 1; letter-spacing: 0;
}
.rank-medal.m1 { background: var(--grass); color: var(--ink); }
.rank-medal.m2 { background: var(--blue); color: #fff; }
.rank-medal.m3 { background: var(--navy); color: #fff; }
.rank-plain { background: transparent; color: var(--muted); font-weight: 700; }
table.standings th:first-child, table.standings td:first-child { width: 78px; text-align: center; }
td.spark { width: 140px; }
svg.rv-trend { display: block; width: 100%; height: 28px; margin-top: 6px; } /* Reviews trend line */
svg.rv-trend .rv-area { fill: var(--blue); opacity: .12; }
svg.rv-trend .rv-line { fill: none; stroke: var(--blue); stroke-width: 2; }
td.spark span { display: block; height: 10px; border-radius: 99px; background: linear-gradient(90deg, var(--line), var(--blue)); }
.assign-card { border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; margin: 12px 0; background: #fbfcfe; }
.assign-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.assign-head h3 { margin: 0 0 8px; }
.assign-head form { margin: 0; flex: none; display: flex; align-items: center; gap: 8px; }
.assign-head .btn { height: var(--btn-h-sm); min-height: var(--btn-h-sm); padding: var(--btn-pad-sm); font-size: var(--btn-fs-sm); }
select.reason {
  width: 112px; min-width: 112px; height: 30px; min-height: 30px; margin: 0; padding: 0 26px 0 12px;
  flex: none; font-size: .78rem; font-weight: 650; line-height: 1; border-radius: 999px;
  appearance: none; -webkit-appearance: none;
  background-color: #fff;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path fill='none' stroke='%236A6E74' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M2.5 4.5 6 8l3.5-3.5'/></svg>");
  background-repeat: no-repeat; background-position: right 8px center; background-size: 12px 12px;
}
.form-grid select.reason { width: 100%; min-width: 0; margin-top: 8px; }
.assign-head select.reason { width: 112px; height: 28px; min-height: 28px; }
form.drop { display: inline-flex; align-items: center; justify-content: flex-end; gap: 6px; margin: 0; vertical-align: middle; }
p + form.drop { margin-top: 8px; }
/* [Shared] In Use box, Move to Another (includes/activity_uses.php): the picker keeps the standard select width and its "Pick a Vendor"
   placeholder instead of being squeezed to a blank box on a phone; Reason + button wrap to the next row when it's narrow. */
form.drop.move-in-use { display: flex; flex-wrap: wrap; justify-content: flex-start; }
form.drop.move-in-use select[name=move_to] { flex: 1 1 220px; width: auto; min-width: 0; max-width: 360px; }
@media (max-width: 600px) { form.drop.move-in-use select[name=move_to] { flex-basis: 100%; max-width: 100%; } }
select.reason + button,
select.reason + .btn,
form.drop select.reason + button,
.row select.reason + button,
.assign-head select.reason + button { margin-top: 0; }
table.log td { vertical-align: middle; }
tr.undone td { color: var(--muted); }
.badge.name { background: var(--navy); color: #fff; font-weight: 750; }
.pills { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.assign-form { margin-top: 8px; }
.assign-form .form-grid { margin-bottom: 4px; }
.property-views { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 16px; }
.property-views .card { margin-bottom: 0; min-width: 0; } /* minmax(0, …) + min-width 0: a card's one-line help line ends in "…" instead of pushing the page sideways (rules check 1024/820, Oct 18 2026) */
.property-views iframe, #lot-map { width: 100%; height: 320px; border: 0; border-radius: 10px; background: var(--paper); }
.lot-note { margin: 8px 0 0; font-size: .8rem; }
#pin-map { height: 380px; border-radius: 10px; border: 1px solid var(--line); }
.map-hold { position: relative; z-index: 0; border-radius: 10px; }
.map-hold > .leaflet-container,
.map-hold > iframe { position: relative; z-index: 1; display: block; }
.map-hold:not(.is-live) > .leaflet-container { pointer-events: none !important; touch-action: auto !important; }
.map-hold:not(.is-live) > iframe { pointer-events: none; }
.map-hold.is-live > iframe { pointer-events: auto; }
.map-shield {
  position: absolute; inset: 0; z-index: 2; margin: 0; padding: 0;
  border: 0; border-radius: inherit; background: transparent; cursor: pointer;
}
.map-hold.is-live .map-shield { display: none; }
/* [Customers and Properties] Property satellite embed (includes/parcel.php): tap areas over Google's own card, which the Move lock covers. Google's
   card by map width: < 400px an "Open in Maps" pill at the top left; 400px+ the address card; 500px+ adds Directions. */
.map-gcard { container-type: inline-size; }
.map-gopen, .map-gdir { position: absolute; z-index: 3; display: block; background: transparent; border-radius: 8px; -webkit-tap-highlight-color: rgba(26, 115, 232, .15); }
.map-gopen { top: 8px; left: 8px; width: 132px; height: 36px; }
.map-gdir { display: none; }
.map-hold.is-live .map-gopen, .map-hold.is-live .map-gdir { display: none; }
@container (min-width: 400px) { .map-gopen { top: 8px; left: 8px; width: 154px; height: 106px; } }
@container (min-width: 500px) { .map-hold:not(.is-live) .map-gdir { display: block; top: 66px; left: 164px; width: 38px; height: 38px; } }
/* [Customers and Properties] Street View card (includes/parcel.php, assets/js/sv-view.js). .sv-pano: the Maps JavaScript panorama, same size and Move
   lock as the old frame. .sv-acts: Reset View and Save View in fixed spots; a hidden one keeps its space (no layout jumping).
   Phones: Reset stacked above Save, both on the right. .sv-open: tap area over the old frame's address card. */
.property-views .sv-pano, .sv-demo { width: 100%; height: 320px; border-radius: 10px; background: var(--paper); overflow: hidden; }
.map-hold > .sv-pano { position: relative; z-index: 1; display: block; }
.map-hold:not(.is-live) > .sv-pano { pointer-events: none; }
.sv-demo { position: relative; display: grid; place-items: center; align-content: center; gap: 10px; color: var(--muted); font-size: 15px; line-height: 1.3; }
.sv-open { position: absolute; z-index: 3; top: 10px; left: 10px; width: 162px; height: 56px; pointer-events: auto; display: block; background: transparent; }
.sv-acts { display: flex; justify-content: flex-end; gap: 8px; margin-top: 10px; }
.sv-acts > button { white-space: nowrap; }
.sv-acts > .is-off { visibility: hidden; pointer-events: none; }
@media (max-width: 420px) { .sv-acts { flex-direction: column; align-items: flex-end; } }
.req { color: #b42318; margin-left: 3px; }
.one { color: var(--blue); margin-left: 3px; }
.use-row { display: flex; gap: 18px; flex-wrap: wrap; margin-top: 6px; }
.stack { display: block; width: 100%; margin-top: 16px; clear: both; }
input.rate-in { max-width: 110px; }
.rate-box { border: 1px solid var(--line); border-radius: 10px; padding: 14px 16px 16px; background: var(--paper); }
.rate-box h3 { margin: 0 0 12px; font-size: .95rem; }
.rate-box[hidden] { display: none; }
.rate-box .form-grid { grid-template-columns: 1fr 1fr 1fr; }
.checks { display: grid; gap: 8px; margin: 14px 0; }
.checks.inline { display: flex; flex-wrap: wrap; gap: 8px 16px; } /* a row of options (MySQL > Backup Database): standard gaps, the same space above and below */
input[type="checkbox"] { width: auto; }
label.check { display: flex; align-items: center; gap: 8px; color: var(--ink); font-weight: 500; margin: 0; }
label.check > .one-line { flex: 1 1 auto; min-width: 0; } /* its text ends in "…" only when the row is really full */
button, .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  background: var(--blue); color: #fff; border: 1px solid var(--blue); border-radius: var(--btn-radius, 999px);
  height: var(--btn-h); min-height: var(--btn-h); padding: var(--btn-pad); line-height: 1;
  text-decoration: none; cursor: pointer; font: inherit; font-weight: 650;
  font-variant-numeric: lining-nums proportional-nums;
  -webkit-appearance: none; appearance: none;
}
.btn.quiet, button.quiet {
  background: #fff; color: var(--ink); border: 1px solid var(--line);
}
button:not(.quiet):not(.danger):not(.nudge):not(.pick):not(.toast-x):not(.x-close):not(.act):not(.note-add):not(.pic-shot):not(.pic-del):not(.sort):not(.tag-x):not(.top-more-item):not(.sp-btn):not(.wxw-fr):not(.wxw-ab):not(.map-move):not(.pn-switch):not(.tile):not(.sx-dot):hover,
.btn:not(.quiet):not(.danger):hover {
  background: #1873cc;
  color: #fff;
  border-color: #1873cc;
}
.btn.quiet:hover, button.quiet:hover {
  background: var(--paper);
  color: var(--ink);
  border-color: var(--blue);
}
.row { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 16px; }
.row.section-end { margin-bottom: 16px; }
.row.preview-size { margin-top: 10px; align-items: end; }
.row.preview-size input { width: 140px; }
.pill { display: inline-block; background: var(--paper); color: var(--ink); border-radius: var(--pill-radius, 999px); padding: var(--pill-pad, 3px 10px); font-size: var(--pill-fs, .8rem); font-weight: 650; }
.pill.on { background: var(--ink); color: #fff; }
.review-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 14px; }
.review-bar form { display: flex; margin: 0; }
.review-bar input[type="month"] {
  width: 170px; height: 36px; margin: 0; text-align: center; background: #fff;
  border: 1px solid var(--line); border-radius: 999px; font-weight: 700; padding: 0 12px;
}
/* [Reports] Reports > Review Month picker (Prev / month / Next): one line at every width; the month box gives way first. */
.review-bar .month-picker { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; min-width: 0; max-width: 100%; }
.review-bar .month-picker > .btn { flex: none; white-space: nowrap; }
.review-bar .month-picker > form { flex: 0 1 auto; min-width: 0; }
.review-views { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }
.review-views a { white-space: nowrap; }
.review-bar .review-views:first-child:last-child { margin-left: 0; }
.review-views a {
  display: inline-flex; align-items: center; justify-content: center; height: 36px; padding: 0 14px;
  border-radius: 999px; border: 1px solid var(--line); background: #fff; color: var(--ink);
  text-decoration: none; font-weight: 700; font-size: .85rem;
}
.review-views a.on { background: var(--blue); color: #fff; border-color: var(--blue); }
.card > .review-sheet { margin: 0; }
/* [Reports] Reports > Review: a wide table scrolls inside its own box; the page itself never scrolls sideways. */
.review-sheet { max-width: 100%; min-width: 0; overflow-x: auto; }
.review-sheet table { width: 100%; }
.review-sheet th, .review-sheet td { text-align: left; }
.review-sheet th:first-child, .review-sheet td:first-child { width: auto; text-align: left; }
.review-sheet th + th, .review-sheet td + td { padding-left: 22px; }
/* [Base and Services] Oct 19, 2026: at a tablet width the Services view's Program, Chemical and Labor (.lc-c) step out under a 600px sheet, the
   house list rule, so the table fits its card instead of scrolling sideways (the month's Chemical and Labor stay in the tiles). */
@media (min-width: 801px) { .review-sheet:has(> table .lc-c) { container-type: inline-size; } }
@media (max-width: 800px) {
  .review-bar { display: grid; grid-template-columns: 1fr 1fr; }
  .review-bar form, .review-views, .review-bar .month-picker { grid-column: 1 / -1; }
  .review-bar .month-picker { gap: 6px; }
  .review-bar .month-picker > form { flex: 1 1 0; }
  .review-bar input[type="month"] { width: 100%; min-width: 0; }
  .review-views { margin: 0; display: grid; grid-template-columns: 1fr 1fr; }
  .review-views a { padding: 0 8px; font-size: .8rem; }
}
@media (max-width: 360px) {
  .review-views { grid-template-columns: 1fr; }
  .review-bar input[type="month"] { padding: 0 8px; font-size: .85rem; }
}
.error { color: var(--ink); }
.login {
  min-height: 100dvh; display: grid; place-items: center; background: var(--ink);
  padding: calc(24px + env(safe-area-inset-top, 0px)) 24px calc(24px + env(safe-area-inset-bottom, 0px));
}
.login h1 { margin: 0 0 8px; color: var(--blue); }
.login h1 span { color: var(--grass); }
.login .card { width: min(420px, 100%); }
.lost {
  min-height: 100dvh; display: grid; place-items: center; background: var(--ink); color: #fff;
  padding: calc(24px + env(safe-area-inset-top, 0px)) 16px calc(24px + env(safe-area-inset-bottom, 0px));
}
.lost main { width: min(560px, 100%); }
.lost-brand { display: inline-block; margin: 0 0 14px; color: var(--blue); font-weight: 750; font-size: 1.15rem; letter-spacing: -.02em; text-decoration: none; }
.lost-brand span { color: var(--grass); }
.lost-card { background: #fff; color: var(--ink); border-radius: 22px; overflow: hidden; box-shadow: 0 18px 40px rgba(0, 0, 0, .28); }
.lost-art svg { display: block; width: 100%; height: auto; }
.lost-card h1 { margin: 0 16px 8px; font-size: 1.55rem; letter-spacing: -.03em; line-height: 1.15; }
.lost-kicker { margin: 14px 16px 4px; color: var(--muted); font-size: .72rem; font-weight: 750; letter-spacing: .06em; text-transform: uppercase; }
.lost-line { margin: 0 16px 12px; color: var(--muted); }
.lost-card .row { margin: 8px 16px 18px; }
.lost-card .hint { margin: -8px 16px 18px; }
.lost-pin { transform-origin: 392px 176px; animation: lost-bob 2.4s ease-in-out infinite; }
.lost-mower { animation: lost-roll 3.6s ease-in-out infinite; }
@keyframes lost-bob { 50% { transform: translateY(6px); } }
@keyframes lost-roll { 50% { transform: translateX(10px); } }
.address-wrap { position: relative; }
.picks {
  position: absolute; z-index: 8; left: 0; right: 0; top: calc(100% - 4px);
  background: #fff; border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 8px 24px rgba(12, 35, 64, .12);
}
.pick {
  display: block; width: 100%; text-align: left; background: #fff; color: var(--ink);
  border: 0; border-radius: 0; border-bottom: 1px solid var(--line);
  padding: 10px 12px; font-weight: 500;
}
.pick:hover { background: var(--paper); }
@media (max-width: 800px) {
  html, body { width: 100%; max-width: 100%; }
  .shell, .content, main { width: 100%; max-width: 100%; min-width: 0; }
  .menu-btn { display: inline-flex; align-items: center; justify-content: center; }
  .side { transform: none; left: -320px; transition: left .2s ease; width: min(280px, 86%); z-index: 30; padding-top: max(47px, env(safe-area-inset-top, 0px)); padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px)); /* clear the phone dock so Log out + version scroll into view */ }
  body.nav-open .side { left: 0; transform: none; }
  body.nav-open .nav-shade { display: block; position: fixed; inset: 0; background: rgba(8, 20, 32, .45); z-index: 20; }
  .content { margin-left: 0; max-width: 100%; overflow-x: clip; }
  /* Keep the menu under the iPhone clock and island. Do not set this padding back to 0. */
  .top { position: sticky; top: 0; z-index: 8; width: 100%; max-width: 100%; min-width: 0; overflow: visible; /* not hidden: the ⋯ menu drops below the header; .content clips sideways */ justify-content: flex-start; gap: 10px; padding-top: env(safe-area-inset-top, 0px); /* exactly the status bar in a home-screen install, none in Safari */ background: var(--top-bg, #fff); }
  .top-title, .top h1 { flex: 1 1 auto; min-width: 0; overflow: hidden; }
  /* Phone: Back is the round chevron only so the title pill keeps the room to read on one line. */
  .back-phone .back-link { display: inline-flex; }
  .back-link { flex: none; width: 32px; padding: 0; justify-content: center; }
  .back-link span { display: none; }
  .top-title { gap: 6px; }
  .top-title.back-phone h1 { height: 32px; border-radius: 999px; background: var(--paper); border: 1px solid var(--line); font-size: 13px; font-weight: 650; }
  .top-title.has-back h1, .top-title.back-phone h1 { padding: 0 10px; }
  /* A long title stays on one line (no wrapping, Oct 17, 2026): ending in "…" when it runs out of room; the page itself says the rest. */
  .top h1 { overflow: hidden; }
  .top h1 > span:not(.pc-test) { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  span.pc-test { display: none; } /* the Test banner already says it; the title keeps the room */
  .top-title.has-back h1, .top-title.back-phone h1 { height: 32px; }
  .top-title.has-back h1 > svg, .top-title.has-back h1 > .ico, .top-title.back-phone h1 > svg, .top-title.back-phone h1 > .ico { display: none; }
  /* Reports: the All Reports icon repeats Back to Reports, so the phone drops it. */
  .top-title.has-back ~ .top-actions a.top-ico[href="reports.php"] { display: none; }
  .live-clock { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .form-grid, .split, .rate-box .form-grid { grid-template-columns: 1fr; }
  .override-block { flex-direction: column; align-items: stretch; }
  .span-2 { grid-column: auto; }
  main, .top { padding-left: 16px; padding-right: 16px; }
  .content > .notices { top: calc(var(--top-h) + env(safe-area-inset-top, 0px)); padding: 0 16px; } /* just under the sticky phone header */
  .settings-jump, .set-savebar, .dw-bar { top: calc(var(--top-h) + env(safe-area-inset-top, 0px)); }
  main { max-width: 100%; min-width: 0; padding-bottom: 120px; padding-bottom: calc(120px + env(safe-area-inset-bottom, 0px)); }
  .property-views { grid-template-columns: minmax(0, 1fr); }
  .profit-top { flex-wrap: wrap; align-items: flex-start; }
  .profit-year { width: 100%; align-items: flex-start; }
  .command { max-width: 100%; min-width: 0; }
  input, select, textarea { min-width: 0; max-width: 100%; font-size: 16px; }
  /* iOS zooms into any field under 16px: same rule, made to win over smaller field styles (Help Ask box, pills, tag box, editors). */
  input:not([type=checkbox]):not([type=radio]), select, textarea { font-size: 16px !important; }
  /* Date and time fields: iOS Safari gives them their own width and height (wider than the box, taller or collapsed when empty). Same size as the other fields. Phone only. */
  input[type=date], input[type=time], input[type=datetime-local], input[type=month] { -webkit-appearance: none; appearance: none; display: block; min-width: 0; max-width: 100%; min-height: 43px; }
  input::-webkit-date-and-time-value { text-align: left; min-height: 1.5em; }
  .phone-dock {
    display: grid; grid-template-columns: repeat(var(--tabs, 4), minmax(0, 136px)); justify-content: space-evenly; /* 1-5 tabs (Settings > Bottom Menu): equal up to 136px each, centered when few */
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
    width: 100%; max-width: 100%; box-sizing: border-box; touch-action: manipulation;
    background: var(--ink); border-top: 3px solid var(--grass); padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
    transform: translateY(var(--dock-drop, 0px)); /* Edge on iPhone, toolbar folded away: flush with the real bottom (phone_tabs.php) */
  }
/* tab count from a class (was an inline --tabs, Route redo Oct 23 2026) */
.phone-dock.pd-tabs-1 { --tabs: 1; } .phone-dock.pd-tabs-2 { --tabs: 2; } .phone-dock.pd-tabs-3 { --tabs: 3; } .phone-dock.pd-tabs-4 { --tabs: 4; } .phone-dock.pd-tabs-5 { --tabs: 5; } .phone-dock.pd-tabs-6 { --tabs: 6; }
  .phone-dock a, .phone-dock button {
    display: flex; flex-direction: column; align-items: center; gap: 2px; background: transparent; border: 0;
    color: #c8c8c8; font-size: .68rem; text-decoration: none; padding: 4px 0; box-shadow: none;
    -webkit-tap-highlight-color: transparent;
  }
  .phone-dock button:hover, .phone-dock button:focus, .phone-dock button:active {
    background: transparent !important; border-color: transparent !important; color: #c8c8c8 !important; box-shadow: none !important;
  }
  body.nav-open .phone-dock #dock-menu,
  body.nav-open .phone-dock #dock-menu:hover,
  body.nav-open .phone-dock #dock-menu:focus,
  body.nav-open .phone-dock #dock-menu:active { color: #fff !important; background: transparent !important; }
  .phone-dock .on, .phone-dock a.on, .phone-dock a:hover { color: #fff; }
  .phone-dock .ico { width: 18px; height: 18px; }
  .phone-dock a, .phone-dock button { min-width: 0; }
  .phone-dock button { height: auto; min-height: 0; font-weight: inherit; line-height: inherit; } /* More: same box and type as the tabs (the global button height cut its name) */
  /* Tab names: one line, every tab, always shown. Sizes are the ones from before the first shrink (59d3f33^, style.css v427):
     icon 18px, name .68rem, line-height 1.15, bar padding 6px 4px; the Base tab is named "Command" here so it fits
     at 390 and 375 (Travis, Oct 16). No icon-only fallback and no smaller steps. */
  .phone-dock span { flex: none; max-width: 100%; text-align: center; line-height: 1.15; white-space: nowrap; }
  /* Bottom Menu look (includes/bottom_menu.php): icons only = bigger icons; text only = bigger names, same bar height. */
  .phone-dock.bm-notext span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .phone-dock.bm-notext .ico { width: 24px; height: 24px; }
  .phone-dock.bm-notext a, .phone-dock.bm-notext button { padding: 6px 0 7px; }
  .phone-dock.bm-noicon .ico { display: none; }
  .phone-dock.bm-noicon a, .phone-dock.bm-noicon button { justify-content: center; min-height: 37px; font-size: .78rem; font-weight: 650; }
  .phone-dock span { overflow: hidden; text-overflow: ellipsis; }
  .assign-head { flex-direction: column; align-items: stretch; gap: 10px; }
  .assign-head .pills { min-width: 0; }
  .assign-head form { justify-content: flex-end; flex-wrap: wrap; }
  .badge.name { border-radius: 12px; line-height: 1.25; max-width: 100%; white-space: normal; }
  .visit summary { flex-direction: column; align-items: stretch; gap: 6px; }
  .visit summary > span { min-width: 0; }
}

.profit-card { display: block; color: inherit; text-decoration: none; }
.profit-card:hover { border-color: var(--line); }
.profit-card h2 { margin: 0; }
.profit-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.profit-figure { font-size: 1.7rem; line-height: 1; }
.profit-year { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.profit-top > div:first-child { min-width: 0; }
.profit-year div { display: grid; grid-template-columns: auto 4.6rem; align-items: center; gap: 8px; }
.profit-year b { justify-self: end; text-align: right; }
.profit-year span, .profit-col em { color: var(--muted); font-style: normal; font-size: .72rem; }
.profit-bars { display: grid; grid-template-columns: repeat(12, 1fr); gap: 6px; align-items: end; height: 86px; margin-top: 14px; }
.profit-col { display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; min-width: 0; }
.profit-col span { display: block; width: 100%; max-width: 18px; min-height: 3px; border-radius: 5px 5px 2px 2px; background: var(--line); }
.profit-col.real span { background: var(--blue); }
.profit-col.predict span { background: var(--grass); }
.profit-col.now em { color: var(--ink); font-weight: 750; }
.visit { border: 1px solid var(--line); border-radius: 12px; background: #fff; margin: 8px 0; }
.visit summary { cursor: pointer; list-style: none; padding: 12px 14px; display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.visit summary::-webkit-details-marker { display: none; }
.visit .body { padding: 0 14px 14px; }
.visit summary > span { min-width: 0; max-width: 100%; } /* its lines are .one-line: date + Service, property + products, weather (rules check, Oct 18 2026) */
.visit .body > p.visit-when { margin: 0 0 12px; text-align: left; text-align-last: left; word-spacing: normal; letter-spacing: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* time · length · technician: one line, "…" when full */
.wx { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 12px; }
.wx span { background: var(--paper); border: 1px solid var(--line); border-radius: 999px; padding: 4px 10px; font-size: .8rem; }
.chem-places { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; margin: 8px 0 16px; }
.chem-place { border: 1px solid var(--line); border-radius: 14px; padding: 12px 14px; background: var(--paper); }
.chem-place h4 { margin: 0 0 8px; }
.chem-place ul { list-style: none; margin: 0; padding: 0; }
.chem-place li { display: flex; justify-content: space-between; gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--line); font-size: .85rem; }
.chem-place li:last-child { border-bottom: 0; }
.chem-place li span { min-width: 0; flex: 1; }
.chem-place li b { white-space: nowrap; flex: none; text-align: right; font-weight: 650; }
table.chem { width: 100%; border-collapse: collapse; }
table.chem th, table.chem td { text-align: left; padding: var(--t-pad, 8px 10px); border-bottom: 1px solid var(--t-line, var(--line)); vertical-align: top; }
table.chem tr.due-total td { font-weight: 750; background: var(--paper); }
table.chem-log { table-layout: fixed; }
table.chem-log col.where { width: 96px; }
table.chem-log col.used { width: 190px; }
table.chem-log col.rate { width: 24%; }
table.chem-log col.how { width: 16%; }
table.chem-log th:nth-child(2), table.chem-log td:nth-child(2) { white-space: nowrap; }
table.chem-log td:nth-child(3) { white-space: normal; }
table.chem-log td:first-child { overflow-wrap: anywhere; }
table.chem-log .ing { display: grid; gap: 2px; margin-top: 4px; }
table.chem-log .ing span { display: block; }
/* [Shared] Oct 19, 2026 (Travis: the rate "0.03 Pound / 1,000 Square Ft." was cut off with room to spare): on a computer or
   tablet the columns size to their words instead of fixed widths (Used was 190px for "1.7 Ounces"). Rate is the row's
   main column (td.t-main, the house table rule), so it takes the room that is left and only ends in "…" on a narrow
   tablet card when nothing else can give (full text on hover and tap). Phones keep the card layout (phone-sheet). */
@media (min-width: 801px) {
  table.chem-log { table-layout: auto; }
  table.chem-log col { width: auto; }
  /* Product keeps its one-line width (name, EPA number, each ingredient) so it never wraps while Rate has room; a very long
     line stops at 16em with "…" so a narrow tablet card still fits. */
  table.chem-log td:first-child { white-space: nowrap; }
  table.chem-log td:first-child :is(b, div.muted, .ing span) { display: block; max-width: 16em; overflow: hidden; text-overflow: ellipsis; }
}
/* [Integrations] Equipment > Controllers on a narrow tablet (801-960px, Oct 20 2026): the 4 columns share the card by set shares and a
   word ends in "…" only when it truly doesn't fit (full text on hover), so the page never scrolls sideways. From 961px the
   columns size to their words (nothing cut). Phones keep the phone-sheet cards. */
@media (min-width: 801px) and (max-width: 960px) {
  table.ctl-list { table-layout: fixed; width: 100%; }
  table.ctl-list th:nth-child(1) { width: 19%; }
  table.ctl-list th:nth-child(2) { width: 25%; }
  table.ctl-list th:nth-child(3) { width: 24%; }
  table.ctl-list th:nth-child(4) { width: 32%; }
  table.ctl-list td { overflow: hidden; }
  table.ctl-list td .one-line { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
  table.ctl-list .rc-favcell { display: flex; align-items: center; gap: 4px; min-width: 0; }
  table.ctl-list .rc-favcell > .one-line { min-width: 0; flex: 0 1 auto; }
}
/* [Shared] Phones: the EPA number and ingredients sit under the product name in the value column (like .override-note); they fell
   into the 92px label column and wrapped ("EPA 100-834-DEMO", SA Style at 375). */
@media (max-width: 800px) { table.chem-log.phone-sheet td:first-child > :is(div.muted, .ing) { grid-column: 2; } }
.sheet { padding: 18px; }
/* [Billing and Plans] Table cards: the card's own padding is the only side inset; a results wrapper inside it adds none (Billing had doubled sides). */
.card > .list-results { padding: 0; }

.command { margin: 0 0 8px; color: var(--ink); }
.command .board-top { display: flex; justify-content: flex-start; gap: 6px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; min-width: 0; }
.command .week-jumps { display: contents; }
.command .jump-today { order: 0; }
.command .jump-today.today-here { display: none; }
.command .jump-wait { order: 1; }
.command .week-days { order: 2; }
.command .jump-next { order: 4; }
.command .board-range { order: 5; margin-left: auto; }
.command .board-tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.command .board-range { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.command .board-range a.btn,
.command .board-range input[type="date"],
.command .week-days a,
.command .week-jump {
  height: 54px; min-height: 54px; border-radius: 12px; box-sizing: border-box;
}
.command .board-range a.btn {
  min-width: 64px; padding: 0 12px; background: #fff; border: 1px solid var(--line); color: var(--ink); font-weight: 700;
}
.command .board-range input[type="date"] {
  width: 154px; text-align: center; padding: 0 8px; background: #fff; border: 1px solid var(--line); color: var(--ink); font-weight: 700;
}
.command .board-range input[type="date"]::-webkit-datetime-edit { text-align: center; padding: 0; }
.command .board-range span { color: var(--muted); font-size: .85rem; align-self: center; }
.command .week-days { display: flex; gap: 6px; align-items: stretch; }
.command .week-days a {
  min-width: 54px; padding: 6px 8px; text-align: center; font-weight: 700;
  color: var(--ink); background: #fff; border: 1px solid var(--line);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.command .week-days a span, .command .week-days a b { display: block; }
.command .week-days a span { color: var(--muted); font-size: .68rem; letter-spacing: .04em; text-transform: uppercase; }
.command .week-days a em { display: block; font-style: normal; font-size: .68rem; color: var(--muted); }
.command .week-days a.on { background: var(--blue); color: #fff; border-color: var(--blue); }
.command .week-days a.on span, .command .week-days a.on em { color: #fff; }
.command .week-days a.week-jump,
.command .week-jump {
  flex-direction: row; min-width: 0; padding: 0 12px;
  text-align: center; font-weight: 700; color: var(--ink); background: #fff; border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center; text-decoration: none;
}
.command .week-jump.on { background: var(--blue); color: #fff; border-color: var(--blue); }
/* [Route] Day picker (Today / Waiting / days / Upcoming) and Month picker (Prev / Start to End / Next): each is one line at every
   width. Wide: they share a line or the Month picker takes the next line whole. Narrower: slightly smaller in steps
   (1100, 960; phone level in the 800 block, then 430 and 360). If a row still can't fit it slides sideways inside itself. */
.command .day-picker,
.command .board-range.month-picker {
  position: relative; display: flex; flex-wrap: nowrap; align-items: stretch; gap: 6px; min-width: 0; max-width: 100%; flex: 0 1 auto;
  overflow-x: auto; overflow-y: hidden; scrollbar-width: none; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
}
.command .board-range.month-picker { align-items: center; }
.command .day-picker::-webkit-scrollbar, .command .board-range.month-picker::-webkit-scrollbar { display: none; }
.command .day-picker .week-days { flex: none; }
.command .day-picker .week-days a, .command .day-picker .week-jump, .command .month-picker > * { flex: none; white-space: nowrap; }
.command .day-picker.more-right, .command .month-picker.more-right { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent); }
.command .day-picker.more-left, .command .month-picker.more-left { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(to left, #000 calc(100% - 28px), transparent); }
.command .day-picker.more-left.more-right, .command .month-picker.more-left.more-right { -webkit-mask-image: linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent); }
@media (max-width: 1100px) and (min-width: 801px) {
  .command .board-range a.btn, .command .board-range input[type="date"], .command .week-days a, .command .week-jump { height: 48px; min-height: 48px; }
  .command .week-days a { min-width: 44px; padding: 4px 4px; }
  .command .week-jump { padding: 0 10px; font-size: .9rem; }
  .command .board-range a.btn { min-width: 54px; padding: 0 10px; }
  .command .board-range input[type="date"] { width: 138px; }
}
@media (max-width: 960px) and (min-width: 801px) {
  .command .day-picker, .command .board-range.month-picker { gap: 4px; }
  .command .board-range a.btn, .command .board-range input[type="date"], .command .week-days a, .command .week-jump { height: 44px; min-height: 44px; border-radius: 10px; }
  .command .week-days a { min-width: 34px; padding: 3px 2px; }
  .command .week-days a span { font-size: .62rem; }
  .command .week-jump { padding: 0 7px; font-size: .78rem; }
  .command .board-range a.btn { min-width: 0; padding: 0 9px; font-size: .82rem; }
  .command .board-range input[type="date"] { width: 128px; font-size: .85rem; padding: 0 4px; }
}
.command .board-cap { margin: -4px 0 12px; color: var(--muted); font-size: .85rem; }
.command .actions-menu { position: relative; }
.command .actions-menu summary { list-style: none; }
.command .actions-menu summary::-webkit-details-marker { display: none; }
.command .actions-menu .status-menu { min-width: 280px; padding: 8px; display: block; }
.command .actions-menu .status-menu > .act {
  width: 100%; display: flex; align-items: center; gap: 10px; justify-content: flex-start;
  height: 36px; min-height: 36px; padding: 0 10px; margin: 0;
  background: transparent; color: var(--ink); font-size: .82rem; font-weight: 650; border-radius: 10px; border: 0;
}
.command .actions-menu .act-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin-top: 6px; }
.command .actions-menu .act-grid button {
  width: 100%; height: auto; min-height: 0; margin: 0; padding: 6px 2px 5px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  background: transparent; color: var(--ink); border: 0; border-radius: 10px;
  font-size: .62rem; font-weight: 650; line-height: 1.15; text-align: center;
}
.command .actions-menu .status-menu button:hover { background: var(--paper); color: var(--ink); }
.command .actions-menu .act-grid .st { width: 32px; height: 32px; border-radius: 8px; }
.command .actions-menu svg, .command .st-cell svg { width: 16px; height: 16px; }
.command .st-cell { white-space: nowrap; }
.command .st-cell .st { display: inline-grid; place-items: center; width: 34px; height: 34px; border-radius: 10px; }
.command .st.call { color: var(--blue); background: var(--paper); }
.command .card { background: #fff; color: var(--ink); border: 0; border-radius: 16px; box-shadow: var(--card-shadow, none); }
.command table.board { width: 100%; min-width: 0; border-collapse: separate; border-spacing: 0; table-layout: fixed; } /* fixed so Client/Service widths stick (auto ignored max-width on td) */
.command .card:has(table.board) { overflow-x: clip; }
.command table.board td.pay .bhr { white-space: nowrap; }
.command table.board th,
.command table.board td { white-space: normal; }
.command table.board th { background: var(--paper); color: var(--muted); font-size: .68rem; letter-spacing: .04em; text-transform: uppercase; border-top: 0; border-bottom: 1px solid var(--t-line, var(--line)); box-shadow: none; }
.command table.board tr:first-child th:first-child { border-top-left-radius: 12px; border-left: 1px dashed var(--line); }
.command table.board tr:first-child th:last-child { border-top-right-radius: 12px; border-right: 1px dashed var(--line); }
.command table.board td { vertical-align: middle; padding: var(--t-pad, 10px 8px); background: #fff; border-bottom: 12px solid var(--paper); }
.command table.board tr.job-row td:first-child,
.command table.board tr.job-note-row td:first-child { border-left: 1px dashed var(--line); }
.command table.board tr.job-row td:last-child,
.command table.board tr.job-note-row td:last-child { border-right: 1px dashed var(--line); }
.command table.board tr:last-child td:first-child { border-bottom-left-radius: 12px; }
.command table.board tr:last-child td:last-child { border-bottom-right-radius: 12px; }
.command table.board tr.job-row:hover td,
.command table.board tr.job-row:hover + tr.job-note-row td,
.command table.board tr.job-row:has(+ tr.job-note-row:hover) td,
.command table.board tr.job-note-row:hover td { background: var(--paper); }
.command table.board tr.job-row:has(+ tr.job-note-row) td { border-bottom: 0; padding-bottom: 2px; }
.command table.board tr.job-note-row td { background: #fff; padding-top: 0; padding-bottom: 8px; border-top: 0; border-bottom: 12px solid var(--paper); white-space: normal; }
.command table.board tr:last-child > td { border-bottom: 1px solid var(--t-line, var(--line)); }
.command table.board th:first-child,
.command table.board td:first-child,
.command table.board th:nth-child(2),
.command table.board td.stop-order,
.command table.board th:nth-child(3),
.command table.board td.st-cell,
.command table.board th:nth-child(4),
.command table.board td.who,
.command table.board th:nth-child(6),
.command table.board td.when,
.command table.board th.note-col,
.command table.board td.note-col,
.command table.board th.file-col,
.command table.board td.file-col { width: 1%; }
.command table.board th:first-child,
.command table.board td:first-child { padding-left: 10px; padding-right: 4px; }
.command table.board th:nth-child(2),
.command table.board td.stop-order { padding-left: 12px; padding-right: 8px; text-align: center; }
.command table.board th:nth-child(3),
.command table.board td.st-cell { padding-left: 14px; padding-right: 14px; text-align: center; }
.command table.board td.st-cell .st { margin-inline: auto; }
.command table.board th:first-child,
.command table.board td:first-child { width: 3%; }
.command table.board th:nth-child(2),
.command table.board td.stop-order { width: 10%; }
.command table.board th:nth-child(3),
.command table.board td.st-cell { width: 5%; }
.command table.board th:nth-child(4),
.command table.board td.who {
  width: 20%; padding-left: 12px; padding-right: 6px; white-space: nowrap;
} /* Client: modest share so Service sits closer (Travis) */
.command table.board th.what-head,
.command table.board td.what { width: 36%; } /* Service: the bigger share so long names fit at 1280 */
.command table.board th:nth-child(6),
.command table.board td.when { width: 9%; }
.command table.board th:nth-child(7),
.command table.board td.pay { width: 9%; padding-left: 12px; }
.command table.board th.note-col,
.command table.board td.note-col,
.command table.board th.file-col,
.command table.board td.file-col { width: 4%; }
.command table.board th,
.command table.board td { overflow: hidden; } /* fixed layout: clip instead of growing the card */
.command table.board td.who > a,
.command table.board td.who > .muted,
.command table.board td.what > a {
  display: block; max-width: none; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
} /* full width of the cell; … only when the name is longer than the column */
.command table.board th:nth-child(7),
.command table.board td.pay { white-space: nowrap; }
.command table.board td.pay .bhrs,
.command table.board td.pay .bhrs b,
.command table.board td.pay .bhr { display: inline; white-space: nowrap; }
.command table.board td.pay .bhr + .bhr::before { content: " · "; color: var(--muted); font-weight: 500; }
.command table.board td.pay .bhr.bid { color: var(--muted); }
.command table.board td.pay .bhr.under { color: var(--grass); }
.command table.board td.pay .bhr.over { color: var(--red); }
.command table.board th .sort,
.command table.board th .sort:hover {
  background: transparent; color: var(--muted); border: 0; height: auto; min-height: 0; padding: 0;
  border-radius: 0; box-shadow: none; font: inherit; font-size: inherit; letter-spacing: inherit;
  text-transform: inherit; font-weight: 650; cursor: pointer;
}
.command table.board th .sort:hover { color: var(--ink); }
.command table.board th .sort.on::after { content: " ↑"; }
.command table.board th .sort.desc::after { content: " ↓"; }
.command table.board th.what-head .sort { margin-right: 8px; }
/* [Shared] Compact "by" dropdown in a table header (same pill look as list-bar filters, header size). */
.command table.board th .th-pick {
  display: inline-block; width: auto; height: 24px; min-height: 24px; margin: 0; padding: 0 24px 0 10px; vertical-align: middle;
  border: 1px solid var(--line); border-radius: 999px; background-color: #fff; background-position: right 8px center;
  color: var(--ink); font: inherit; font-size: .75rem; font-weight: 650; letter-spacing: 0; text-transform: none; cursor: pointer;
}
.command table.board th .th-pick:hover { border-color: var(--muted); }
.command table.board th .th-pick:focus { background-color: #fff; border-color: var(--teal); outline: none; }
.command table.board th.what-head { white-space: nowrap; }
.command table.board td.who,
.command table.board td.what { min-width: 0; }
.command table.board td.when,
.command table.board td.pay,
.command table.board td.last,
.command table.board td.stop-order,
.command table.board td.st-cell { white-space: nowrap; }
.when-clock { display: block; }
.command table.board td.who .muted,
.command table.board td.what .muted,
.command table.board td.when .muted { display: block; margin-top: 1px; font-size: .75rem; font-weight: 500; line-height: 1.25; color: var(--muted); }
.command table.board td.when .pause-pill { margin-top: 4px; }
.command table.board td.what > .muted { white-space: nowrap; } /* the line under the Service name stays one line; the table gives it the room */
.command table.board td.pay .pay-amt { display: block; font-variant-numeric: tabular-nums; font-weight: 750; }
.command .job-note b { color: var(--ink); font-weight: 750; }
.pause-pill { display: inline-flex; align-items: center; height: 22px; padding: 0 8px; border-radius: 999px; background: var(--orange); color: var(--ink); font-size: .72rem; font-weight: 750; white-space: nowrap; }
.command .stop-order { white-space: nowrap; cursor: grab; }
.command .stop-order .nudge {
  width: 22px; height: 22px; min-height: 22px; padding: 0; border-radius: 7px;
  background: var(--paper); color: var(--ink); border: 0; font-size: .85rem;
}
.command .order-num {
  width: 40px; height: 32px; min-height: 32px; margin: 0 2px; padding: 0;
  text-align: center; font-size: 14px; font-weight: 650; line-height: 32px; color: var(--ink);
  border: 1px solid var(--line); border-radius: 8px; background: #fff;
  -moz-appearance: textfield;
}
.command .order-num::-webkit-outer-spin-button,
.command .order-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.route-pin-wrap { background: none !important; border: 0 !important; }
.leaflet-marker-icon.route-pin-wrap { overflow: visible; }
.route-pin {
  width: 26px; height: 26px; border-radius: 50% 50% 50% 0; background: var(--blue); color: #fff;
  transform: rotate(-45deg); display: grid; place-items: center; box-shadow: 0 2px 6px rgba(0,0,0,.28);
}
.route-pin span { transform: rotate(45deg); font-size: 12px; font-weight: 800; line-height: 1; }
.command tr.job-row:target td { background: #E8F3FF; }
.command .job-note { display: flex; align-items: center; gap: 6px; margin: 0; padding: 0; background: none; font-size: 12px; line-height: 1.3; color: var(--muted); }
.command .job-note + .job-note { margin-top: 6px; padding-top: 6px; border-top: 1px dashed var(--line); }
.command .job-note .ico { width: 14px; height: 14px; flex: none; }
.command .job-note-text { min-width: 0; }
.command .note-tools { margin-left: auto; display: flex; gap: 2px; flex: none; }
.command .note-tools button { width: 22px; height: 22px; min-height: 0; padding: 0; border: 0; background: transparent; color: var(--muted); }
.command .note-tools button:hover { background: transparent; color: var(--ink); }
.command .note-tools .note-trash, .command .note-tools .note-trash:hover { color: var(--red); }
.command .job-note-row td { background: #fff; padding-top: 0; padding-bottom: 12px; border-top: 0; border-bottom: 12px solid var(--paper); }
.command table.board tr.job-row:last-child > td,
.command table.board tr.job-note-row:last-child > td { border-bottom: 1px solid var(--t-line, var(--line)); }
.command #dispatch-map { height: 380px; border-radius: 12px; }
.command table.board th.note-col,
.command table.board td.note-col { white-space: nowrap; text-align: center; width: 1%; padding-left: 22px; padding-right: 10px; }
.command table.board th.file-col,
.command table.board td.file-col { white-space: nowrap; text-align: center; width: 1%; padding-left: 16px; padding-right: 18px; }
.command table.board td.note-col button,
.command table.board td.file-col button { display: inline-flex; align-items: center; gap: 4px; height: var(--btn-h-sm); min-height: var(--btn-h-sm); padding: var(--btn-pad-sm); font-size: var(--btn-fs-sm); }
.command table.board td.note-col .ico,
.command table.board td.file-col .ico { width: 16px; height: 16px; }
.command table.board td.note-col b,
.command table.board td.file-col b { font-size: .75rem; font-weight: 750; }
dialog h2 { margin: 0 0 6px; }
dialog p { margin: 0 0 12px; }
dialog select { width: 100%; margin: 0 0 14px; }
dialog::backdrop { background: rgba(8, 20, 32, .45); }
dialog textarea { width: 100%; }
.st { display: inline-grid; place-items: center; }
.st svg { width: 16px; height: 16px; display: block; }
.st.pending { color: var(--muted); background: var(--paper); }
.st.dispatched, .st.driving { color: var(--blue); background: var(--paper); }
.st.onsite { color: var(--ink); background: var(--grass); }
.st.paused { color: var(--ink); background: var(--orange); }
.st.done { color: #248C34; background: var(--paper); }
.st.skipped { color: var(--red); background: var(--paper); }
.st.cancelled { color: #fff; background: var(--red); }

.sky {
  display: grid;
  grid-template-columns: minmax(160px, 200px) minmax(0, 1fr) minmax(300px, 420px);
  grid-template-areas: "now days radar" "meters meters meters";
  gap: 14px 18px;
  margin: 0 0 16px;
  padding: 18px;
  border-radius: 18px;
  color: #f4fbff;
  background:
    radial-gradient(900px 280px at 0% 0%, rgba(82, 196, 214, .35), transparent 60%),
    linear-gradient(145deg, #0b2944 0%, #0c3c4c 48%, #0d5c58 100%);
  box-shadow: 0 16px 40px rgba(8, 28, 48, .18);
}
.sky-now { grid-area: now; }
.sky-place { font-weight: 750; letter-spacing: .02em; }
.sky-read { display: flex; align-items: center; gap: 8px; margin: 6px 0 2px; }
.sky-icon { font-size: 2rem; line-height: 1; }
.sky-temp { font-size: 3rem; font-weight: 750; line-height: .9; letter-spacing: -.04em; }
.sky-temp sup { font-size: 1.15rem; }
.sky-meta { color: rgba(244, 251, 255, .78); }
.sky-days { grid-area: days; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); grid-template-rows: 1fr 1fr; gap: 8px; height: 100%; min-width: 0; }
.sky-day {
  display: flex; flex-direction: column; justify-content: space-between; align-items: center; gap: 2px;
  min-width: 0; height: 100%; text-align: center; padding: 8px 6px;
  background: rgba(255, 255, 255, .08); border: 1px solid rgba(255, 255, 255, .08); border-radius: 12px;
}
.sky-when { color: rgba(244, 251, 255, .7); font-size: .68rem; letter-spacing: .04em; text-transform: uppercase; }
.sky-when b { color: #fff; font-size: .95rem; letter-spacing: 0; }
.sky-ico { font-size: 1.15rem; line-height: 1; }
.sky-temps { display: flex; gap: 6px; align-items: baseline; }
.sky-temps strong { font-weight: 750; }
.sky-temps em, .sky-extra { color: rgba(244, 251, 255, .72); font-style: normal; font-size: .68rem; }
.sky-extra { display: grid; gap: 1px; line-height: 1.25; }
.sky-radar { grid-area: radar; display: flex; min-width: 0; min-height: 0; }
.radar-stage {
  position: relative; flex: 1; width: 100%; min-height: 180px; border-radius: 12px; overflow: hidden; isolation: isolate;
  clip-path: inset(0 round 12px); background: #1a1d22; border: 1px solid rgba(255, 255, 255, .08);
}
.radar-stage img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: fill; }
.radar-echo { z-index: 2; }
.radar-labels { z-index: 1; }
.radar-live {
  position: absolute; left: 10px; top: 10px; z-index: 3; padding: 3px 8px; border-radius: 999px;
  background: rgba(6, 16, 24, .72); color: #d7fff4; font-size: .72rem; font-weight: 750; letter-spacing: .04em;
}
.radar-live::before { content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 6px; border-radius: 99px; background: #3dffb0; box-shadow: 0 0 8px #3dffb0; }
.sky-soil { grid-area: meters; display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }
.sky-soil > div {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  background: rgba(255, 255, 255, .08); border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 14px; padding: 12px 16px;
}
.sky-soil span { display: block; color: #fff; font-weight: 750; letter-spacing: .01em; }
.sky-soil em { display: block; margin-top: 2px; color: rgba(244, 251, 255, .68); font-style: normal; font-size: .75rem; }
.sky-soil b { font-size: 1.85rem; line-height: 1; letter-spacing: -.03em; }
.sky-soil .soil-dry { color: #ffb4a8; }
.sky-soil .soil-fair { color: #ffd08a; }
.sky-soil .soil-good { color: #9cf0df; }
.sky-soil .soil-wet { color: #b9d4ff; }
.sky-soil .soil-humid { color: #9cf0df; }
.sky-soil .soil-heavy { color: #b9d4ff; }
.dash { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(340px, .9fr); gap: 16px; align-items: stretch; }
.dash-main { display: contents; }
.dash .stats { grid-column: 1; margin: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.dash .stat { min-width: 0; }
.dash .profit-card { grid-column: 2; margin: 0; height: 100%; display: flex; flex-direction: column; justify-content: space-between; }
@media (max-width: 900px) {
  .sky { width: 100%; min-width: 0; grid-template-columns: minmax(0, 1fr); grid-template-areas: "now" "days" "radar" "meters"; }
  .sky-days { width: auto; min-width: 0; height: auto; grid-template-rows: auto auto; align-items: stretch; }
  .sky-day { height: auto; justify-content: flex-start; gap: 3px; padding: 8px 4px; }
  .sky-temps { justify-content: center; font-size: .8rem; }
  .sky-soil { grid-template-columns: minmax(0, 1fr); }
  .radar-stage { min-height: 180px; min-width: 0; aspect-ratio: 16 / 9; flex: none; }
  .dash { grid-template-columns: minmax(0, 1fr); }
  .dash .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .dash .profit-card, .dash .stats { grid-column: 1; height: auto; }
}

.card > .list-results { margin: 0; }
.card > .list-results:has(.visit) { margin: 4px 0 0; overflow: visible; }
.list-results > .visit { margin: 0 0 10px; }
.list-results { overflow-x: auto; }
.list-results table { min-width: 720px; }
.list-results th, .list-results td { white-space: nowrap; vertical-align: middle; }
.list-results td.num { font-variant-numeric: tabular-nums; }
.list-results td:nth-child(2), .list-results td:nth-child(3), .list-results td.wrap { white-space: normal; }
.card > table:not(.board),
.list-results table,
.review-sheet table,
table.roster { border-collapse: separate; border-spacing: 0; }
.card > table:not(.board) th,
.list-results table th,
.review-sheet table th,
table.roster th { position: sticky; top: 0; z-index: 1; background: var(--paper); border-bottom: 1px solid var(--t-line, var(--line)); box-shadow: none; }
.card > table:not(.board) th:first-child,
.list-results table th:first-child,
.review-sheet table th:first-child,
table.roster th:first-child { border-top-left-radius: 12px; }
.card > table:not(.board) th:last-child,
.list-results table th:last-child,
.review-sheet table th:last-child,
table.roster th:last-child { border-top-right-radius: 12px; }
.card > table:not(.board) tr:last-child td:first-child,
.list-results table tr:last-child td:first-child,
.review-sheet table tr:last-child td:first-child,
table.roster tr:last-child td:first-child { border-bottom-left-radius: 12px; }
.card > table:not(.board) tr:last-child td:last-child,
.list-results table tr:last-child td:last-child,
.review-sheet table tr:last-child td:last-child,
table.roster tr:last-child td:last-child { border-bottom-right-radius: 12px; }
.card > table:not(.board) td:first-child,
.card > table:not(.board) th:first-child,
.list-results table td:first-child, .list-results table th:first-child,
.review-sheet table td:first-child, .review-sheet table th:first-child,
table.roster td:first-child, table.roster th:first-child { border-left: 0; }
.card > table:not(.board) td:last-child,
.card > table:not(.board) th:last-child,
.list-results table td:last-child, .list-results table th:last-child,
.review-sheet table td:last-child, .review-sheet table th:last-child,
table.roster td:last-child, table.roster th:last-child { border-right: 0; }
/* [Shared] Oct 18, 2026 (Travis): the table sides were a dashed line (a quirk kept on purpose when the Default Style was frozen,
   "0 pixels changed"); it showed as a stray dotted right edge on Quote Requests, Integrations and every card table.
   Changed here, in the Default source the Styles build on (LMN and SA only set corners), so every table and Style follows.
   A select in a table cell (a row's Status) shows its picked value at its natural width instead of shrinking to the
   arrow (the house width: 100% collapses in an auto-width column). */
.card table td > form:not(.drop) > select, .list-results table td > form:not(.drop) > select, table.roster td > form:not(.drop) > select { width: auto; max-width: 100%; } /* not the delete form's Reason menu (form.drop keeps its own caps) */
.card > table:not(.board) tr:hover td,
.list-results tr:hover td,
table.roster tr:hover td,
.review-sheet tr:hover td { background: var(--paper); }
td:last-child:has(button), td:last-child:has(form) { text-align: right; }
td:last-child form { display: inline; margin: 0; }
td:last-child form.drop { display: inline-flex; align-items: center; vertical-align: middle; }
td:last-child button, td:last-child .btn { height: var(--btn-h-sm); min-height: var(--btn-h-sm); padding: var(--btn-pad-sm); font-size: var(--btn-fs-sm); line-height: 1; border-radius: var(--btn-radius, 999px); }
input, select, textarea {
  border-color: #d5e0ec;
  border-radius: 10px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--teal);
  box-shadow: 0 0 0 3px rgba(30, 144, 255, .16); /* Default refine: brand blue ring (was a leftover teal ring, rgba(15,159,147)) */
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--teal) 18%, transparent); /* follows a company's own Brand color */
}
/* (Tracker 880) the second copy of the base button rule is gone: one button, defined once above. */
select.reason + button,
select.reason + .btn {
  height: var(--btn-h-sm); min-height: var(--btn-h-sm); padding: var(--btn-pad-sm); font-size: var(--btn-fs-sm); margin-top: 0;
}
.assign-head select.reason + button,
.assign-head select.reason + .btn { height: var(--btn-h-sm); min-height: var(--btn-h-sm); padding: var(--btn-pad-sm); }
.stat.predict { background: #eefbe6; }
.stat.predict b, .stat.predict span { color: var(--ink); }
.predict-pill { display: inline-block; background: var(--grass); color: var(--ink); border-radius: 999px; padding: 2px 8px; }
td, .list-count, .pager { font-variant-numeric: tabular-nums; }
.side nav a { padding: 9px 12px; }
.side nav > a { padding: 10px 12px; font-size: .68rem; font-weight: 700; line-height: 1.2; }
.top-pills { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.top-pills .pill {
  display: inline-flex; align-items: center; height: 32px; padding: 0 14px; border-radius: 999px;
  background: var(--blue); color: #fff; font-weight: 700; font-size: 13px; text-decoration: none; white-space: nowrap;
}
.top-pills .pill.money { background: var(--grass); color: var(--ink); }
.top-actions .top-action { margin-left: 0; }
/* [Top Bar and Menus] Page title toolbar (docs/ui-patterns.md): icon buttons, then one primary on the right. */
.top-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; flex: none; flex-wrap: nowrap; }
.top-actions > [hidden] { display: none; } /* Top Bar fold (js/topbar-fold.js) */
.top-ico { width: 32px; height: 32px; min-height: 32px; padding: 0; flex: none; }
.top-ico .ico, .top-primary .ico, .top-more-item .ico { width: 18px; height: 18px; }
.top-primary .ta-ico { display: none; }
.top-more { position: relative; }
.top-more summary { list-style: none; }
.top-more summary::-webkit-details-marker { display: none; }
.top-more .status-menu { top: 40px; min-width: 200px; padding: 6px; }
.top-more-item {
  display: flex; align-items: center; gap: 10px; width: 100%; height: 36px; min-height: 36px; padding: 0 10px; justify-content: flex-start;
  background: none; border: 0; border-radius: 10px; color: var(--ink); text-decoration: none; font-weight: 600;
}
.top-more-item:hover { background: var(--paper); }
.print-only { display: none; }
/* [Shared] Print view (?print=1): the printed page on screen, with only the header Back pill and Print button. */
.print-view .side, .print-view .phone-dock, .print-view .no-print, .print-view .list-bar, .print-view .menu-btn, .print-view #hc-fab, .print-view .hc-fab { display: none !important; }
.print-view .content { margin-left: 0; }
.print-view .print-only { display: block; }
.print-view { background: #fff; }
@media print {
  .side, .top, .no-print, .phone-dock { display: none !important; }
  .print-only { display: block; }
  .content { margin: 0 !important; }
  body { background: #fff; }
}
.assign-card, .visit, .chem-place, .rate-box { box-shadow: none; }

.ledger-hero { display: grid; gap: 14px; }
.ledger-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
.ledger-bars { display: grid; gap: 8px; }
.ledger-bars div { display: grid; grid-template-columns: 88px 1fr; align-items: center; gap: 10px; }
.ledger-bars .bar { display: block; height: 12px; border-radius: 99px; min-width: 0; }
.ledger-bars .bar.paid { background: var(--blue); }
.ledger-bars .bar.got { background: var(--grass); }
.ledger-month-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
.ledger-month-head h2 { margin: 0; }
.ledger-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
.ledger-cols.one { grid-template-columns: 1fr; }
.ledger-cols h3 { margin: 12px 0 0; font-size: .78rem; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.ledger-line { display: grid; grid-template-columns: 78px minmax(0, 1fr) auto; gap: 10px; align-items: start; padding: 10px 0; border-bottom: 1px solid var(--line); }
.ledger-line time { color: var(--muted); font-variant-numeric: tabular-nums; }
.ledger-amt { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.ledger-cost { display: flex; flex-wrap: wrap; gap: 6px 12px; margin-top: 4px; color: var(--muted); font-size: .8rem; }
.badge.due { background: var(--pill-due, var(--orange)); color: var(--ink); }
.phone-picks { display: none; }
@media (max-width: 800px) {
  .ledger-cols { grid-template-columns: 1fr; }
  .stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat { min-width: 0; }
  .stat span:not(.badge) { min-width: 0; white-space: normal; }
  .phone-pick {
    display: block; padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px;
    background: #fff; color: var(--ink); text-decoration: none;
  }
  .phone-pick b { display: block; }
  .phone-pick span { display: block; margin-top: 2px; color: var(--muted); font-size: .8rem; }
  .phone-list .list-results { overflow: clip; max-width: 100%; }
  .phone-list .list-results table { display: none !important; min-width: 0 !important; }
  .phone-list .list-search { width: 100%; min-width: 0; max-width: 100%; }
  .phone-list .phone-picks { display: grid; gap: 8px; }
  .phone-list .list-bar { display: grid; grid-template-columns: 1fr; }
  .phone-list .status-filter summary { max-width: none; }
  table.phone-sheet, table.phone-sheet tbody, table.phone-sheet tr {
    display: block; width: 100%; max-width: 100%; min-width: 0; box-sizing: border-box;
  }
  table.phone-sheet tr:first-child { display: none; }
  table.phone-sheet tr {
    margin: 0 0 8px; padding: 10px 12px;
    border: 1px solid var(--line); border-radius: 12px; background: #fff;
  }
  table.phone-sheet td, table.phone-sheet td:first-child, table.phone-sheet td:last-child {
    display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 8px; align-items: center;
    width: 100%; max-width: 100%; min-width: 0; box-sizing: border-box; border: 0; padding: 4px 0;
    text-align: left; white-space: normal; background: transparent;
  }
  .slim-list > table td, .slim-list > table th { border-left: 0; border-right: 0; border-radius: 0; }
  table.phone-sheet td::before {
    content: attr(data-label); color: var(--muted); font-size: .68rem; letter-spacing: .04em;
    text-transform: uppercase; font-weight: 650;
  }
  table.phone-sheet td:not([data-label]),
  table.phone-sheet td[data-label=""] { grid-template-columns: minmax(0, 1fr); }
  table.phone-sheet td:not([data-label])::before,
  table.phone-sheet td[data-label=""]::before { content: none; }
  table.phone-sheet td[data-label=""] { font-weight: 650; }
  table.phone-sheet td:empty { display: none; }
  table.phone-sheet .override-note { grid-column: 2; margin: 2px 0 0; }
  table.phone-sheet tr:hover td { background: transparent; }
  table.phone-sheet form.row, table.phone-sheet form.drop {
    display: flex; flex-wrap: wrap; justify-content: flex-start; align-items: center; gap: 8px;
    width: 100%; min-width: 0; margin: 0;
  }
  table.phone-sheet form.row input, table.phone-sheet input.rate-in { flex: 1 1 auto; width: auto; min-width: 0; max-width: none; }
  table.phone-sheet select.reason { width: auto; min-width: 0; flex: 1 1 120px; }
  .row.preview-size { align-items: center; }
  .row.preview-size label { width: 100%; }
  .row.preview-size input { flex: 1; width: auto; min-width: 0; }
  .slim-list { overflow-x: visible; }
  .slim-list > table, .slim-list > table tbody { display: block; width: 100%; max-width: 100%; min-width: 0; }
  .slim-list > table tr { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; max-width: 100%; box-sizing: border-box; border-bottom: 1px solid var(--line); }
  .slim-list > table tr:first-child { display: none; }
  .slim-list > table td { border: 0; padding: 12px 0; white-space: normal; }
  .slim-list > table td:not(:first-child) { display: none; }
  .slim-list > table td:first-child { flex: 1; min-width: 0; }
  .slim-list > table td:first-child:has(> a.svc-name) { max-width: none; } /* Service name shows on phones (the no-wrap rule set max-width: 0) */
  .slim-list > table td:first-child:not(:has(input, select, textarea, form, button)) { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* one line, "…" (no wrapping) */
  .slim-list > table td:last-child:not(:has(form)):not(:has(button)) { display: block; flex: none; }
  .slim-list > table tr:hover td { background: transparent; }
  .command, .command .card { overflow-x: visible; max-width: 100%; }
  .command .card:has(table.board) { overflow-x: visible; }
  /* Day picker + Month picker, phone level: each on its own full-width line, still one line each (never wraps).
     Day chips fill the line; below ~520px the Day picker slides sideways (hidden scrollbar, edge fade). */
  .command .board-top { display: grid; grid-template-columns: minmax(0, 1fr); width: 100%; max-width: 100%; min-width: 0; gap: 8px; }
  .command .day-picker { width: 100%; gap: 4px; }
  .command .day-picker .week-days { flex: 1 0 auto; gap: 4px; }
  .command .day-picker .week-days a { flex: 1 0 36px; min-width: 36px; width: auto; padding: 3px 2px; }
  .command .week-jump { padding: 0 9px; font-size: .8rem; }
  .command .board-range a.btn, .command .board-range input[type="date"], .command .week-days a, .command .week-jump { height: 44px; min-height: 44px; border-radius: 10px; }
  .command .board-range.month-picker { margin-left: 0; width: 100%; gap: 4px; }
  .command .board-range a.btn { flex: none; min-width: 0; padding: 0 10px; font-size: .82rem; }
  .command .month-picker > input[type="date"] { flex: 1 1 0; width: auto; min-width: 92px; padding: 0 4px; font-size: .85rem; }
  /* Tracker 501: iOS gives date fields an inner value box with its own min-height and top alignment, so the Prev/Next row's date
     boxes grew taller than the buttons with blank space under the date. Pin them to the button height, text centered. */
  .command .board-range input[type="date"] { max-height: 44px; padding-top: 0; padding-bottom: 0; line-height: 42px; display: flex; align-items: center; justify-content: center; }
  .command .board-range input[type="date"]::-webkit-date-and-time-value { min-height: 0; margin: 0; line-height: 42px; text-align: center; }
  .command .board-range input[type="date"]::-webkit-datetime-edit { padding: 0; line-height: 42px; }
  .command .board-range > span { flex: none; font-size: .78rem; }
  .command .list-bar:not(.lb) { display: grid; grid-template-columns: 1fr; }
  .command .list-bar:not(.lb) select { width: 100%; }
  .command #dispatch-map { height: 240px; }
}
/* [Route] Base board: the card layout (every field; Notes and Photos as icon-with-count buttons) whenever the board's
   card is under 800px wide, so tablets (820-1024, sidebar open) fit the card like phones, no sideways scroll, nothing
   hidden. Over 800px wide windows the sort buttons stay as one row above the cards. Was @media (max-width: 800px). */
.command .card:has(table.board) { container: cc-board / inline-size; }
@container cc-board (max-width: 799px) {
  .command table.board,
  .command table.board tbody { display: block; width: 100%; min-width: 0; table-layout: auto; }
  .command table.board tr:first-child { display: flex; align-items: center; gap: 8px; padding: 0 2px 8px; }
  .command table.board tr:first-child th { display: none; position: static; border: 0; padding: 0; background: transparent; box-shadow: none; }
  .command table.board tr:first-child th:first-child { display: flex; align-items: center; gap: 8px; }
  .command table.board tr:first-child th:first-child::after { content: "Select all"; letter-spacing: 0; text-transform: none; color: var(--ink); font-weight: 650; font-size: .8rem; }
  .command table.board tr.job-row {
    display: grid;
    width: 100%;
    box-sizing: border-box;
    grid-template-columns: 28px 34px minmax(0, 1fr) 36px 36px;
    grid-template-areas:
      "check status who note files"
      "service service service service service"
      "when when pay pay pay"
      "order order order order order";
    gap: 4px 8px;
    align-items: center;
    margin: 0 0 10px;
    padding: 12px;
    border: 1px solid var(--line);
    border-radius: 14px;
    background: #fff;
    max-width: 100%;
    overflow: hidden;
  }
  .command table.board tr.job-row td { display: block; min-width: 0; border: 0; padding: 0; white-space: normal; background: transparent; }
  .command table.board tr.job-row td:nth-child(1) { grid-area: check; width: 28px; justify-self: center; }
  .command table.board tr.job-row td:nth-child(2) { grid-area: order; justify-self: start; }
  .command table.board tr.job-row td:nth-child(3) { grid-area: status; }
  .command table.board tr.job-row td.st-cell {
    width: 34px; min-width: 34px; max-width: 34px; padding: 0;
    display: flex; align-items: center; justify-content: flex-start; gap: 4px; text-align: left;
  }
  .command table.board tr.job-row td.st-cell .st { width: 34px; height: 34px; flex: none; margin: 0; }
  .command table.board tr.job-row td:nth-child(4),
  .command table.board tr.job-row td.who {
    grid-area: who; width: auto; max-width: none; padding-left: 0; padding-right: 0; white-space: normal;
  }
  .command table.board tr.job-row td:nth-child(4) a,
  .command table.board tr.job-row td:nth-child(4) .muted,
  .command table.board tr.job-row td:nth-child(5) a,
  .command table.board tr.job-row td:nth-child(5) .muted {
    display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: none;
  }
  .command table.board tr.job-row td:nth-child(5),
  .command table.board tr.job-row td.what { grid-area: service; width: auto; max-width: none; }
  .command table.board tr.job-row td:nth-child(6) { grid-area: when; }
  .command table.board tr.job-row td:nth-child(7) { grid-area: pay; justify-self: end; text-align: right; }
  .command table.board tr.job-row td.when,
  .command table.board tr.job-row td.pay,
  .command table.board tr.job-row td.stop-order { width: auto; max-width: none; }
  .command table.board tr.job-row td.when .muted,
  .command table.board tr.job-row .when-clock { white-space: nowrap; }
  .command table.board tr.job-row td.pay,
  .command table.board tr.job-row td.pay .bhrs { white-space: nowrap; }
  .command table.board tr.job-row td.stop-order { display: flex; align-items: center; gap: 4px; justify-self: start; }
  .command table.board tr.job-row .order-num { width: 44px; flex: none; }
  .command table.board tr.job-row td:nth-child(8) { grid-area: note; }
  .command table.board tr.job-row td:nth-child(9) { grid-area: files; }
  .command table.board tr.job-row > td,
  .command table.board tr.job-row:last-child > td,
  .command table.board tr.job-note-row > td,
  .command table.board tr.job-note-row:last-child > td { border: 0; border-radius: 0; }
  .command table.board tr.job-row td.note-col,
  .command table.board tr.job-row td.file-col {
    width: auto; max-width: 40px; justify-self: end;
  }
  .command table.board tr.job-row td.note-col { grid-area: note; }
  .command table.board tr.job-row td.file-col { grid-area: files; }
  .command table.board tr.job-row td.note-col button,
  .command table.board tr.job-row td.file-col button {
    width: 34px; min-width: 34px; max-width: 34px; height: 34px; min-height: 34px;
    padding: 0; gap: 0; border-radius: 50%; justify-content: center; position: relative;
  }
  .command table.board tr.job-row td.note-col b,
  .command table.board tr.job-row td.file-col b {
    position: absolute; top: 1px; right: 1px; min-width: 14px; height: 14px; padding: 0 3px;
    border-radius: 99px; background: var(--ink); color: #fff; font-size: .6rem; line-height: 14px; text-align: center;
  }
  .command table.board tr.job-note-row { display: block; margin: -10px 0 10px; padding: 0 12px 8px; border: 1px solid var(--line); border-top: 0; border-radius: 0 0 14px 14px; background: #fff; }
  .command table.board tr.job-note-row td { display: block; border: 0; padding: 0; white-space: normal; background: transparent; }
  .command table.board tr.job-note-row td:first-child { display: none; }
}
@media (min-width: 801px) {
  @container cc-board (max-width: 799px) {
    .command table.board tr:first-child { gap: 4px 16px; padding: 0 2px 10px; }
    .command table.board tr:first-child th:has(> .sort) { display: flex; align-items: center; gap: 6px; }
    .command table.board tr:first-child th .sort { padding: 0; }
    .command table.board tr:first-child th .th-pick { width: auto; }
  }
}
/* [Route] Day picker / Month picker, near-phone and smallest phones: a bit smaller again; the dates drop their calendar icons
   (tapping a date still opens its picker) and at 360 and under the "to" between the dates is dropped. */
@media (max-width: 430px) {
  .command .week-jump { padding: 0 8px; font-size: .78rem; }
  .command .board-range a.btn { padding: 0 9px; font-size: .8rem; }
  .command .month-picker > input[type="date"] { min-width: 88px; font-size: .8rem; padding: 0 2px; }
  .command .month-picker > input[type="date"]::-webkit-calendar-picker-indicator { display: none; }
}
@media (max-width: 360px) {
  .command .board-range > span { display: none; }
  .command .board-range a.btn { padding: 0 7px; font-size: .76rem; }
  .command .month-picker > input[type="date"] { min-width: 86px; font-size: .72rem; padding: 0 1px; }
}
.field-body { margin: 0; background: var(--ink); }
.field-app { max-width: 480px; min-height: 100dvh; margin: 0 auto; background: var(--paper); display: flex; flex-direction: column; }
/* [Shared] Test company (tenants.php 'test'): badge by the title and the Test copy banner under the header, same as office pages. */
.field-app > .field-test-banner { margin: 8px 12px 0; }
.field-burger { width: 40px; height: 40px; padding: 0; border: 0; background: transparent; color: #fff; }
.field-burger svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.field-gear { display: grid; place-items: center; }
.field-when { display: flex; align-items: center; background: #fff; border-bottom: 1px solid var(--line); }
.field-back { flex: none; margin: 0 0 0 10px; height: 58px; padding: 0 12px; border-radius: 12px; border: 1px solid var(--line); display: flex; align-items: center; background: #fff; color: var(--blue); font-weight: 750; font-size: .78rem; text-decoration: none; }
.field-days { display: flex; justify-content: center; gap: 6px; overflow: hidden; flex: 1; min-width: 0; padding: 10px 12px; background: #fff; touch-action: pan-y; } /* one week + ‹ › (Oct 17, 2026: no control row scrolls sideways) */
.field-days::-webkit-scrollbar { display: none; }
.field-day { flex: 1 1 0; min-width: 0; max-width: 64px; height: 58px; border-radius: 12px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-decoration: none; color: var(--ink); }
.field-day span { font-size: .7rem; color: var(--muted); font-weight: 650; }
.field-day b { font-size: 1.05rem; }
.field-day.today span, .field-day.today b { color: var(--blue); }
.field-day.on { background: var(--grass); }
.field-day.on span, .field-day.on b { color: var(--ink); }
.field-tally { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 4px; padding: 10px 8px; background: #fff; border-bottom: 1px solid var(--line); text-align: center; align-items: end; }
.field-toast + .field-tally, .tc-bar + .field-tally, .tc-crew + .field-tally { margin-top: 10px; border-top: 1px solid var(--line); } /* a card above the stats row (Clock In bar, alerts, Route note): same 10px gap as above it */
.field-tally > div { min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 2px; }
.field-tally > div > b { height: 36px; display: flex; align-items: center; justify-content: center; font-size: .82rem; font-variant-numeric: tabular-nums; text-align: center; }
.field-tally span { display: block; color: var(--muted); font-size: .68rem; text-align: center; }
.field-tally .over b { color: var(--orange); }
.field-score .score-dial { position: relative; width: 36px; height: 36px; margin: 0 auto; }
.field-score svg { width: 36px; height: 36px; display: block; }
.field-score circle { fill: none; stroke-width: 3.4; }
.field-score .track { stroke: var(--line); }
.field-score .fill { stroke: var(--grass); stroke-linecap: round; transform: rotate(-90deg); transform-origin: 18px 18px; stroke-dasharray: calc(var(--p) * 97.39 / 100) 97.39; }
.field-score .score-dial b { position: absolute; inset: 0; display: grid; place-items: center; font-size: .68rem; line-height: 1; }
.field-crew { display: flex; flex-wrap: wrap; gap: 14px; padding: 12px; background: #fff; border-bottom: 1px solid var(--line); }
.field-look { display: block; padding: 10px 12px 0; }
.field-look .map-hold { z-index: 0; isolation: isolate; }
.field-look .leaflet-container { z-index: 0; }
.field-look .map-hold:not(.is-live) .leaflet-container { pointer-events: none !important; touch-action: pan-y; }
.field-look .map-hold:not(.is-live) .leaflet-marker-icon { pointer-events: auto !important; }
.map-move { position: absolute; z-index: 4; right: 8px; bottom: 8px; height: 30px; min-height: 30px; padding: 0 10px; border: 0; border-radius: 999px; background: var(--ink); color: #fff; font-size: .72rem; }
.map-move.on, .map-move.on:hover { background: var(--blue); color: #fff; }
.field-look #field-stops { height: 220px; border: 1px solid var(--line); border-radius: 12px; }
.field-house { position: relative; height: 210px; margin: 12px 12px 0; overflow: hidden; border-radius: 16px; background: #d5d8dc; }
.field-house img { display: block; width: 100%; height: 100%; object-fit: cover; }
.field-house.later { background: #d5d8dc linear-gradient(100deg, transparent 35%, rgba(255, 255, 255, .45) 50%, transparent 65%) 0 0 / 250% 100% no-repeat; animation: house-wait 1.4s linear infinite; transition: height .25s ease, margin .25s ease; }
.field-house.later img { opacity: 0; transition: opacity .4s ease; }
.field-house.later.loaded { animation: none; background-image: none; }
.field-house.later.loaded img { opacity: 1; }
.field-house.later.gone { height: 0; margin-top: 0; animation: none; }
@keyframes house-wait { from { background-position: 120% 0; } to { background-position: -20% 0; } }
@media (prefers-reduced-motion: reduce) { .field-house.later { animation: none; } .field-house.later img { transition: none; } }
.sheet-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.sheet-top a { margin: 0; width: 36px; height: 36px; }
.sheet-top .x-close { --x-size: 36px; } /* Route tap size kept (Tracker 880) */
.sheet-line { display: flex; align-items: center; gap: 10px; }
.sheet-line b { flex: 1; min-width: 0; }
.field-look > span { display: block; margin-top: 4px; color: var(--muted); font-size: .68rem; letter-spacing: .04em; text-transform: uppercase; font-weight: 650; }
.route-pin.on { background: var(--grass); color: var(--ink); animation: status-pulse 1.6s ease-out infinite; }
.field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.field-ask label span { color: var(--muted); font-weight: 500; }
.field-ask form { max-height: 70dvh; overflow: auto; padding: 0 4px; margin: 0 -4px; } /* room for the More pill and focus rings at the right edge (iPhone 390) */
.field-ask .lo-oz { font-variant-numeric: tabular-nums; }
.bhrs b { display: block; font-variant-numeric: tabular-nums; font-weight: 750; }
.bhr { display: block; margin-top: 1px; font-size: .72rem; font-weight: 650; white-space: nowrap; }
.bhr.over { color: var(--orange); }
.bhr.under, .bhr.bid { color: var(--muted); font-weight: 600; }
.field-person { flex: none; width: 72px; text-align: center; color: var(--muted); }
.field-person b { display: grid; place-items: center; width: 48px; height: 48px; margin: 0 auto 4px; border-radius: 50%; background: var(--paper); color: var(--ink); }
.field-person.on b { background: var(--navy); color: #fff; }
.field-person span, .field-person em { display: block; font-style: normal; font-size: .75rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.field-person em { color: var(--grass); font-weight: 650; }
.field-crew .field-team { align-self: center; margin-left: auto; flex: 0 1 auto; min-width: 48px; display: inline-block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* a long team name ends in … instead of scrolling the bar sideways */
.field-toast { margin: 10px 12px 0; padding: 10px 12px; border-radius: 12px; font-weight: 650; }
/* [Route] My Day has no header: the shared toasts float at the top, over the Service sheet, below the iPhone notch. */
.field-body .notices { position: fixed; z-index: 60; top: 0; left: 0; right: 0; max-width: 480px; margin: 0 auto; height: 0; padding: calc(env(safe-area-inset-top, 0px) + 8px) 12px 0; pointer-events: none; }
/* [Shared] Taps go through to the sheet's tabs underneath; only × and Undo take them. */
.field-body .notices > .toast { pointer-events: none; margin-top: 0; box-shadow: 0 8px 24px rgba(16, 24, 40, .22); }
.field-body .notices .toast-x, .field-body .notices .geo-undo { pointer-events: auto; }
.field-body .notices > .toast span { overflow-wrap: anywhere; }
.field-body .notices .geo-undo { display: inline-flex; margin: 0; }
.field-toast.ok { background: var(--grass); color: var(--ink); }
.field-toast.bad { background: var(--red); color: #fff; }
.field-alert { display: flex; align-items: center; gap: 8px; padding: 6px 6px 6px 12px; }
.field-alert span { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.field-list { flex: 1; padding: 12px 12px 24px; }
@media (max-width: 800px) {
  .field-list { padding-bottom: calc(88px + env(safe-area-inset-bottom, 0px)); }
  body.has-job .phone-dock { display: none; }
}
.field-month { margin: 0; padding: 8px 12px 0; background: #fff; color: var(--muted); font-size: .75rem; font-weight: 750; letter-spacing: .04em; text-transform: uppercase; }
.field-mo { flex: none; align-self: center; color: var(--muted); font-style: normal; font-size: .68rem; font-weight: 750; letter-spacing: .04em; text-transform: uppercase; }
body.has-job { overflow: hidden; }
.field-sheet { position: fixed; z-index: 25; inset: 0; max-width: 480px; margin: 0 auto; background: var(--navy); display: flex; flex-direction: column; }
.field-sheet.driving { background: var(--blue); }
.field-sheet.onsite { background: var(--navy); }
.field-sheet.paused { background: var(--orange); }
.field-sheet-bar { background: transparent; box-shadow: none; }
.field-sheet-bar { display: flex; align-items: flex-start; gap: 8px; min-height: 92px; padding: calc(env(safe-area-inset-top, 0px) + 14px) 8px 18px 16px; background: transparent; color: #fff; box-shadow: none; }
.field-sheet-bar div { min-width: 0; flex: 1; }
.field-sheet-bar a { margin-left: 4px; width: 44px; height: 44px; display: grid; place-items: center; color: #fff; text-decoration: none; font-size: 2rem; line-height: 1; }
.field-sheet-bar small, .field-sheet-bar .who, .field-sheet-bar em { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.field-sheet-bar small { display: inline-flex; align-items: center; gap: 6px; width: fit-content; max-width: calc(100% - 52px); margin-top: 4px; padding: 4px 10px 4px 8px; border-radius: var(--pill-radius, 999px); background: #fff; color: var(--ink); font-size: .62rem; letter-spacing: .03em; text-transform: uppercase; font-weight: 750; }
.field-sheet-bar small i { width: 8px; height: 8px; border-radius: 50%; background: var(--grass); animation: status-pulse 1.6s ease-out infinite; }
@keyframes status-pulse { 70% { box-shadow: 0 0 0 6px transparent; } }
.field-sheet-bar small.ready i { background: #c8c8c8; animation: none; }
.field-sheet-bar small.done i { background: var(--grass); animation: none; }
.field-sheet-bar small.skipped i { background: var(--red); animation: none; }
.field-sheet-bar small.over i { background: var(--orange); }
.field-sheet.driving .field-sheet-bar small { background: #fff; color: var(--blue); }
.field-sheet.driving .field-sheet-bar small i { background: var(--blue); }
.field-sheet.paused .field-sheet-bar small { background: var(--navy); color: #fff; }
.field-sheet.paused .field-sheet-bar small i { background: #fff; animation: none; }
.field-sheet-bar .who { margin-top: 4px; color: rgba(255,255,255,.9); font-size: .85rem; }
.field-sheet-bar div b { display: block; margin-top: 2px; font-size: 1.45rem; line-height: 1.15; letter-spacing: -.02em; white-space: normal; }
.field-sheet-bar em { margin-top: 8px; padding: 3px 8px; border-radius: var(--pill-radius, 999px); background: rgba(255,255,255,.16); color: #fff; font-style: normal; font-size: .72rem; font-weight: 650; width: fit-content; max-width: 100%; }
.sheet-line em { margin-top: 0; align-self: center; }
.sheet-line em { margin: 0; flex: none; max-width: 46%; }
.field-sheet-body { flex: 1; overflow: auto; padding-bottom: 12px; background: var(--paper); border-radius: 22px; margin: 0 12px; }
.field-sheet.stepping .job-tabs,
.field-sheet.stepping .field-sheet-body,
.field-sheet.stepping .job-dock { display: none; }
.sheet-step { flex: 1; overflow: auto; margin: 0 12px; padding: 16px 16px calc(16px + env(safe-area-inset-bottom)); background: var(--paper); color: var(--ink); border-radius: 22px 22px 0 0; } /* Oct 22 2026 (Travis 12:49 PM: blue showed under the white card): flush to the bottom */
.sheet-step[hidden] { display: none; }
.sheet-step h2 { margin: 0 0 6px; }
.sheet-step p { margin: 0 0 14px; color: var(--muted); }
.sheet-step form { display: flex; flex-direction: column; gap: 8px; }
.sheet-step button { width: 100%; }
.field-where { margin: 8px 12px 0; color: var(--muted); font-size: .75rem; }
.field-house.short { height: 160px; margin: 0; }
dialog.field-ask.screen { position: fixed; inset: 0; width: min(480px, 100%); height: 100dvh; max-height: none; margin: 0 auto; border: 0; border-radius: 0; padding: calc(8px + env(safe-area-inset-top)) 16px calc(16px + env(safe-area-inset-bottom)); overflow: auto; }
.field-ask .sheet-x { width: 44px; height: 44px; min-height: 0; margin: 0 0 0 auto; padding: 0; border: 0; background: transparent; color: var(--ink); font-size: 2rem; line-height: 1; }
/* Oct 22 2026 12:22 PM (Travis: Products X was a blue filled X that vanished on tap): a sheet opens with focus on its X,
   which lit the .tile focus style. The sheet X stays the plain X on every sheet. */
.field-ask .sheet-x:hover, .field-ask .sheet-x:focus, .field-ask .sheet-x:focus-visible { background: transparent; border: 0; color: var(--ink); outline: none; }
.field-empty { color: var(--muted); text-align: center; padding: 32px 12px; }
.field-job { display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; gap: 10px; align-items: center; background: #fff; border: 1px solid var(--card-edge, var(--line)); border-radius: 14px; padding: 12px; margin: 0 0 10px; text-decoration: none; color: inherit; }
.field-job.on { border-color: var(--blue); box-shadow: 0 0 0 2px rgba(30, 144, 255, .25); }
.field-job i { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; background: var(--grass); color: var(--ink); font-style: normal; font-weight: 750; }
.field-job strong, .field-job span, .field-job em, .field-job small { display: block; }
.field-job span, .field-job em, .field-job small { color: var(--muted); font-style: normal; }
.field-job strong { font-size: .85rem; }
.field-job em, .field-job small { font-size: .75rem; }
.field-job .st { width: 28px; height: 28px; border-radius: 8px; flex: none; display: inline-grid; place-items: center; align-self: center; }
.field-job .st svg { width: 15px; height: 15px; display: block; }
.field-drive { align-self: center; height: 36px; min-height: 36px; padding: 0 12px; border: 0; border-radius: 10px; background: var(--grass); color: var(--ink); text-decoration: none; font-size: .75rem; font-weight: 750; display: inline-flex; align-items: center; }
.field-skip.lo-done { display: inline-flex; align-items: center; gap: 4px; } /* Loaded: same as the stop cards' Skip button, reopens the Loaded window (Travis 1:03 PM) */
.lo-done svg { width: 14px; height: 14px; }
.field-drive:hover { background: var(--grass); color: var(--ink); border-color: transparent; }
.field-acts { display: flex; align-items: center; gap: 6px; }
.field-acts form { margin: 0; }
.field-skip, .field-skip:hover { height: 36px; min-height: 36px; padding: 0 10px; border-radius: 10px; background: #fff; color: var(--ink); border: 1px solid var(--line); font-size: .75rem; }
.job-tabs { display: grid; grid-template-columns: repeat(5, 1fr); gap: 2px; background: transparent; border-bottom: 0; padding: 0 8px 10px; }
.job-tabs button, .job-tabs button:hover { height: 48px; min-height: 48px; border: 0; border-radius: 12px; background: transparent; color: rgba(255,255,255,.72); border-bottom: 0; box-shadow: none; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: .62rem; padding: 0; }
.job-tabs button svg { width: 18px; height: 18px; }
.job-tabs button.on, .job-tabs button.on:hover { color: #fff; background: rgba(255,255,255,.16); border-bottom: 0; }
.field-sheet.driving .field-sheet-bar,
.field-sheet.onsite .field-sheet-bar,
.field-sheet.paused .field-sheet-bar { background: transparent; }
.field-now { display: flex; align-items: center; gap: 8px; margin: 10px 12px 0; padding: 10px 12px; background: var(--ink); color: #fff; border-radius: 16px; }
.field-now div { min-width: 0; flex: 1; }
.field-now b, .field-now span { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.field-now span { color: #c8c8c8; font-size: .75rem; }
.field-now form { margin: 0; }
.note-when { display: block; margin: 2px 0 8px; color: var(--muted); font-style: normal; font-size: .72rem; font-weight: 650; }
.command .job-note .note-when { display: inline; margin: 0 0 0 8px; white-space: nowrap; font-size: 12px; font-weight: 500; font-style: normal; letter-spacing: 0; color: var(--muted); }
.note-block { margin: 0 0 18px; }
.note-block label { display: inline-flex; align-items: center; width: auto; margin: 0 0 8px; padding: 3px 10px; border-radius: 999px; background: var(--grass); color: var(--ink); font-size: .75rem; font-weight: 750; letter-spacing: 0; text-transform: none; }
.note-block label a, .visit-note a.pill, .visit-note span.pill { color: var(--ink); background: var(--grass); text-decoration: none; }
.note-block label a { background: transparent; color: inherit; }
.note-block label:has(a):hover, .visit-note a.pill:hover { background: var(--ink); color: #fff; }
.note-block .note-when { margin: 6px 0 0; }
.visit-notes { display: flex; flex-direction: column; gap: 8px; }
.visit-note { padding: 10px 12px; background: var(--paper); border-radius: 14px; }
.visit-note-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.visit-note-top .note-when { margin: 0; }
.visit-note p { margin: 6px 0 0; }
.note-tools { margin-left: auto; display: inline-flex; gap: 2px; flex: none; }
.note-tools button { width: 28px; height: 28px; min-height: 28px; padding: 0; border: 0; background: transparent; color: var(--muted); display: inline-flex; align-items: center; justify-content: center; }
.note-tools button:hover { color: var(--ink); background: transparent; }
.note-tools .note-trash, .note-tools .note-trash:hover { color: var(--red); }
.note-pill { position: relative; margin: 8px 12px 0; padding: 8px 12px; background: #fff; border-radius: 14px; font-size: .78rem; }
.note-pill .note-when { margin: 4px 0 0; }
.note-pill:has(.note-add) { padding-right: 40px; }
.note-pill span { display: block; color: var(--muted); font-size: .68rem; font-weight: 750; letter-spacing: .04em; text-transform: uppercase; }
.note-pill p { margin: 4px 0 0; }
/* [Route] Task ticket on Route and the Visit box on a task (Send to Route): the note-pill look, checklist + two quiet buttons. */
.field-task .row, .task-visit .job-files { margin-top: 8px; }
.field-task .row { gap: 6px; }
/* [Route] Task stops on Route and Base (Send to Route with no customer): the Service card and the .rt-strip line, a clock instead of a stop number */
.field-job.task-stop i { background: var(--paper); color: var(--muted); }
.field-job.task-stop strong, .field-job.task-stop em { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.task-stop-line > .badge { flex: none; }
.task-stop-line.is-done > span { text-decoration: line-through; }
@media (max-width: 520px) { .task-stop-line > .badge { display: none; } }
.note-add, .note-add:hover { position: absolute; top: 50%; right: 8px; transform: translateY(-50%); width: 28px; height: 28px; min-height: 28px; margin: 0; padding: 0; border: 0; border-radius: 50%; background: var(--paper); color: var(--ink); box-shadow: none; display: flex; align-items: center; justify-content: center; line-height: 0; }
.note-add svg { width: 14px; height: 14px; display: block; }
.wx-grid { margin: 10px 12px 0; }
.wx-save { margin: 12px 12px 0; }
.job-rows { margin: 12px; background: #fff; border: 0; border-radius: 18px; overflow: hidden; box-shadow: 0 10px 24px rgba(16, 24, 40, .12); }
.job-rows div { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 0; padding: 12px 14px; border: 0; border-top: 1px solid var(--line); border-radius: 0; background: transparent; }
.job-rows div:first-child { border-top: 0; }
.job-dock { position: relative; left: auto; bottom: auto; transform: none; width: auto; display: block; margin: 10px 12px calc(12px + env(safe-area-inset-bottom)); padding: 0; background: transparent; border: 0; }
.job-dock-card { display: flex; align-items: center; gap: 8px; padding: 8px 4px 8px 16px; background: #1c1c1c; color: #fff; border-radius: 22px; }
.dock-end { display: flex; align-items: center; gap: 36px; margin-left: auto; flex: none; }
.job-dock-card > .dock-end { margin-left: auto; flex: 0 0 auto; }
.dock-slot { width: 40px; height: 40px; flex: none; }
.dock-tools { display: flex; align-items: center; gap: 10px; margin-left: 0; flex: none; }
.job-dock-card > div { min-width: 0; flex: 1; }
.job-dock-card > div b, .job-dock-card > div span { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.job-dock-card > div:has(.sheet-clock),
.dock-status {
  flex: 0 1 9.5rem; width: 9.5rem; min-width: 4.5rem; text-align: center;
}
@media (max-width: 430px) { .dock-end { gap: 16px; } .dock-tools { gap: 6px; } }
.job-dock-card > .dock-status b,
.job-dock-card > .dock-status span {
  width: 100%; text-align: center; overflow: visible; text-overflow: clip;
}
.job-dock .sheet-clock { display: block; width: 100%; font-size: 1rem; font-variant-numeric: tabular-nums; text-align: center; overflow: visible; }
.job-dock-card > div span { color: #c8c8c8; font-size: .72rem; font-weight: 650; }
.job-dock .tech-dot { display: inline-grid; place-items: center; width: 34px; height: 34px; margin: 0; overflow: visible; color: var(--ink); background: var(--grass); font-size: .85rem; line-height: 1; }
.dock-mini svg, .dock-mini .ico { width: 28px; height: 28px; display: block; }
.dock-mini#field-reach svg { width: 22px; height: 22px; }
.dock-mini#field-map svg { transform: translateY(-2px); }
.dock-mini.start .ico { width: 34px; height: 34px; }
.dock-mini.go:not(.start), .dock-mini.go:not(.start):hover { color: var(--grass); }
.dock-mini.pause, .dock-mini.pause:hover { color: var(--orange); }
.dock-mini.stop, .dock-mini.stop:hover { color: var(--red); }
.job-meter { display: block; height: 8px; margin: 4px 14px 0; padding: 0 !important; border: 0 !important; border-radius: 99px; background: var(--paper); overflow: hidden; }
.job-meter b { display: block; height: 8px; background: var(--grass); border-radius: 99px; }
.job-used { display: flex; justify-content: space-between; gap: 8px; margin: 0; padding: 6px 14px 14px; border: 0; }
.job-used .used { color: var(--grass); font-weight: 750; }
.job-used .left { color: var(--ink); }
.job-dock button, .job-dock button:hover { border: 0; color: #fff; background: transparent; box-shadow: none; }
.dock-mini, .dock-mini:hover { width: 40px; height: 40px; min-height: 40px; padding: 0; border-radius: 12px; color: #fff; background: transparent; flex: none; display: inline-flex; align-items: center; justify-content: center; }
.job-rows span { color: var(--muted); font-size: .75rem; }
.job-rows b { font-size: .9rem; }
.job-rows .job-meter { display: block; height: 8px; margin: 4px 14px 0; padding: 0; border: 0; border-radius: 99px; background: var(--paper); overflow: hidden; }
.job-rows .job-meter b { display: block; height: 8px; background: var(--grass); border-radius: 99px; }
.job-rows.over .job-meter b { background: var(--orange); }
.job-rows .job-used { display: flex; justify-content: space-between; border: 0; padding: 6px 14px 14px; }
.job-rows .job-used .used,
.job-rows .job-used .left { color: var(--ink); font-size: .75rem; font-weight: 750; }
.job-rows .job-used .used { color: var(--grass); }
.job-rows .job-used .left.over { color: var(--orange); }
.job-dock-card > div span.over, #dock-state.over { color: var(--orange); }
.job-rows p { margin: 0; padding: 8px 12px 12px; font-size: .78rem; font-weight: 650; }
.job-rows.over p { color: var(--orange); }
.tech-dot { width: 32px; height: 32px; margin: 0; border-radius: 50%; background: var(--grass); color: var(--ink); display: inline-grid; place-items: center; font-size: .8rem; font-weight: 750; flex: none; }
.prop-pics { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.prop-pics img { width: 100%; height: 92px; object-fit: cover; border-radius: 12px; background: var(--paper); }
/* [Route] Equipment On Site by Business Type (includes/equipment_site_ui.php, field.php On Site): standard .card + h2, .set-row lists,
   zone card as rows (full width; phones stack each zone, no table, no sideways scroll). */
.eq-list .set-row { padding-left: 0; padding-right: 0; }
.eq-empty { margin: 4px 0 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.eq-add { margin-top: 12px; flex-wrap: nowrap; overflow: hidden; }
.eq-add form { margin: 0; display: flex; gap: 8px; align-items: center; min-width: 0; }
.eq-add select { width: auto; min-width: 0; margin: 0; }
.eq-pics { margin-top: 12px; }
.zone-grid { display: block; }
.zone-row { position: relative; display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr) 96px minmax(0, 2.2fr); gap: 12px; align-items: center; min-height: 46px; padding: 6px 0 6px 44px; border-top: 1px solid var(--line); }
.zone-grid[data-cols="4"] .zone-row { grid-template-columns: minmax(0, 1.6fr) 96px 96px minmax(0, 2.2fr); }
.zone-row > span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.zone-row > .zn { position: absolute; left: 0; top: 50%; transform: translateY(-50%); width: 30px; height: 30px; border-radius: 50%; background: var(--paper); display: grid; place-items: center; font-weight: 700; font-size: .85rem; }
.zone-row > .zu { text-align: right; font-weight: 650; }
.zone-row input, .zone-row select { width: 100%; min-width: 0; margin: 0; }
.zone-head { min-height: 34px; border-top: 0; font-size: .72rem; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
.zone-head > .zn { background: transparent; }
.zone-row > .zone-meta, .zone-row > .zone-note { display: none; }
.zone-row > .zone-note { grid-column: 1 / -1; white-space: normal; font-size: .85rem; } /* a zone's note is a sentence: it flows on phones */
.eq-note { margin: 8px 0 4px; font-size: .85rem; }
@media (max-width: 600px) {
  .zone-head { display: none; }
  .zone-grid:not(.edit) .zone-row, .zone-grid.stack .zone-row { grid-template-columns: minmax(0, 1fr) auto; gap: 0 10px; padding-left: 42px; }
  .zone-grid:not(.edit) .zone-row > span:not(.zn):not(.zc-name):not(.zu):not(.zone-meta) { display: none; }
  .zone-grid:not(.edit) .zone-row > .zc-name { font-weight: 650; }
  .zone-grid:not(.edit) .zone-row > .zone-meta { display: block; grid-column: 1 / -1; font-size: .85rem; }
  .zone-grid:not(.edit) .zone-row > .zone-meta:empty { display: none; }
  .zone-grid:not(.edit) .zone-row > .zone-note { display: block; }
  .zone-grid.edit .zone-row { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; padding: 10px 0 10px 42px; }
  .zone-grid.edit .zone-row > .zn { top: 14px; transform: none; }
  .zone-grid.edit .zone-row > .zc-name { grid-column: 1 / -1; }
  .zone-grid.edit .zone-row > span:not(.zn):not(.zc-name):not(.zc-notes):not(.zu) { grid-column: span 2; }
  .zone-grid.edit[data-cols="5"] .zone-row > .zc-notes { grid-column: span 3; }
  .zone-grid.edit[data-cols="4"] .zone-row > .zu { grid-column: span 2; }
  .zone-grid.edit[data-cols="4"] .zone-row > .zc-notes { grid-column: 1 / -1; }
  .zone-grid.edit .zone-row > .zu { text-align: left; }
  .eq-add { flex-direction: column; align-items: stretch; }
  .eq-list .set-txt { flex-direction: column; align-items: stretch; gap: 2px; }
  .eq-list .set-txt b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .eq-add .btn, .eq-add .file-pick, .eq-add select { flex: 1; }
  .eq-pics { grid-template-columns: repeat(3, 1fr); }
}
.zone-grid.stack .zone-head { display: none; }
.zone-grid.stack .zone-row { grid-template-columns: minmax(0, 1fr) auto; gap: 0 10px; padding-left: 42px; }
.zone-grid.stack .zone-row > span:not(.zn):not(.zc-name):not(.zu):not(.zone-meta) { display: none; }
.zone-grid.stack .zone-row > .zc-name { font-weight: 650; }
.zone-grid.stack .zone-row > .zone-meta { display: block; grid-column: 1 / -1; font-size: .85rem; }
.zone-grid.stack .zone-row > .zone-meta:empty { display: none; }
.zone-grid.stack .zone-row > .zone-note { display: block; }
.zone-grid.edit[data-site-edit] .zone-row { grid-template-columns: minmax(0, 1fr) 110px; gap: 8px; padding: 10px 0 10px 42px; }
.zone-grid.edit[data-site-edit] .zone-row > .zn { top: 14px; transform: none; }
.zone-grid.edit[data-site-edit] .zone-row > .zc-name { grid-column: auto; }
.zone-grid.edit[data-site-edit] .zone-row > .zc-notes { grid-column: 1 / -1; }
.site-rows .site-open { cursor: pointer; }
.site-rows .site-open > span { flex: none; }
.site-rows .site-open > b { min-width: 0; margin-left: auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.site-rows .site-open > i { flex: none; font-style: normal; color: var(--muted); }
.site-back { margin: 12px 12px 0; }
/* [Sprout] Tank Calculator (includes/tank_calc.php, assets/js/tank.js): the rig from above (open levers light their nozzles' fans),
   lever and tank checks, and the shared .sx-gauge gauges. The Route row is a .site-open row inside a link. */
.job-rows > a.row-link { display: block; color: inherit; text-decoration: none; }
.tank-rig { display: block; width: 100%; max-width: 420px; height: auto; margin: 6px auto 4px; }
.tank-rig .body { fill: var(--paper); stroke: var(--line); }
.tank-rig .tk { fill: var(--paper); stroke: var(--line); }
.tank-rig .tk.on { fill: var(--grass); fill-opacity: .35; stroke: var(--grass); }
.tank-rig .boom { stroke: var(--ink); stroke-width: 3; stroke-linecap: round; }
.tank-rig .nz { fill: var(--ink); }
.tank-rig .fan { fill: var(--paper); stroke: var(--line); stroke-dasharray: 3 3; }
.tank-rig .fan.on { fill: var(--grass); fill-opacity: .45; stroke: var(--grass); stroke-dasharray: none; }
.tank-rig .dim { stroke: var(--muted); stroke-width: 1; }
.tank-rig .fan.on.out { fill-opacity: .18; stroke-dasharray: 3 3; }
.tank-rig .ghost { opacity: .45; }
.tank-rig .foam { fill: var(--paper); stroke: var(--ink); stroke-width: 1.5; }
.tank-rig text.small { font-size: 9px; fill: var(--muted); }
.tank-rig text { font-size: 11px; fill: var(--ink); text-anchor: middle; dominant-baseline: middle; }
.tank-levers { justify-content: center; margin: 6px 0; }
.tank-levers:empty { display: none; }
.tank-tanks { display: flex; justify-content: center; gap: 0; margin: 0 0 -2px; }
.tank-tanks:empty { display: none; }
.tank-tanks .check { flex: 0 0 21.875%; flex-direction: column; align-items: center; gap: 2px; margin: 0; white-space: nowrap; } /* one tank's width in the 320 diagram (tank.js tw 70) */
.tank-gauges { justify-content: space-around; margin: 12px 0 4px; }
.tank-card .tank-speeds, .tank-card .tank-mix { margin-top: 12px; }
/* [Sprout] Live What If (Travis Oct 18 7:29 PM): the rig's own photo with the gauges over it, no motion; the Speed Sheet grouped by
   nozzle (details + .set-row summary, the in-use nozzle open, its row lit); Convert is a .field-ask dialog. */
.tank-dash { position: relative; margin: 4px 0 12px; }
.tank-pic, .rachio-pic { display: block; width: 100%; max-height: 300px; object-fit: contain; border-radius: var(--card-radius, 12px); } /* the whole machine (maker shots are cut-outs on white), gauges right under it */
.rachio-pic { max-height: 220px; margin: 4px 0 12px; } /* the controller photo at the top of the Rachio panel (same cut-out rule) */
/* [Integrations] Rachio panel in the Rachio app's look (Travis Oct 18 2026): a status hero, zone photo tiles with Run, schedule and history
   cards. White rounded cards with soft tints of the Style's own --blue, so Default, LMN and SA each keep their accent. */
.rc-hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); gap: 16px; align-items: center; padding: 14px; margin: 6px 0 14px; border-radius: 16px; background: color-mix(in srgb, var(--blue) 7%, #fff); border: 1px solid color-mix(in srgb, var(--blue) 18%, #fff); }
.rc-hero.on { border-color: var(--blue); }
.rc-hero .rachio-pic { margin: 0; max-height: 190px; background: #fff; }
.rc-stat { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.rc-big { font-size: 1.35rem; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rc-wx { display: flex; gap: 6px; margin: 6px 0 2px; min-width: 0; }
.rc-day { background: #fff; white-space: nowrap; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.rc-day.wet { background: color-mix(in srgb, var(--blue) 16%, #fff); }
.rc-acts { margin-top: 6px; gap: 8px; flex-wrap: nowrap; }
.rc-acts form, .rc-zone form { margin: 0; }
.rc-h { display: flex; align-items: baseline; gap: 8px; margin: 14px 0 8px; }
.rc-zones { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 12px; }
.rc-zone { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 8px 8px 10px; background: #fff; border: 1px solid var(--line); border-radius: 16px; box-shadow: 0 1px 3px rgba(0, 0, 0, .06); }
.rc-zone.on > b { color: var(--blue); } /* watering now: see-through blue over the photo + drop badge; Quick Run picks keep the thin outline */
.rc-zone.on .rc-zpic::after { content: ""; position: absolute; inset: 0; background: color-mix(in srgb, var(--blue) 35%, transparent); pointer-events: none; }
.rc-zpic .rc-num, .rc-drop { z-index: 1; }
.rc-drop { position: absolute; right: 8px; top: 8px; width: 28px; height: 28px; border-radius: 999px; background: #fff; display: flex; align-items: center; justify-content: center; box-shadow: 0 1px 3px rgba(0, 0, 0, .2); }
.rc-drop::before { content: ""; width: 11px; height: 11px; margin-top: 3px; background: var(--blue); border-radius: 50% 0 50% 50%; transform: rotate(-45deg); }
.rcw-zone .rc-drop { width: 22px; height: 22px; right: 5px; top: 5px; }
.rcw-zone .rc-drop::before { width: 9px; height: 9px; }
.rc-qr.rc-wait { pointer-events: none; } /* sending: the tapped zone already shows blue, so no dimming */
.rc-zone > b, .rc-zone > .muted { padding: 0 4px; font-size: .9rem; }
.rc-zone > .muted { font-size: .78rem; }
.rc-zpic { position: relative; aspect-ratio: 4 / 3; border-radius: 12px; overflow: hidden; margin-bottom: 6px; background: linear-gradient(135deg, color-mix(in srgb, var(--blue) 30%, #fff), color-mix(in srgb, var(--blue) 10%, #fff)); }
.rc-zpic { display: block; }
.rc-zpic img { width: 100%; height: 100%; object-fit: cover; display: block; } /* a photo that fails to load leaves the tint below it */
label.rc-zone { cursor: pointer; margin: 0; color: var(--ink); font-size: inherit; font-weight: inherit; }
.rc-pick { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.rc-zone { position: relative; }
.rc-zone:has(.rc-pick:focus-visible) { outline: 2px solid var(--blue); outline-offset: 2px; }
.rc-check { position: absolute; right: 8px; top: 8px; width: 28px; height: 28px; border-radius: 999px; border: 2px solid #fff; background: rgba(0, 0, 0, .25); color: transparent; display: flex; align-items: center; justify-content: center; font-weight: 800; }
.rc-zone:has(.rc-pick:checked) { border-color: var(--blue); box-shadow: 0 0 0 2px color-mix(in srgb, var(--blue) 30%, #fff); }
.rc-zone:has(.rc-pick:checked) .rc-check { background: var(--blue); border-color: var(--blue); color: #fff; }
.rc-zmeta { display: flex; align-items: center; gap: 6px; padding: 0 4px; min-width: 0; }
.rc-zmeta > .muted { flex: 1 1 auto; min-width: 0; font-size: .78rem; }
.rc-zmeta select { flex: 0 0 auto; width: auto; padding: 4px 22px 4px 8px; font-size: .78rem; }
.rc-qrbar { display: flex; align-items: center; min-height: 52px; margin-top: 12px; padding: 8px 12px; background: #fff; border: 1px solid var(--line); border-radius: 16px; box-shadow: 0 4px 14px rgba(0, 0, 0, .08); }
.rc-qr-go { display: none; align-items: center; gap: 8px; width: 100%; min-width: 0; }
.rc-qr-go > b { flex: 1 1 auto; min-width: 0; }
.rc-qr-go select { flex: 0 1 auto; width: auto; min-width: 0; }
.rc-qr-go button { flex: none; }
.rc-qr:has(.rc-pick:checked) .rc-qr-go { display: flex; }
.rc-qr:has(.rc-pick:checked) .rc-qr-hint { display: none; }
.rc-qr:has(.rc-pick:checked) .rc-qrbar { border-color: var(--blue); }
.rc-box .set-row form { margin: 0; flex: none; }
.rc-turf .rc-zpic { background: linear-gradient(135deg, color-mix(in srgb, var(--grass) 70%, #fff), color-mix(in srgb, var(--grass) 60%, var(--ink))); }
.rc-drip .rc-zpic { background: linear-gradient(135deg, color-mix(in srgb, var(--orange) 45%, #fff), color-mix(in srgb, var(--orange) 55%, var(--ink))); }
.rc-shrubs .rc-zpic { background: linear-gradient(135deg, color-mix(in srgb, var(--grass) 50%, var(--navy)), color-mix(in srgb, var(--grass) 30%, var(--navy))); }
.rc-flowers .rc-zpic { background: linear-gradient(135deg, color-mix(in srgb, var(--red) 35%, #fff), color-mix(in srgb, var(--red) 70%, var(--navy))); }
.rc-trees .rc-zpic { background: linear-gradient(135deg, color-mix(in srgb, var(--grass) 55%, var(--ink)), color-mix(in srgb, var(--grass) 30%, var(--ink))); }
.rc-garden .rc-zpic { background: linear-gradient(135deg, color-mix(in srgb, var(--grass) 45%, #fff), color-mix(in srgb, var(--orange) 40%, var(--ink))); }
.rc-num { position: absolute; left: 8px; top: 8px; min-width: 28px; height: 28px; padding: 0 6px; border-radius: 999px; background: #fff; color: var(--ink); font-weight: 700; display: flex; align-items: center; justify-content: center; font-size: .85rem; }
.rc-zpic .badge { position: absolute; right: 8px; top: 8px; }
.rc-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 14px 0 6px; }
.rc-box { min-width: 0; padding: 4px 14px 8px; background: #fff; border: 1px solid var(--line); border-radius: 16px; }
.rc-box .rc-h { margin-top: 10px; }
.rc-box .set-row { padding-left: 0; padding-right: 0; min-height: 44px; }
/* [Integrations] Schedule rows: Run Now, Skip Next and Adjust (Seasonal Adjust) stay on one line; what doesn't fit goes into More (fit-row.js). */
.rc-sc { gap: 8px; }
.rc-sc .set-txt { flex: 1 1 auto; min-width: 72px; flex-direction: column; align-items: stretch; gap: 0; } /* name over its zones, minutes and start time */
.rc-sc .set-txt b { flex: none; min-width: 0; }
.rc-sc .rc-adj { flex: none; }
.rc-sact { display: flex; flex: 0 1 auto; min-width: 0; margin-left: auto; gap: 6px; flex-wrap: nowrap; } /* no flex-end: an overflow to the left would not count as too wide for fit-row.js */
.rc-sact > form { margin: 0; flex: none; }
.rc-sact button, .rc-sact .btn, .rc-sact summary.btn { padding: 6px 12px; min-height: 0; white-space: nowrap; }
.rc-edit { margin: 6px 0 2px; }
.rc-pct input[type=range] { width: 100%; height: 28px; margin: 0; padding: 0; border: 0; background: none; box-shadow: none; accent-color: var(--blue); }
/* [Integrations] Seasonal Adjust sheets: the buttons stack full width, so "Adjust 3 Controllers to +20%" stays on one line. */
.rc-all .row.rc-stack { flex-direction: column; align-items: stretch; gap: 8px; }
.rc-all .rc-stack > button { width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rc-pct > span:first-child { display: flex; justify-content: space-between; }
.rc-pct-ends { display: flex; justify-content: space-between; gap: 8px; white-space: nowrap; }
/* [Integrations] Dashboard Controllers widget (widgets.php widget_controllers): the Rachio panel look at each widget size. */
.rcw { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.rcw-paused { align-self: flex-start; max-width: 100%; }
.rcw-counts { display: flex; gap: 8px; min-width: 0; }
.rcw-n { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; padding: 6px 4px; border-radius: 12px; background: color-mix(in srgb, var(--blue) 7%, #fff); white-space: nowrap; }
.rcw-n b { font-size: 1.2rem; line-height: 1.1; }
.rcw-n .muted { font-size: .72rem; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.rcw-n.on { background: color-mix(in srgb, var(--blue) 18%, #fff); color: var(--blue); }
.rcw-n.bad b { color: var(--red); }
.rcw-top { display: flex; align-items: center; gap: 8px; min-width: 0; color: var(--ink); white-space: nowrap; }
.rcw-top .dw-t { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.rcw .badge { flex: none; max-width: 62%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rcw-rows { display: flex; flex-direction: column; min-width: 0; }
.rcw-row { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--paper); color: var(--ink); min-width: 0; white-space: nowrap; }
.rcw-row:last-child { border-bottom: 0; }
/* [Integrations] Favorites (Travis, Oct 18 2026 10:40 PM): the star beside each controller row, in the hero and on Controllers. */
.rcw-roww { display: flex; align-items: center; gap: 4px; min-width: 0; border-bottom: 1px solid var(--paper); }
.rcw-roww:last-child { border-bottom: 0; }
.rcw-roww > .rcw-row { flex: 1 1 auto; border-bottom: 0; }
.rc-fav-f { display: inline-flex; flex: none; margin: 0; }
button.quiet.rc-fav, .rc-fav { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 32px; height: 32px; min-height: 0; padding: 0; border: 0; border-radius: 999px; background: none; color: var(--muted); font-size: 1.25rem; line-height: 1; cursor: pointer; box-shadow: none; }
button.quiet.rc-fav:hover { background: var(--paper); color: var(--orange); }
button.quiet.rc-fav.on, .rc-fav.on { color: var(--orange); }
span.rc-fav { width: auto; height: auto; cursor: default; font-size: inherit; }
.rcw-hname { display: flex; align-items: center; gap: 2px; min-width: 0; }
.rcw-hname .rc-big { min-width: 0; }
.rc-favcell { display: inline-flex; align-items: center; gap: 2px; min-width: 0; max-width: 100%; }
h2 .rc-fav-f { vertical-align: middle; margin-left: 4px; }
.rcw-row:hover b { color: var(--blue); }
.rcw-pic, .rcw-hpic { flex: none; display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 10px; overflow: hidden; background: color-mix(in srgb, var(--blue) 7%, #fff); color: var(--blue); }
.rcw-pic img, .rcw-hpic img { width: 100%; height: 100%; object-fit: contain; background: #fff; }
.rcw-txt { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.rcw-txt .muted { font-size: .78rem; }
/* [Integrations] Large Controllers widget: every big spot sits in the same grid cell (the tallest sets the height, so a swap never
   moves the rows); only the shown one is visible. A row that swaps it is a button; its name stays the page link. */
.rcw-big { display: grid; min-width: 0; }
.rcw-spot { grid-area: 1 / 1; display: flex; flex-direction: column; gap: 8px; min-width: 0; visibility: hidden; }
.rcw-spot.on { visibility: visible; }
.rcw-swap { cursor: pointer; border-radius: 10px; }
.rcw-swap.on { background: var(--paper); }
.rcw-swap .rcw-name { color: var(--ink); font-weight: 700; }
.rcw-swap .rcw-name:hover { color: var(--blue); }
.rcw-hero { grid-template-columns: 96px minmax(0, 1fr); gap: 12px; padding: 10px 12px; margin: 0; }
.rcw-hpic { width: 96px; height: 96px; border-radius: 12px; }
.rcw-hpic svg { width: 40px; height: 40px; }
.rcw-hero .rc-big { color: var(--ink); font-size: 1.1rem; }
.rcw-hero .badge { align-self: flex-start; }
.rcw-hero .rc-wx { margin: 2px 0 0; }
.rcw-qr { margin: 0; }
.rcw-zones { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); grid-auto-rows: auto; gap: 8px; }
.rcw-zone { padding: 4px 4px 6px; border-radius: 12px; }
.rcw-zone .rc-zpic { margin-bottom: 4px; border-radius: 9px; }
.rcw-zone .rc-num { min-width: 22px; height: 22px; left: 5px; top: 5px; font-size: .72rem; }
.rcw-zone .rc-check { width: 22px; height: 22px; right: 5px; top: 5px; font-size: .75rem; }
.rcw-zone > b { font-size: .76rem; padding: 0 2px; }
.rcw-acts { margin-top: 8px; gap: 8px; flex-wrap: nowrap; align-items: center; }
.rcw-acts .rc-qr-hint { flex: 1 1 auto; min-width: 0; }
.rcw-go { display: none; }
.rcw-sc { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line); min-width: 0; }
.rcw-sc .rcw-sc-l { flex: 0 0 auto; }
.rcw-sc .rcw-sc-n { flex: 1 1 auto; min-width: 0; width: auto; margin: 0; }
.rcw-sc button, .rcw-sc .badge { flex: 0 0 auto; white-space: nowrap; }
.rcw-sc button { padding: 6px 12px; min-height: 0; }
.rcw-qr:has(.rc-pick:checked) .rcw-go { display: inline-flex; }
.rcw-qr:has(.rc-pick:checked) .rc-qr-hint { display: none; }
.rcw-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: auto; min-width: 0; white-space: nowrap; }
.rcw-all, .rc-allbar { gap: 8px; flex-wrap: nowrap; align-items: center; }
.rcw-all button, .rc-allbar button { padding: 6px 12px; min-height: 0; }
.rc-allbar { margin: 4px 0 10px; }
.rc-all { white-space: normal; text-align: left; overflow-x: hidden; }
/* [Integrations] Pause All / Resume All / Adjust All sheets never scroll sideways (Travis, Oct 18 2026 10:42 PM): the buttons share the row
   and keep one line; when the sheet is narrower than the row needs, they stack full width (same font, same look). */
.rc-all form { container: rcall / inline-size; }
.rc-all .row > button { min-width: 0; white-space: nowrap; }
@container rcall (max-width: 400px) { .rc-all .row { flex-direction: column; align-items: stretch; } .rc-all .row > button { width: 100%; } }
.rc-all label { display: flex; flex-direction: column; gap: 4px; margin: 10px 0; }
.rc-all select, .rc-all input { width: 100%; }
.rcw .rcw-paused { max-width: 100%; }
.rc-all .row { flex-wrap: nowrap; margin-top: 12px; }
.rcw-medium .rcw-row .badge { max-width: 50%; }
.rc-hero.rcw-hero { grid-template-columns: 96px minmax(0, 1fr); }
.rcw-hero .badge { max-width: 100%; }
.rcw-zones { grid-template-rows: auto; grid-auto-rows: 0; row-gap: 0; overflow: hidden; } /* one strip: tiles that don't fit the first row are hidden */
.rcw-zone { margin-bottom: 2px; }
@media (max-width: 600px) {
  .rc-hero.rcw-hero { grid-template-columns: 64px minmax(0, 1fr); gap: 10px; }
  .rcw-hpic { width: 64px; height: 64px; }
  .rcw-hero .rc-wx { gap: 4px; }
  .rcw-hero .rc-day { padding: 2px 6px; font-size: .74rem; flex: 0 0 auto; }
  .rcw-zones { grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); }
  .fz-bar { flex-wrap: wrap; }
  .fz-txt { flex: 1 1 calc(100% - 40px); }
  .fz-bar > button { flex: 1 1 100%; }
}
.rc-box .set-row .muted { white-space: nowrap; }
@media (max-width: 700px) {
  .rc-hero { grid-template-columns: minmax(0, 1fr); gap: 10px; padding: 12px; }
  .rc-hero .rachio-pic { max-height: 130px; }
  .rc-hi { display: none; } /* phones: day, sky and rain chance only, so the three days fit one line */
  .rc-zones { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .rc-cards { grid-template-columns: minmax(0, 1fr); }
  .rc-acts > form { flex: 1 1 0; }
  .rc-acts button { width: 100%; }
  .rc-qr:has(.rc-pick:checked) .rc-qrbar { position: fixed; left: 12px; right: 12px; bottom: 76px; z-index: 20; margin: 0; } /* phones: Quick Run floats above the bottom menu once a zone is picked (main clips sticky) */
  .rc-zmeta > .muted { display: none; }
  .rc-zmeta select { flex: 1 1 auto; }
  .rc-qrbar .rc-qr-go > b { display: none; } /* phones: the bar is just the length pick and Start */
  .rc-qr-go select { flex: 1 1 auto; }
}
.tank-dash.has-pic .tank-gauges { margin: 8px 0 0; }
/* [Integrations] Hero (Travis 7:54 PM): the machine photo and the nozzle diagram side by side, gauges under both; phones stack them. */
.tank-hero { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; align-items: center; }
.tank-dash.has-pic .tank-hero { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.tank-spray { min-width: 0; }
.tank-dash.has-pic .tank-hero:has(> .tank-spray[hidden]) { grid-template-columns: minmax(0, 1fr); } /* hand wand: the photo alone */
.tank-spray .tank-rig { margin-top: 0; }
.tank-what { display: flex; justify-content: center; align-items: center; gap: 8px; min-width: 0; margin: 8px 0 0; font-size: .85rem; color: var(--ink); white-space: nowrap; } /* under photo + diagram, one line */
.tank-what[hidden] { display: none; }
.tank-what-t { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.tank-what .badge { flex: none; }
.tank-what-short { display: none; }
.tank-levers .set-switch { margin-right: 6px; }
.tank-gauges figure[hidden] { display: none; }
.tank-sheet { margin-top: 14px; }
.tank-sheet h3 { margin: 0 0 6px; font-size: .95rem; white-space: nowrap; }
.tank-group > summary, .rachio-link > summary, .zone-fold > summary { cursor: pointer; list-style: none; padding-left: 0; padding-right: 0; min-height: 48px; }
.tank-group > summary::-webkit-details-marker, .rachio-link > summary::-webkit-details-marker, .zone-fold > summary::-webkit-details-marker { display: none; }
.tank-group[open] > summary .set-chev, .rachio-link[open] > summary .set-chev, .zone-fold[open] > summary .set-chev { transform: rotate(90deg); }
.tank-group .set-row .badge { display: inline-block; }
table.tank-chart { margin: 0 0 10px; table-layout: fixed; }
table.tank-chart th, table.tank-chart td { padding: 8px 6px; white-space: nowrap; }
table.tank-chart .num { text-align: right; font-variant-numeric: tabular-nums; }
table.tank-chart th:first-child, table.tank-chart td:first-child { text-align: left; }
table.tank-chart tr:not(:first-child) { cursor: pointer; }
table.tank-chart th.on, table.tank-chart td.on { color: var(--ink); font-weight: 700; }
table.tank-chart tr.on td { background: var(--paper); font-weight: 700; }
table.tank-chart tr.on td:first-child { box-shadow: inset 3px 0 0 var(--grass); }
table.tank-chart tr.tank-chart-note td { padding-top: 0; font-size: .8rem; white-space: normal; }
.tank-conv-rate { display: grid; grid-template-columns: minmax(0, 1fr) 84px 110px; gap: 8px; }
.field-ask .tank-conv-out { margin: 4px 0 0; color: var(--ink); font-weight: 650; white-space: nowrap; }
.tank-conv .pills:empty { display: none; }
@media (max-width: 600px) {
  .tank-gauges { flex-wrap: nowrap; gap: 6px; }
  .tank-gauges figure { flex: 1 1 0; min-width: 0; font-size: .72rem; }
  .tank-gauges .sx-gauge { width: 72px; height: 72px; margin: 0 auto; }
  .tank-dash.has-pic .tank-hero { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .tank-pic { max-height: 220px; }
  .tank-levers[data-levers] { flex-wrap: nowrap; gap: 8px 12px; }
  .tank-levers .tank-n { display: none; }
  .tank-what-long { display: none; }
  .tank-what-short { display: inline; }
  .tank-levers .set-switch { margin-right: 4px; }
  .tank-dash .tank-gauges { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px 6px; margin: 10px 0 0; }
  .tank-dash .tank-gauges .sx-gauge { width: 64px; height: 64px; }
  table.tank-chart th, table.tank-chart td { padding: 8px 3px; font-size: .82rem; }
  table.tank-chart th { font-size: .66rem; letter-spacing: .02em; }
}
.job-files-card.eq-list h3 { margin: 0 0 6px; font-size: .95rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.job-files-card.eq-list h3 + .zone-grid { margin-bottom: 4px; }
.job-files-card.eq-list .set-row + h3, .job-files-card.eq-list .eq-note + h3 { margin-top: 14px; }
.job-files-card.eq-list .set-row { min-height: 40px; padding-top: 6px; padding-bottom: 6px; }
.job-files-card { margin: 12px; padding: 12px; background: #fff; border-radius: 16px; box-shadow: 0 10px 24px rgba(16, 24, 40, .12); }
.job-files-card > p { margin: 0 0 12px; color: var(--muted); font-size: .78rem; }
.pic-open { display: inline-flex; align-items: center; gap: 4px; height: 32px; min-height: 32px; padding: 0 8px; }
.pic-open .ico { width: 16px; height: 16px; }
.pic-open b { font-size: .75rem; font-weight: 750; }
.pic-tile { position: relative; }
.pic-share { margin: 4px 0 0; }
.pic-share .check { font-size: .75rem; color: var(--muted); }
.pic-shot, .pic-shot:hover { display: block; width: 100%; height: auto; min-height: 0; padding: 0; border: 0; border-radius: 12px; background: transparent; overflow: hidden; box-shadow: none; }
.pic-del, .pic-del:hover { position: absolute; top: 6px; right: 6px; z-index: 2; display: flex; align-items: center; justify-content: center; width: 22px; height: 22px; min-height: 22px; margin: 0; padding: 0; border: 0; border-radius: 50%; background: var(--red); color: #fff; line-height: 0; box-shadow: none; }
.pic-del svg { width: 12px; height: 12px; display: block; }
a.photo-place { display: inline-flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 1px; height: auto; min-height: 36px; margin: 0 0 12px; padding: 6px 14px; border: 1px solid var(--line); border-radius: 999px; background: #fff; color: var(--ink); text-decoration: none; line-height: 1.15; }
a.photo-place:hover { border-color: var(--blue); background: var(--paper); color: var(--ink); }
a.photo-place b, a.photo-place span { display: block; }
a.photo-place b { font-size: .85rem; font-weight: 750; }
a.photo-place span { color: var(--muted); font-size: .72rem; font-weight: 500; }
.job-files { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 12px; }
.job-files img, .prop-pics img { width: 100%; height: 96px; object-fit: cover; display: block; background: var(--paper); }
.eq-pics img { height: 120px; object-fit: contain; border: 1px solid var(--line); } /* equipment photo: the whole machine, not a cropped strip (Oct 19 2026) */
.file-pick { position: relative; display: inline-flex; align-items: center; justify-content: center; height: 36px; min-height: 36px; padding: 0 16px; border: 1px solid var(--blue); border-radius: 999px; background: var(--blue); color: #fff; font: inherit; font-weight: 650; font-size: .85rem; cursor: pointer; overflow: hidden; }
.file-pick:hover { background: #1873cc; border-color: #1873cc; }
.file-pick input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.photo-add { margin-top: 12px; }
.job-past { margin: 0 12px; }
.job-past article { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr); gap: 10px; align-items: start; padding: 12px 0; border-bottom: 1px solid var(--line); }
.job-past b, .job-past span, .job-past em { display: block; }
.job-past span, .job-past em, .job-past p { color: var(--muted); font-size: .75rem; font-style: normal; margin: 0; }
.job-past p { text-align: right; }
.field-burger:hover { background: transparent; color: inherit; border-color: transparent; }
.field-shade { position: fixed; inset: 0; background: rgba(17, 17, 17, .45); z-index: 80; }
.field-menu { width: min(300px, 82vw); height: 100%; background: var(--ink); color: #fff; padding: calc(18px + env(safe-area-inset-top)) 12px 24px; display: flex; flex-direction: column; gap: 4px; border-right: 3px solid var(--grass); }
.field-menu p { margin: 14px 8px 4px; color: #9a9a9a; font-size: .75rem; letter-spacing: .04em; text-transform: uppercase; }
.field-menu a, .field-menu button { display: block; width: 100%; text-align: left; background: transparent; color: #eee; border: 0; border-radius: 8px; padding: 12px; text-decoration: none; font: inherit; font-weight: 650; height: auto; min-height: 0; }
.field-menu a.on, .field-menu button.on, .field-menu a:hover, .field-menu button:hover { background: var(--navy); color: #fff; }
.field-ask { border: 0; border-radius: 16px; padding: 18px; width: min(360px, calc(100% - 32px)); }
.field-ask[open] { display: flex; flex-direction: column; gap: 8px; }
.field-ask h2 { margin: 0 0 6px; }
.field-ask p { margin: 0 0 14px; color: var(--muted); }
.field-ask form { display: flex; flex-direction: column; gap: 8px; }
.field-ask button, .field-ask a.btn { width: 100%; }
.field-ask::backdrop { background: rgba(17, 17, 17, .45); }
@media (max-width: 800px) {
  input, select, textarea { font-size: 16px; }
}

/* [Messages and Emails] Emails (emails.php) and the shared editor (assets/editor.js) */
.nav-count { margin-left: auto; padding: 1px 8px; }
.side nav .nav-count { margin-top: -4px; margin-bottom: -4px; } /* a count filling in (about 1.5 s after load) never makes its menu row taller */
.mail-toast span { cursor: pointer; }
.mail-new td { font-weight: 700; }
.mail-split { display: grid; grid-template-columns: 340px minmax(0, 1fr); gap: 16px; align-items: start; }
.mail-bar { margin-bottom: 16px; }
.mail-split .mail-list { position: sticky; top: 12px; max-height: calc(100vh - 24px); overflow-y: auto; overflow-x: hidden; }
.mail-avatar { flex: none; display: inline-grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: var(--blue); color: #fff; font-weight: 750; }
.mail-avatar.ours { background: var(--ink); }
.mail-msg { border: 1px solid var(--line); border-radius: 12px; margin: 0 0 12px; }
.mail-msg.focus { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(30, 144, 255, .16); scroll-margin: 80px; }
.mail-msg > summary { display: flex; gap: 12px; align-items: flex-start; padding: 12px 14px; cursor: pointer; list-style: none; }
.mail-msg > summary::-webkit-details-marker { display: none; }
.mail-msg.ours > summary { background: var(--paper); border-radius: 12px; }
.mail-who { flex: 1; min-width: 0; }
.mail-line { display: flex; gap: 10px; align-items: baseline; min-width: 0; }
.mail-cut { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mail-date { margin-left: auto; flex: none; white-space: nowrap; }
.mail-stack { display: grid; }
.mail-item { display: flex; gap: 10px; min-width: 0; max-width: 100%; box-sizing: border-box; align-items: flex-start; padding: 10px; border-bottom: 1px solid var(--line); color: var(--ink); text-decoration: none; }
.mail-item:hover, .mail-item.on { background: var(--paper); }
.mail-item.on { box-shadow: inset 3px 0 0 var(--blue); }
.mail-item.mail-new .mail-cut { font-weight: 700; }
.mail-item .pills { margin-top: 4px; display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; }
.mail-item .mail-line > .mail-cut { flex: 1 1 auto; }
.mail-item .mail-who > .mail-cut { font-size: .85rem; margin-top: 2px; }
.mail-item .mail-date { font-size: .78rem; }
.mail-peek { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mail-msg[open] .mail-peek { display: none; }
.mail-body { padding: 12px 14px 14px 60px; }
.mail-actions { margin: 0 0 16px; }
.mail-text { overflow-wrap: anywhere; }
.mail-unread-note { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0 0 10px; padding: 8px 12px; border-radius: 10px; background: var(--paper); font-size: .9rem; }
.mail-frame { width: 100%; min-height: 80px; border: 0; display: block; }
.mail-thumbs { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0; }
.mail-thumb { display: block; max-width: 240px; max-height: 180px; border-radius: 12px; border: 1px solid var(--line); }
.mail-fields { display: grid; grid-template-columns: auto 1fr; gap: 8px 12px; align-items: center; margin-bottom: 12px; }
.mail-fields label { margin: 0; }
.editor { border: 1px solid #d5deea; border-radius: 8px; background: #fff; }
.editor:focus-within { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(30, 144, 255, .16); }
.editor-bar { display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center; padding: 6px; border-bottom: 1px solid var(--line); background: var(--paper); border-radius: 8px 8px 0 0; }
.editor-group { display: inline-flex; flex-wrap: nowrap; gap: 2px; align-items: center; }
.editor-bar button, .editor-bar select { height: 32px; min-height: 32px; margin: 0; border-radius: 8px; font-size: .85rem; line-height: 1; }
.editor-bar button { min-width: 32px; width: 32px; padding: 0; display: inline-flex; align-items: center; justify-content: center; }
.editor-bar button.on { background: var(--ink); color: #fff; }
.editor-bar select { width: 7.2rem; padding: 0 24px 0 10px; }
.editor-area { padding: 12px; outline: none; overflow-wrap: anywhere; max-height: 70vh; overflow-y: auto; }
.editor-area img { max-width: 100%; height: auto; }
.editor-area blockquote { margin: 8px 0; padding-left: 12px; border-left: 3px solid var(--line); color: var(--muted); }
.editor-source { border: 0; border-radius: 0 0 8px 8px; }
pre.editor-source, textarea.editor-source { display:block; width:100%; max-width:100%; overflow:auto; white-space:pre-wrap; word-break:break-word; background:var(--paper); border:1px solid var(--line); border-radius:8px; padding:12px; font-family:Consolas,monospace; font-size:.85rem; }
textarea.editor-source { min-height:180px; resize:vertical; background:var(--ink); color:#fff; border-color:var(--ink); }
@media (max-width: 800px) {
  .mail-split { display: block; }
  .mail-split.is-open .mail-list { display: none; }
  .mail-split:not(.is-open) .mail-pane { display: none; }
  .mail-body { padding: 12px; }
  .mail-fields { grid-template-columns: 1fr; }
}
/* [Messages and Emails] Messages (messages.php): iPhone-style thread. Header and compose bar stay put; only .mt-scroll scrolls. */
.chat { display: flex; flex-direction: column; gap: 6px; max-height: 60vh; overflow-y: auto; padding: 12px 8px; margin: 12px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.chat-day { align-self: center; margin: 10px 0 2px; font-size: .75rem; font-weight: 600; }
.bubble { max-width: 78%; align-self: flex-start; background: var(--paper); position: relative; border-radius: 18px; padding: 8px 12px; overflow-wrap: anywhere; }
.bubble.ours { align-self: flex-end; background: var(--blue); color: #fff; border-radius: 18px; }
.bubble.same { margin-top: -3px; }
.bubble a { color: inherit; }
.bubble img { display: block; max-width: 100%; max-height: 320px; border-radius: 14px; }
.bubble a + a, .bubble a + div { margin-top: 6px; display: block; }
.bubble.pic-only { background: none; padding: 0; }
/* Tracker 886 (old 322): iPhone-style tails, only on the last bubble of a run (the next bubble is not a .same one). */
.bubble:not(.pic-only):not(:has(+ .bubble.same))::after { content: ""; position: absolute; bottom: 0; left: -6px; width: 12px; height: 14px; background: inherit; -webkit-mask: radial-gradient(circle at 0 0, transparent 11px, black 12px); mask: radial-gradient(circle at 0 0, transparent 11px, black 12px); }
.bubble:not(.pic-only):not(.ours):not(:has(+ .bubble.same)) { border-bottom-left-radius: 6px; }
.bubble.ours:not(.pic-only):not(:has(+ .bubble.same)) { border-bottom-right-radius: 6px; }
.bubble.ours:not(.pic-only):not(:has(+ .bubble.same))::after { left: auto; right: -6px; -webkit-mask: radial-gradient(circle at 100% 0, transparent 11px, black 12px); mask: radial-gradient(circle at 100% 0, transparent 11px, black 12px); }
.chat-meta { color: var(--muted); font-size: .75rem; margin-top: -2px; align-self: flex-start; }
.chat-meta.ours { align-self: flex-end; }
.chat-meta.bad { color: var(--red); }
.mt-thread { display: flex; flex-direction: column; padding: 0; overflow: hidden; position: relative; }
.mt-head { flex: none; display: flex; gap: 10px; align-items: center; padding: 10px 16px; border-bottom: 1px solid var(--line); background: #fff; }
.mt-head label { margin: 0; }
.mt-head input { flex: 1; min-width: 0; }
.mt-who { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.mt-who a.muted { color: var(--muted); font-size: .85rem; text-decoration: none; }
/* [Shared] Few texts sit at the bottom by the compose bar, like the iPhone; the space is above them (margin-top:auto keeps scrolling intact). */
.mt-scroll > :first-child { margin-top: auto; }
.mt-scroll { flex: 1 1 auto; min-height: 0; overflow-anchor: none; max-height: none; margin: 0; padding: 8px 16px 12px; border: 0; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.mt-compose { flex: none; position: relative; padding: 8px 12px; border-top: 1px solid var(--line); background: #fff; }
.mt-bar { display: flex; align-items: flex-end; gap: 6px; }
button.mt-ico { flex: none; width: 34px; min-width: 34px; height: 34px; min-height: 34px; padding: 0; border-radius: 50%; color: var(--muted); }
button.mt-ico svg { width: 20px; height: 20px; display: block; }
.mt-field { flex: 1; min-width: 0; display: flex; align-items: flex-end; gap: 6px; border: 1px solid var(--line); border-radius: 18px; background: #fff; padding: 2px 2px 2px 12px; }
.mt-field:focus-within { border-color: var(--blue); }
.mt-field textarea { flex: 1; min-width: 0; width: auto; height: 30px; min-height: 30px; margin: 0; padding: 5px 0; border: 0; border-radius: 0; outline: 0; box-shadow: none; resize: none; background: transparent; line-height: 1.4; overflow-y: auto; }
.mt-field textarea:focus { box-shadow: none; border: 0; }
button.mt-send { flex: none; width: 30px; min-width: 30px; height: 30px; min-height: 30px; padding: 0; border-radius: 50%; }
button.mt-send svg { width: 18px; height: 18px; }
button.mt-send:disabled { opacity: .5; }
.mt-count { display: block; text-align: right; margin-top: 4px; }
.mt-count:empty { display: none; }
.mt-pic { position: relative; display: inline-block; margin: 0 0 8px 80px; }
.mt-pic img { display: block; max-height: 120px; max-width: 200px; border-radius: 14px; border: 1px solid var(--line); }
.mt-pic-x { position: absolute; top: -8px; right: -8px; --x-size: 26px; } /* shared X close (Tracker 880), sitting on the picture */
.mt-pic[hidden], .mt-menu[hidden], .mt-emoji[hidden], .mt-new[hidden] { display: none; }
.mt-compose .status-menu { top: auto; bottom: calc(100% + 6px); left: 12px; }
.mt-menu { display: grid; gap: 6px; width: 300px; }
.mt-menu select { width: 100%; }
.mt-menu .hint { margin: 2px 4px 4px; }
.mt-emoji { display: grid; grid-template-columns: repeat(8, 36px); gap: 2px; padding: 8px; min-width: 0; }
.mt-emoji button { width: 36px; min-width: 36px; height: 36px; min-height: 36px; padding: 0; border: 0; border-radius: 10px; font-size: 22px; line-height: 1; background: none; }
.mt-emoji button:hover { background: var(--paper); }
button.mt-new { position: absolute; z-index: 2; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%); height: 30px; min-height: 30px; padding: 0 14px; box-shadow: 0 6px 16px rgba(11, 42, 69, .18); }
body:has(.mt-thread) .hc-fab { display: none; }
@media (max-width: 800px) {
  html.mt-lock, html.mt-lock body { overflow: hidden; overscroll-behavior: none; }
  body:has(.mail-split.is-open) .mail-bar { display: none; }
  .mt-thread { position: fixed; left: 0; right: 0; z-index: 9; margin: 0; border-radius: 0; border-left: 0; border-right: 0; box-shadow: none; }
  html.mt-kb .phone-dock { display: none; }
  .mt-scroll { padding: 8px 12px 12px; }
  .mt-compose { padding: 6px 8px; }
  .mt-pic { margin-left: 76px; }
  .mt-menu { width: calc(100vw - 24px); left: 4px; }
  .mt-compose .mt-emoji { left: 4px; right: 4px; grid-template-columns: repeat(auto-fill, 40px); justify-content: center; max-height: 240px; }
  .mt-emoji button { width: 40px; min-width: 40px; height: 40px; min-height: 40px; }
}


/* [Messages and Emails] Files — tree + editor only (everything else uses shared list/card/tabs styles) */
.fm { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 16px; align-items: start; }
.fm-tree { position: sticky; top: 12px; max-height: calc(100vh - 160px); overflow: auto; padding-right: 12px; border-right: 1px solid var(--line); }
.fm-tree h2 { display: flex; align-items: center; gap: 6px; margin: 0 0 8px; font-size: .95rem; }
.fm-tree h2 + h2, .fm-tree #fm-tree + h2 { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--line); }
.fm-tree ul { list-style: none; margin: 0; padding: 0 0 0 14px; }
#fm-tree > ul { padding-left: 0; }
.fm-tree li > ul { display: none; }
.fm-tree li.open > ul { display: block; }
.fm-tree-row { display: flex; align-items: center; gap: 4px; min-width: 0; }
.fm-tw { padding: 0 !important; min-height: 0 !important; height: 22px !important; width: 22px; color: var(--muted) !important; display: inline-flex !important; align-items: center; justify-content: center; flex: none; background: transparent !important; border: 0 !important; box-shadow: none !important; border-radius: 4px !important; }
.fm-tw:hover { background: var(--paper) !important; color: var(--ink) !important; }
.fm-tw .ico { width: 14px; height: 14px; transition: transform .15s ease; }
.fm-tree li.open > .fm-tree-row > .fm-tw .ico { transform: rotate(90deg); }
.fm-tree li > a, .fm-tree-row > a { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1; color: var(--ink); text-decoration: none; padding: 3px 6px; border-radius: 6px; font-size: .85rem; }
.fm-tree li > a:hover, .fm-tree-row > a:hover, .fm-tree a.on { background: var(--paper); color: var(--blue); }
.fm-tree-row .fm-ico { color: var(--muted); flex: none; }
.fm-tree-name { min-width: 0; word-break: break-all; }
.fm-recent li { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; padding: 4px 0; font-size: .85rem; word-break: break-all; }
.fm-recent a { display: inline-flex; align-items: center; gap: 6px; text-decoration: none; color: var(--ink); font-weight: 600; }
.fm-recent a:hover { color: var(--blue); }
.fm-recent .fm-ico { color: var(--muted); flex: none; }
.fm-main .list-results table a { text-decoration: none !important; }
.fm-main .list-results td { vertical-align: middle; }
.fm-recent { list-style: none; margin: 0; padding: 0; }
.fm-main { min-width: 0; overflow: hidden; }
.fm-name { vertical-align: middle; }
.fm-name .fm-ico { display: inline-block; vertical-align: middle; margin-right: 8px; color: var(--muted); line-height: 0; }
.fm-name .fm-ico .ico { width: 16px; height: 16px; }
.fm-name a { color: var(--ink); text-decoration: none; font-weight: 600; word-break: break-all; vertical-align: middle; }
.fm-name a:hover { color: var(--blue); text-decoration: none; }
.fm-ico { color: var(--muted); }
.fm-ico .ico { width: 16px; height: 16px; display: block; }
.fm-crumbs { font-weight: 650; word-break: break-all; margin: 0 0 10px; }
.fm-crumbs a { text-decoration: none; }
.fm-drop { transition: background .15s ease; max-width: 100%; overflow-x: auto; }
.fm-drop.on { background: #E8F3FF; outline: 2px dashed var(--blue); outline-offset: -6px; }
.fm-drop-target, .fm-tree a.fm-drop-target { outline: 2px dashed var(--blue); background: #E8F3FF; }
.fm-editor { position: fixed; inset: 0; z-index: 2000; background: var(--ink); display: flex; flex-direction: column; padding: env(safe-area-inset-top, 0px) 0 env(safe-area-inset-bottom, 0px); }
.fm-editor[hidden] { display: none; }
.fm-ed-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 12px; background: #fff; border-bottom: 1px solid var(--line); }
.fm-ed-gap { flex: 1; }
.fm-ed-host { flex: 1; min-height: 0; }
.fm-tabs { max-width: min(70vw, 900px); }
.fm-menu { position: fixed; z-index: 2100; margin: 0; padding: 6px; list-style: none; min-width: 160px; box-shadow: 0 10px 28px rgba(16, 24, 40, .12); }
.fm-menu[hidden] { display: none; }
.fm-menu button { width: 100%; text-align: left; }
body.fm-editing { overflow: hidden; }
@media (max-width: 800px) {
  .fm { grid-template-columns: minmax(0, 1fr); }
  .fm-tree { position: static; max-height: 200px; border-right: 0; border-bottom: 1px solid var(--line); padding: 0 0 10px; }
}
.role-grid th:not(:first-child), .role-grid td:not(:first-child) { text-align: center; }
.role-grid th input { max-width: 140px; text-align: center; }
.role-grid input[type=checkbox] { width: 18px; height: 18px; }
/* [Shared] Automations builder */
.af-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 16px; align-items: start; }
.af-panel { position: sticky; top: 12px; max-height: calc(100vh - 24px); overflow: auto; }
.af-panel h2 { margin: 0 0 8px; font-size: 1.05rem; }
.af-field { margin-bottom: 10px; }
.af-field label { display: block; }
.af-flow { display: flex; flex-direction: column; align-items: center; padding: 8px 0 24px; }
.af-list { display: flex; flex-direction: column; align-items: center; width: 100%; }
.af-card { width: min(360px, 100%); background: #fff; border: 1px solid var(--line); border-left: 4px solid var(--blue); border-radius: 12px; padding: 10px 14px; cursor: pointer; box-shadow: 0 1px 2px rgba(17, 17, 17, .04); }
.af-card.is-on { box-shadow: 0 0 0 2px var(--blue); }
.af-card.is-off { opacity: .55; }
.af-kind { display: block; font-size: .72rem; font-weight: 750; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.af-sub { display: block; font-weight: 600; overflow-wrap: anywhere; }
.af-trigger, .af-end { border-left-color: var(--navy); }
.af-cond, .af-if { border-left-color: var(--orange); }
.af-wait { border-left-color: var(--muted); }
.af-email, .af-text, .af-notify { border-left-color: var(--grass); }
.af-stop { border-left-color: var(--red); }
.af-join { position: relative; display: flex; flex-direction: column; align-items: center; padding: 6px 0; }
.af-join::before { content: ""; position: absolute; top: 0; bottom: 0; left: 50%; border-left: 2px solid var(--line); }
.af-plus { position: relative; width: 26px; height: 26px; min-height: 26px; padding: 0; border-radius: 50%; line-height: 1; font-weight: 750; }
.af-add-menu { position: absolute; top: 34px; z-index: 5; display: grid; grid-template-columns: 1fr 1fr; gap: 4px; background: #fff; border: 1px solid var(--line); border-radius: 12px; padding: 8px; box-shadow: 0 8px 24px rgba(16, 24, 40, .12); width: 280px; }
.af-branches { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; width: 100%; border-top: 2px solid var(--line); margin-top: 6px; padding-top: 8px; }
.af-branch { display: flex; flex-direction: column; align-items: center; min-width: 0; }
.af-rule { display: flex; gap: 6px; align-items: center; margin-bottom: 6px; }
.af-rule > * { min-width: 0; flex: 1; }
.af-rule > button { flex: 0 0 auto; }
.af-days { display: flex; flex-wrap: wrap; gap: 6px 10px; }
.af-preview { width: 100%; height: 200px; border: 1px solid var(--line); border-radius: 8px; margin-top: 6px; }
@media (max-width: 900px) { .af-wrap { grid-template-columns: 1fr; } .af-panel { position: static; max-height: none; } .af-branches { grid-template-columns: 1fr; } }
.af-line { height: 16px; padding: 0; }
.af-end { margin-top: 0; }
/* [Shared] Tags */
.tag-chip { background: color-mix(in srgb, var(--tag, var(--blue)) 16%, #fff); color: color-mix(in srgb, var(--tag, var(--blue)) 70%, var(--ink)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tag, var(--blue)) 35%, #fff); margin: 2px 4px 2px 0; }
.tag-x { border: 0; border-radius: 0; background: none; padding: 0 0 0 6px; color: inherit; font: inherit; font-size: .9em; cursor: pointer; height: auto; min-height: 0; width: auto; line-height: inherit; box-shadow: none; }
.tag-picker { display: flex; flex-wrap: wrap; align-items: center; gap: 2px; margin: 6px 0; }
.tag-add { position: relative; }
.tag-input { width: 110px; max-width: 100%; padding: 3px 10px; border-radius: 99px; font-size: .8rem; min-height: 0; }
.tag-menu { position: absolute; z-index: 30; top: 100%; left: 0; min-width: 220px; margin-top: 4px; background: #fff; border: 1px solid var(--line); border-radius: 10px; padding: 4px; box-shadow: 0 8px 24px rgba(16, 24, 40, .12); }
.tag-menu button { display: flex; align-items: center; gap: 6px; width: 100%; text-align: left; color: var(--muted); }
.tag-menu button.on { background: var(--paper); }
.tag-row { margin-top: 2px; }
/* .tag-row/.tag-filter .tag-chip: shared pill size (Tracker 880) */
.tag-group { font-size: .72rem; text-transform: uppercase; margin: 6px 0 2px; }
.tag-colors { display: flex; gap: 8px; flex-wrap: wrap; }
.tag-color { position: relative; }
.tag-color input { position: absolute; opacity: 0; inset: 0; margin: 0; }
.tag-color span { display: block; width: 26px; height: 26px; border-radius: 50%; background: var(--tag); cursor: pointer; }
.tag-color input:checked + span { box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--tag); }
.bulk-bar { align-items: center; padding: 8px 0; }
/* [Tasks and Tracker] Tasks */
.task-wrap:has(> #task-panel[hidden]) { grid-template-columns: minmax(0, 1fr); }
.task-quick { display: flex; gap: 8px; }
.task-quick input { flex: 1; }
.task-wrap .task-quick { margin-bottom: 14px; } /* Tasks: same gap as list bar → table */
.qa-anchor { position: relative; }
.qa-help { position: absolute; z-index: 15; top: calc(100% + 6px); left: 0; right: 0; padding: 10px 16px 14px; background: #fff; border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 16px 40px rgba(11, 42, 69, .16); font-size: .8rem; max-height: min(70vh, 560px); overflow-y: auto; opacity: 0; visibility: hidden; transform: translateY(-4px); transition: opacity .14s ease, transform .14s ease, visibility 0s linear .14s; }
.qa-help.qa-open { opacity: 1; visibility: visible; transform: none; transition: opacity .14s ease, transform .14s ease; }
.qa-help code { font: inherit; background: var(--paper); border-radius: 6px; padding: 1px 6px; color: var(--ink); }
.qa-guide { height: 30px; display: flex; flex-wrap: nowrap; align-items: center; gap: 6px; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; margin-bottom: 10px; }
.qa-guide::-webkit-scrollbar { display: none; }
.qa-guide > * { flex: none; }
.qa-idle { color: var(--muted); display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.qa-idle svg { color: var(--grass); }
.qa-bit { --tag: var(--muted); display: inline-flex; align-items: baseline; gap: 5px; max-width: 100%; padding: 2px 9px; border-radius: 999px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  background: color-mix(in srgb, var(--tag) 12%, #fff); color: color-mix(in srgb, var(--tag) 70%, var(--ink)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tag) 30%, #fff); animation: qa-pop .16s ease-out; }
.qa-bit .qa-k { font-weight: 500; font-size: .7rem; text-transform: uppercase; letter-spacing: .04em; opacity: .75; }
.qa-bit[data-kind="task"] { --tag: var(--ink); }
.qa-bit[data-kind="customer"] { --tag: var(--blue); }
.qa-bit[data-kind="person"] { --tag: var(--navy); }
.qa-bit[data-kind="due"] { --tag: var(--orange); }
.qa-bit[data-kind="template"] { --tag: var(--grass); }
.qa-bit[data-kind="priority"] { --tag: var(--red); }
.qa-warn { color: var(--red); font-weight: 600; animation: qa-pop .16s ease-out; }
.qa-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr) minmax(0, 1.25fr); border-top: 1px dashed var(--line); padding-top: 10px; }
.qa-cols > section { padding: 0 14px; min-width: 0; }
.qa-cols > section:first-child { padding-left: 0; }
.qa-cols > section + section { border-left: 1px dashed var(--line); }
.qa-h { margin: 0 0 8px; font-size: .68rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.qa-exs { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.qa-keys { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; color: var(--muted); }
.qa-keys li { display: flex; align-items: center; gap: 8px; }
.qa-keys b { flex: none; width: 22px; height: 22px; display: inline-grid; place-items: center; border-radius: 7px; background: var(--paper); color: var(--ink); font-size: .8rem; }
.qa-order { margin: 8px 0 0; display: grid; gap: 4px; justify-items: start; }
.qa-order code { white-space: nowrap; }
.qa-tpls { display: grid; gap: 8px; }
.qa-tpls > div { display: grid; gap: 3px; justify-items: start; }
.qa-cols p { margin: 0; }
button.qa-ex { margin: 0; height: auto; min-height: 0; padding: 2px 10px; text-align: left; line-height: 1.5; border-radius: 999px; font: inherit; font-weight: 600; background: #fff; color: var(--blue); border: 1px solid var(--line); box-shadow: none; cursor: pointer; transition: border-color .15s, background .15s, transform .1s; }
button.qa-ex:hover, button.qa-ex:focus-visible { border-color: var(--blue); background: color-mix(in srgb, var(--blue) 8%, #fff); }
button.qa-ex:active { transform: scale(.97); }
.qa-sug { position: absolute; z-index: 20; top: calc(100% + 4px); left: 0; right: 0; max-height: 260px; overflow-y: auto; background: #fff; border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 12px 30px rgba(11, 42, 69, .12); padding: 4px; animation: qa-drop .14s ease-out; }
.qa-opt { padding: 7px 10px; border-radius: 8px; cursor: pointer; display: flex; gap: 8px; align-items: baseline; }
.qa-opt span:first-child { font-weight: 600; white-space: nowrap; }
.qa-opt .muted { font-size: .8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qa-opt[aria-selected="true"], .qa-opt:hover { background: var(--paper); }
.qa-note { padding: 7px 10px; }
@keyframes qa-pop { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: none; } }
@keyframes qa-drop { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .qa-bit, .qa-warn, .qa-sug { animation: none; } button.qa-ex, .qa-help { transition: none; } }
@media (max-width: 800px) { .qa-cols { grid-template-columns: 1fr; gap: 10px; } .qa-cols > section { padding: 0; } .qa-cols > section + section { border-left: 0; border-top: 1px dashed var(--line); padding-top: 10px; } .qa-exs { flex-direction: row; flex-wrap: wrap; } }
.check-col { width: 34px; }
.check-col input { width: 18px; height: 18px; }
.task-row.is-done .task-open { text-decoration: line-through; color: var(--muted); }
.task-row.is-sel td { background: var(--paper); }
.task-meta { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 2px; font-size: .8rem; }
/* .task-meta .badge: shared pill size (Tracker 880) */
.task-late { color: var(--red); font-weight: 650; }
.task-title { font-size: 1.15rem; font-weight: 700; margin: 8px 0 6px; width: 100%; }
textarea.task-title { display: block; min-height: 0; resize: none; overflow: hidden; line-height: 1.35; font-size: calc(1em + 2px); font-weight: 400; min-height: calc(2.7em + 20px); max-height: calc(4.05em + 20px); overflow-y: auto; /* Task Card title box (Travis Oct 22 2026): normal weight, 2px over the card text, room for 2 lines and grows to 3 (then scrolls) so the card still fits at 1280x720 */ overflow-wrap: anywhere; }
.task-panel-meta { margin: 0 0 12px; }
.task-panel-top { justify-content: space-between; align-items: center; }
.task-checklist { list-style: none; padding: 0; margin: 0 0 6px; }
.task-checklist li { display: flex; align-items: center; gap: 6px; padding: 3px 0; }
.task-checklist li button { margin-left: auto; min-height: 0; padding: 0 8px; }
/* [Tasks and Tracker] ==== Steps: the ONE shared component for any instructions or handoff (docs/sprout-root/ui-glossary.md "Steps").
   Tickable: task_steps_html (ul.task-checklist.steps). Read-only numbered: steps_html / help_text_steps / tx_render / help.js
   (ol.steps). No other step or checklist styles anywhere. .hc-steps is only an alias for Help articles already saved with it. */
ol.steps, ol.hc-steps { list-style: none; counter-reset: st; padding: 0; margin: 8px 0; display: grid; gap: 6px; }
ol.steps > li, ol.hc-steps > li { counter-increment: st; position: relative; padding: 3px 0 3px 36px; min-height: 26px; min-width: 0; overflow-wrap: anywhere; }
ol.steps > li::before, ol.hc-steps > li::before { content: counter(st); position: absolute; left: 0; top: 0; width: 26px; height: 26px; border-radius: 50%; background: var(--blue); color: #fff; font-weight: 650; font-size: .8rem; display: grid; place-items: center; }
ol.steps a, ol.hc-steps a { font-weight: 650; }
/* [Tasks and Tracker] Tickable Steps (task_steps_html): box toggles done; wording expands full text + detail (Travis Oct 18 7:42 PM) */
.steps li.task-step { flex-wrap: wrap; align-items: center; padding: 5px 0; }
.steps li.task-step + li.task-step { border-top: 1px solid var(--line); }
.steps li.task-step > .task-step-tick { flex: none; width: 44px; min-width: 44px; height: 44px; margin: 0; justify-content: center; cursor: pointer; }
.steps li.task-step > .task-step-tick > input { width: 18px; height: 18px; margin: 0; flex: none; }
.steps li.task-step > .task-step-text { flex: 1 1 0; min-width: 0; font-weight: 650; cursor: pointer; color: var(--ink); }
.steps li.task-step.is-done > .task-step-text { color: var(--muted); font-weight: 500; }
/* [Shared] An open step keeps its title on one line (Travis, Oct 18 2026: no wrap); the full wording shows in the detail line instead. */
.steps li.task-step > .task-step-link { flex: none; font-size: .85rem; white-space: nowrap; }
.steps li.task-step > .task-step-copy { flex: none; font-size: .8rem; white-space: nowrap; padding: 2px 8px; border: 1px solid var(--line); border-radius: 6px; background: var(--card); color: var(--blue); cursor: pointer; }
.steps li.task-step > .task-step-copy:hover, .steps li.task-step > .task-step-copy:focus-visible { border-color: var(--accent, var(--blue)); }
.steps .task-step-detail { display: none; flex: 0 0 calc(100% - 44px); max-width: calc(100% - 44px); margin: 0 0 0 44px; font-size: .85rem; line-height: 1.4; overflow-wrap: anywhere; white-space: pre-line; } /* numbered directions keep one per line */
.steps li.task-step.is-open > .task-step-detail { display: block; }
.steps li.task-step > button { min-height: 0; height: 26px; padding: 0 8px; }
.steps-head { display: flex; align-items: center; gap: 8px; }
.task-comments p { margin: 0 0 10px; }
.dash-tasks h2 { margin: 0; }
.dash-tasks .row { align-items: center; }
.dash-tasks > .row { margin-bottom: 14px; } /* header row to first task: same 14px as the Monthly Profit header to its chart */
/* (Task side panel column rule retired Oct 22 2026: the task opens in the Task Card) */
.dash .dash-tasks { grid-column: 1 / -1; margin: 0; }
@media (max-width: 800px) {
  /* Page title toolbar stays on the title row; the primary shows just its icon */
  .top-actions { gap: 6px; }
  .top-primary.has-ico { width: 32px; padding: 0; }
  .top-primary.has-ico .ta-ico { display: inline-flex; }
  .top-primary.has-ico .ta-label { display: none; }
  /* (Task side panel full screen retired Oct 22 2026: Task Card) */
}
.fm-ed-bar .list-size { margin: 0; }
@media (max-width: 600px) {
  .editor-bar .editor-group:last-child { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; flex: 1 1 100%; }
  .editor-bar .editor-group:last-child select { width: 100%; min-width: 0; max-width: 100%; }
}
/* [Shared] Selects inside a button row (bulk tag bar, Enroll, pickers) size to their text and sit on the row like the buttons. */
.row > select { width: auto; max-width: 100%; height: 36px; min-height: 36px; margin: 0; padding: 0 12px; border-radius: 999px; }
.row > select + button, .row > select + .btn, .row > input + button { margin-top: 0; }
.bulk-bar { margin-top: 0; }
.bulk-bar b { margin-right: 4px; }
.task-quick input { height: 36px; padding: 0 12px; margin: 0; }
/* [Tasks and Tracker] Task panel actions: one even 2×2 grid instead of 3 + a lone Delete. */
#task-panel .row:not(.task-panel-top) { display: grid; grid-template-columns: 1fr 1fr; }
@media (max-width: 800px) {
  .list-bar .list-size { flex: 1 1 calc(50% - 10px); }
  .list-bar .list-size select { width: 100%; }
  .phone-list .list-size { display: none; }
  .bulk-bar { display: grid; grid-template-columns: 1fr 1fr; }
  .bulk-bar b { grid-column: 1 / -1; }
  .bulk-bar select { width: 100%; }
}
.tag-picker > .badge:not(.tag-chip) { margin: 2px 6px 2px 0; }
.tag-chip.tag-status { border-radius: 8px; }
/* [Tasks and Tracker] Smart quick add: "Usually Ryan · Tab" hints and the gentle duplicate note (live guide line) */
button.qa-hint.quiet { flex: none; height: 24px; min-height: 0; padding: 0 9px; gap: 5px; border-radius: 999px; font: inherit; font-weight: 600; color: var(--navy); background: color-mix(in srgb, var(--navy) 6%, #fff); border: 1px dashed color-mix(in srgb, var(--navy) 35%, #fff); box-shadow: none; animation: qa-pop .16s ease-out; }
button.qa-hint.quiet:hover, button.qa-hint.quiet:focus-visible { border-style: solid; border-color: var(--navy); background: color-mix(in srgb, var(--navy) 10%, #fff); color: var(--navy); }
.qa-hint kbd { font: inherit; font-size: .7rem; padding: 0 5px; border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 5px; background: #fff; color: var(--muted); }
.qa-warn.qa-dup { color: var(--orange); }
@media (prefers-reduced-motion: reduce) { button.qa-hint.quiet { animation: none; } }
/* [Shared] Pictures that open in the viewer (files keep the pointer) */
[data-view]:not([data-type]) { cursor: zoom-in; }
/* [Shared] List bar (docs/ui-patterns.md): one shared search + filter row, upgraded by assets/listbar.js (not Dispatch). */
form.list-bar:not(.lb):not(.command .list-bar) { flex-wrap: nowrap; overflow: hidden; background: none; border: 0; border-radius: 0; padding: 0; }
form.list-bar:not(.lb):not(.command .list-bar) .list-search input { height: 38px; }
.list-bar.lb { flex-wrap: nowrap; gap: 10px; background: none; border: 0; border-radius: 0; padding: 0; margin: 0 0 14px; }
.lb .list-search { flex: 1 1 200px; min-width: 150px; position: relative; }
.lb .list-search input {
  height: 38px; padding: 0 64px 0 38px; background: var(--paper); border: 1px solid transparent; border-radius: 999px;
  transition: background .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.lb .list-search input:focus { background: #fff; border-color: var(--teal); box-shadow: 0 0 0 3px rgba(15, 159, 147, .16); outline: none; }
.lb-mag { position: absolute; z-index: 1; left: 13px; top: 50%; transform: translateY(-50%); display: inline-flex; color: var(--muted); pointer-events: none; }
.lb-mag .ico { width: 16px; height: 16px; }
.lb .list-search .lb-mag { width: 16px; height: 16px; margin: 0; padding: 0; overflow: visible; clip: auto; clip-path: none; white-space: normal; }
.lb-clear {
  position: absolute; z-index: 1; right: 8px; top: 50%; transform: translateY(-50%) scale(.8); width: 24px; height: 24px; min-height: 24px; padding: 0;
  border-radius: 50%; background: var(--line); border: 0; color: var(--ink); font-size: 1rem; line-height: 1;
  opacity: 0; pointer-events: none; transition: opacity .15s ease, transform .15s ease;
}
.lb.has-q .lb-clear { opacity: 1; pointer-events: auto; transform: translateY(-50%) scale(1); }
.lb .lb-clear:hover { background: var(--muted); color: #fff; border-color: transparent; }
.lb-kbd {
  position: absolute; z-index: 1; right: 12px; top: 50%; transform: translateY(-50%); min-width: 20px; height: 20px; padding: 0 5px; box-sizing: border-box;
  border: 1px solid var(--line); border-radius: 6px; background: #fff; color: var(--muted); font: inherit; font-size: .75rem; line-height: 18px; text-align: center;
  pointer-events: none; transition: opacity .15s ease;
}
.lb.has-q .lb-kbd, .lb .list-search:focus-within .lb-kbd { opacity: 0; }
.lb-filters { display: flex; align-items: center; gap: 6px; flex: 0 1 auto; min-width: 0; padding: 2px 0 2px 10px; border-left: 1px solid var(--line); overflow-x: auto; scrollbar-width: none; }
.lb-filters::-webkit-scrollbar { display: none; }
/* [Shared] A pill row that slides (assets/listbar.js toggles these): fade the side that has more instead of a hard cut. */
.lb-filters.more-right { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent); }
.lb-filters.more-left { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(to left, #000 calc(100% - 28px), transparent); }
.lb-filters.more-left.more-right { -webkit-mask-image: linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent); }
.lb-filters.is-empty { display: none; }
/* [Shared] A bar with no search box starts with its filters: no divider line in front of them. */
.lb-filters:first-child { padding-left: 0; border-left: 0; }
/* [Shared] Buttons (Show, Find) and older labelled inputs sit on the same 38 px line as the filter pills. */
.lb-filters > button, .lb-filters > .btn { height: 38px; min-height: 38px; margin: 0; }
.lb-filters > label:not(.list-size):not(.check):not(.month-pick) { display: inline-flex; align-items: center; gap: 6px; margin: 0; color: var(--muted); font-size: .85rem; font-weight: 650; white-space: nowrap; }
.lb-filters > label:not(.list-size):not(.check) > input { height: 38px; width: auto; margin: 0; border-radius: 999px; }
/* [Shared] A bar sitting on the page background (not in a card): white pills so they show, like the tabs above. */
:not(.card):not(.command) > .list-bar.lb .list-search input, :not(.card):not(.command) > .list-bar.lb .lb-filters select, :not(.card):not(.command) > .list-bar.lb .lb-filters input, :not(.card):not(.command) > .list-bar.lb .lb-filters .status-filter summary { background-color: #fff; border-color: var(--line); }
@media (max-width: 800px) {
  /* Filters with their own Show/Find button wrap on a phone, so the button never scrolls out of sight. */
  .lb-filters:has(> button[type="submit"]) { flex-wrap: wrap; overflow: visible; }
  .lb-filters:has(> button[type="submit"]) > * { flex: 0 1 auto; min-width: 0; max-width: 100%; }
  .lb-filters:has(> button[type="submit"]) select { max-width: 100%; }
}
.lb-filters > * { flex: none; }
.lb-filters select, .lb-filters .status-filter summary, .lb-filters input[type="month"], .lb-filters input[type="date"] {
  width: auto; height: 34px; min-height: 34px; margin: 0; padding: 0 28px 0 12px; border-radius: 999px; background-color: var(--paper);
  border: 1px solid transparent; font-weight: 650; transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.lb-filters .status-filter summary { padding: 0 16px; box-sizing: border-box; overflow: hidden; text-overflow: ellipsis; justify-content: center; gap: 6px; }
.lb-filters input[type="month"], .lb-filters input[type="date"] { padding: 0 12px; }
.lb-filters select:hover, .lb-filters .status-filter summary:hover { border-color: var(--line); }
.lb-filters select.is-active, .lb-filters .status-filter.is-active > summary { background-color: rgba(15, 159, 147, .1); border-color: var(--teal); color: var(--teal); }
.lb-filters .status-filter summary[data-n]::after {
  content: attr(data-n); display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box;
  border-radius: 999px; background: var(--teal); color: #fff; font-size: .7rem; font-weight: 750;
}
.lb .lb-reset {
  height: 34px; min-height: 34px; padding: 0 16px; border-radius: 999px; background: none; border: 1px solid transparent;
  color: var(--teal); font-weight: 650; text-decoration: none; transition: background-color .15s ease, color .15s ease;
}
.lb .lb-reset:hover { background: var(--paper); color: var(--ink); border-color: transparent; text-decoration: none; }
.lb-reset[hidden] { display: none; }
.lb-tail { display: flex; align-items: center; gap: 8px; flex: none; margin-left: auto; color: var(--muted); }
.lb-tail .list-size select {
  width: auto; height: 34px; min-height: 34px; margin: 0; padding: 0 26px 0 10px; background-color: transparent; border: 1px solid transparent;
  border-radius: 999px; color: var(--muted); font-weight: 600;
}
.lb-tail .list-size select:hover, .lb-tail .list-size select:focus { border-color: var(--line); background-color: #fff; outline: none; }
.lb .list-count { margin: 0; }
/* [Messages and Emails] Narrow places (phone, the Emails/Messages list pane): search on its own row, then one scrollable pill row. */
@media (max-width: 800px) {
  .list-bar.lb, form.list-bar:not(.lb):not(.command .list-bar) { flex-wrap: wrap; }
  form.list-bar:not(.lb) .list-search { flex-basis: 100%; }
  .lb .list-search { flex-basis: 100%; }
  .lb-filters { padding-left: 0; border-left: 0; min-width: 0; flex: 1 1 100%; overflow-x: auto; scrollbar-width: none; }
  .lb-tail { flex: 1 1 100%; justify-content: flex-end; font-size: .85rem; }
  .lb-filters::-webkit-scrollbar { display: none; }
  .lb-kbd { display: none; }
  .lb .list-search input { padding-right: 40px; }
}

/* [Shared] Month picker (assets/listbar.js, docs/ui-patterns.md "List bar") */
.month-pick { display: inline-flex; align-items: center; gap: 2px; flex: none; }
.month-pick .mp-pill {
  height: 34px; min-height: 34px; margin: 0; padding: 0 16px; border-radius: 999px; border: 1px solid var(--line);
  background: #fff; color: var(--ink); font: inherit; font-weight: 650; white-space: nowrap; min-width: 136px;
}
.month-pick .mp-pill:hover, .month-pick.is-open .mp-pill { border-color: var(--teal); color: var(--teal); background: #fff; }
.month-pick .mp-step, .mp-pop .mp-yr {
  width: 30px; height: 30px; min-height: 30px; margin: 0; padding: 0; display: inline-grid; place-items: center;
  border-radius: 999px; border: 0; background: none; color: var(--muted);
}
.month-pick .mp-step:hover, .mp-pop .mp-yr:hover { background: var(--paper); color: var(--ink); }
.month-pick .mp-step .ico, .mp-pop .mp-yr .ico { width: 16px; height: 16px; }
.mp-pop {
  position: fixed; z-index: 60; width: 248px; padding: 10px; box-sizing: border-box; background: #fff;
  border: 1px solid var(--line); border-radius: 14px; box-shadow: 0 8px 24px rgba(16, 24, 40, .12);
}
.mp-pop[hidden] { display: none; }
.mp-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.mp-head .mp-year { font-weight: 750; color: var(--ink); }
.mp-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.mp-pop .mp-m {
  height: 36px; min-height: 36px; margin: 0; padding: 0; border-radius: 999px; border: 1px solid transparent;
  background: none; color: var(--ink); font: inherit; font-weight: 600;
}
.mp-pop .mp-m:hover { background: var(--paper); }
.mp-pop .mp-m.is-now { border-color: var(--teal); color: var(--teal); }
.mp-pop .mp-m.is-picked, .mp-pop .mp-m.is-picked:hover { background: var(--teal); border-color: var(--teal); color: #fff; }
.mp-foot { display: flex; justify-content: center; margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--line); }
.mp-pop .mp-now { height: 30px; min-height: 30px; margin: 0; padding: 0 14px; border-radius: 999px; border: 0; background: none; color: var(--teal); font: inherit; font-weight: 650; }
.mp-pop .mp-now:hover { background: var(--paper); }

.lb .list-search input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
.lb-filters .list-size { flex: none; width: auto; min-width: 0; }
.lb-filters select { min-width: 0; max-width: 200px; flex: none; }
/* [Shared] A bar that is a small form (picks + its own Find/Show button): selects show their whole choice, and the button
   matches the 34 px pills beside it (a button alone after the search box keeps the search box's 38 px). */
.lb-filters:has(> button[type="submit"]) select { max-width: 100%; }
.lb-filters > :is(.list-size, label, select, input) ~ button, .lb-filters > :is(.list-size, label, select, input) ~ .btn { height: 34px; min-height: 34px; }
.card.mail-bar { padding-top: 14px; padding-bottom: 14px; }
.mail-bar .list-bar { margin-bottom: 0; }
.login .login-keep { display: flex; align-items: center; gap: 8px; margin: 12px 0 4px; font-weight: 600; }
.login .login-note { margin: 0 0 8px; }
.login .login-note a:hover { color: var(--ink); }
/* [Logins and Security] See Demo on every sign-in screen: a full-width quiet button like Use Face ID under a centered "Just looking?" divider. */
.login .login-demo { display: flex; flex-direction: column; align-items: stretch; gap: 10px; margin: 18px 0 2px; }
.login .login-or { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: .78rem; font-weight: 600; line-height: 1.2; }
.login .login-or::before, .login .login-or::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.login .login-demo .btn { width: 100%; }
/* [Shared] iPhone app / home-screen install (viewport-fit=cover): an opaque strip exactly the height of the status bar, above the
   page, so content scrolled up (or pushed up by the keyboard) never shows under the clock or notch. In a normal browser
   the inset is 0, so it is invisible. Same color as the page's own top bar; overlays above z-index 50 pad themselves. */
body::before { content: ""; position: fixed; top: 0; left: 0; right: 0; z-index: 50; height: env(safe-area-inset-top, 0px); background: var(--sb-bg, var(--paper)); pointer-events: none; }
/* One top color (Travis Oct 21 2026 12:20 PM, every page): the iPhone status bar / safe area is painted with the SAME
   --top-bg as the shared Top Bar, so there is never a black or white band. Pages only change --top-bg. Rules check
   'Top fill rule'. */
body { --top-bg: var(--page-bg, var(--paper)); --sb-bg: var(--top-bg); } /* Travis 12:22 PM: the color just below the Top Bar line = the Top Bar = the status bar, one continuous color */
body.portal, body:has(> .portal-top) { --sb-bg: var(--ink); }
@media (max-width: 800px) {
  table.roster td:first-child, table.roster th:first-child, table.roster td:last-child, table.roster th:last-child { border-left: 0; border-right: 0; }
}
.mail-item .mail-date-top { display: block; margin: 0 0 1px; line-height: 1.2; }
.mail-item .mail-who > .mail-date-top + .mail-cut { font-size: inherit; margin-top: 0; }
/* [Logins and Security] Login / privacy backdrop: animated turf scene with a stand-on spray rig (includes/turf_scene.php). */
.login { position: relative; overflow: hidden; isolation: isolate; }
.login > :not(.turf-scene) { position: relative; z-index: 1; }
.login .card { box-shadow: 0 18px 50px rgba(17, 17, 17, .45); }
.login > .hint { background: rgba(17, 17, 17, .72); color: var(--line); padding: 6px 12px; border-radius: 999px; text-align: center; }
.login > .hint a { color: #fff; }
.turf-scene { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.turf-scene .ts-sky { position: absolute; inset: 0; width: 100%; height: 100%; }
.ts-cloud { fill: var(--paper); fill-opacity: .12; animation: ts-cloud 70s linear infinite; }
.ts-cloud.c2 { animation-duration: 95s; animation-delay: -40s; }
.ts-cloud.c3 { animation-duration: 120s; animation-delay: -80s; }
@keyframes ts-cloud { from { transform: translateX(-30%); } to { transform: translateX(110%); } }
.ts-grass .blade { fill: none; stroke: var(--grass); stroke-opacity: .55; stroke-width: 3; stroke-linecap: round; transform-box: fill-box; transform-origin: 50% 100%; animation: ts-sway 4s ease-in-out infinite alternate; }
.ts-grass .b1 { animation-delay: -1s; } .ts-grass .b2 { animation-delay: -2s; } .ts-grass .b3 { animation-delay: -3s; }
@keyframes ts-sway { from { transform: rotate(-5deg); } to { transform: rotate(6deg); } }
.ts-trail { position: absolute; right: 30%; bottom: 0; height: clamp(14px, 2.2vw, 30px); width: 130vw; background: linear-gradient(90deg, rgba(30, 144, 255, 0), rgba(30, 144, 255, .08) 40%, rgba(30, 144, 255, .3)); border-radius: 0 999px 999px 0; pointer-events: none; animation: ts-trail 16s linear infinite; }
@keyframes ts-trail { 0%, 86% { opacity: 1; } 100% { opacity: 0; } }
.ts-drive { position: absolute; left: 0; bottom: max(4vh, 18px); width: clamp(220px, 26vw, 400px); aspect-ratio: 400 / 260; animation: ts-drive 16s linear infinite; }
.ts-drive .ts-rig { position: absolute; inset: 0; width: 100%; height: 100%; animation: ts-bob .5s ease-in-out infinite alternate; }
.ts-drive .ts-mist { position: absolute; left: 0; bottom: 0; width: 650%; height: calc(100% * 320 / 260); pointer-events: none; }
@keyframes ts-drive { from { transform: translateX(-110%); } to { transform: translateX(100vw); } }
@keyframes ts-bob { from { transform: translateY(0); } to { transform: translateY(-1.5px); } }
.ts-wheel { animation: ts-spin 1.1s linear infinite; }
.ts-spinner-vanes { stroke-dasharray: 4 5; animation: ts-spinner .35s linear infinite; }
@keyframes ts-spinner { to { stroke-dashoffset: -18; } }
@keyframes ts-spin { to { transform: rotate(360deg); } }
@media (max-width: 700px) { .ts-drive { width: 190px; bottom: 10px; } .ts-trail { height: 12px; } }
@media (prefers-reduced-motion: reduce) {
  .ts-cloud, .ts-grass .blade, .ts-wheel, .ts-spinner-vanes, .ts-drive .ts-rig { animation: none; }
  .ts-drive { animation: none; transform: translateX(8vw); }
  .ts-trail { animation: none; }
  .ts-mist { display: none; }
}
/* [Logins and Security] Login footer: never wraps mid-item. One line when it fits, otherwise one item per line. */
.login > .login-foot { display: flex; flex-wrap: nowrap; justify-content: center; align-items: center; white-space: nowrap; max-width: calc(100vw - 32px); }
.login-foot > span { white-space: nowrap; }
.login-foot .sep { padding: 0 .4em; }
@media (max-width: 760px) {
  .login > .login-foot { flex-direction: column; gap: 2px; padding: 10px 18px; border-radius: 14px; line-height: 1.5; }
  .login-foot .sep { display: none; }
}
/* [Route] Login: Sign in full width, Forgot password centered under it; Keep me signed in aligned to the field edge. */
.login .login-keep { margin: 14px 0 12px; line-height: 1.3; }
.login .login-keep input { margin: 0; flex: none; width: 16px; height: 16px; }
.login .login-actions { display: flex; flex-direction: column; align-items: stretch; gap: 10px; }
.login .login-actions button { width: 100%; }
.login .login-actions a { align-self: center; text-align: center; }

/* [Logins and Security] v334 golden-hour scene: sun glow, parallax layers, sky birds, perching bird on the login card */
.ts-sun { animation: ts-glow 9s ease-in-out infinite alternate; transform-box: fill-box; transform-origin: center; }
@keyframes ts-glow { from { opacity: .85; transform: scale(.97); } to { opacity: 1; transform: scale(1.03); } }
.ts-bird { fill: none; stroke: var(--ink); stroke-opacity: .7; stroke-width: 2.2; stroke-linecap: round; animation: ts-birdfly 38s linear infinite; }
.ts-bird.g2 { animation-duration: 46s; animation-delay: -20s; }
@keyframes ts-birdfly { 0% { transform: translate(-60px, 300px) scaleY(1); } 25% { transform: translate(400px, 270px) scaleY(.4); } 50% { transform: translate(800px, 250px) scaleY(1); } 75% { transform: translate(1200px, 280px) scaleY(.5); } 100% { transform: translate(1700px, 240px) scaleY(1); } }
.ts-perch { position: absolute; bottom: calc(100% - 3px); right: 28px; width: 50px; height: 38px; pointer-events: none; opacity: 0; z-index: 2; }
.ts-perch.is-on { opacity: 1; }
.ts-perch svg { width: 100%; height: 100%; display: block; overflow: visible; }
.ts-perch .pb-wing { transform-box: fill-box; transform-origin: 30% 100%; }
.ts-perch.is-flying .pb-wing { animation: pb-flap .16s ease-in-out infinite alternate; }
@keyframes pb-flap { from { transform: scaleY(1); } to { transform: scaleY(-1.4); } }
.ts-perch .pb-head { transform-box: fill-box; transform-origin: 30% 80%; }
.ts-perch.do-look .pb-head { animation: pb-look 1.2s ease-in-out; }
@keyframes pb-look { 30% { transform: rotate(-14deg); } 65% { transform: rotate(10deg) translateX(-1px); } }
.ts-perch.do-hop svg { animation: pb-hop .5s ease-out 2; }
.ts-perch.face-left > svg { scale: -1 1; }
.ts-perch.face-left .pb-chirp { left: -6px; }
.ts-pelican { position: fixed; left: 0; top: 10vh; width: clamp(70px, 7vw, 110px); pointer-events: none; z-index: 0; opacity: 0; }
.ts-pelican svg { display: block; width: 100%; }
.ts-pelican.face-left svg { scale: -1 1; }
@keyframes pp-flap { 0%, 60%, 100% { transform: scaleY(1); } 75% { transform: scaleY(.45); } 88% { transform: scaleY(1.1); } }
@keyframes pb-hop { 40% { transform: translateY(-7px); } }
.pb-chirp { position: absolute; left: 34px; top: -14px; color: var(--orange); font-size: 14px; font-weight: 700; opacity: 0; }
.ts-perch.do-chirp .pb-chirp { animation: pb-chirp .9s ease-out; }
.ts-perch.do-chirp .pb-head { animation: pb-look .5s ease-in-out; }
@keyframes pb-chirp { 0% { opacity: 0; transform: translate(0, 4px); } 30% { opacity: 1; } 100% { opacity: 0; transform: translate(8px, -10px); } }
@media (max-width: 700px) { .ts-perch { right: 18px; width: 32px; height: 24px; } }
@media (prefers-reduced-motion: reduce) { .ts-sun, .ts-layer, .ts-bird { animation: none; } .ts-bird { display: none; } .ts-perch, .ts-pelican { display: none; } }
/* [Logins and Security] v336 lawn story: dull patchy turf ahead of the spray greens up behind it; weeds wilt after treatment */
.ts-ahead { position: absolute; left: 72%; bottom: calc(-1 * max(4vh, 18px)); width: 110vw; height: max(29vh, 16.3vw); pointer-events: none;
  background: radial-gradient(ellipse 9vw 3vh at 30% 70%, rgba(106, 110, 116, .22), transparent 70%), radial-gradient(ellipse 12vw 4vh at 65% 40%, rgba(240, 138, 36, .16), transparent 70%), radial-gradient(ellipse 8vw 3vh at 85% 80%, rgba(106, 110, 116, .2), transparent 70%), linear-gradient(90deg, transparent, rgba(240, 138, 36, .26) 22vw), linear-gradient(90deg, transparent, rgba(106, 110, 116, .26) 22vw);
  -webkit-mask-image: linear-gradient(transparent, #000 18%); mask-image: linear-gradient(transparent, #000 18%); animation: ts-regrow 16s linear infinite; }
/* [Logins and Security] after a loop the whole lawn is healthy; patchy turf fades back in ahead of the returning rig (no pop) */
@keyframes ts-regrow { 0% { opacity: 0; } 22% { opacity: 1; } 100% { opacity: 1; } }
.ts-weeds { position: absolute; inset: 0; pointer-events: none; }
.ts-weed { position: absolute; width: clamp(18px, 2vw, 30px); height: clamp(18px, 2vw, 30px); transform-origin: 50% 100%; transition: transform 2.4s ease-out var(--d, 0s), opacity 2.4s ease-out var(--d, 0s), filter 2.4s var(--d, 0s); }
.ts-weed.is-wilted { transform: scale(.35) rotate(18deg); opacity: 0; filter: grayscale(1); transition: transform 1.8s ease-in .4s, opacity 1.8s ease-in .4s, filter 1.8s .4s; }
@media (max-width: 700px) { .ts-ahead { bottom: -10px; } }
@media (prefers-reduced-motion: reduce) { .ts-ahead, .ts-weeds { display: none; animation: none; } }
/* [Logins and Security] public home page on the turf scene: card stays readable, footer matches login */
.login.welcome { gap: 14px; align-content: center; }
.login.welcome .card { width: min(560px, 100%); background: rgba(255, 255, 255, .97); }
/* [Logins and Security] v339 wow layer: time of day, weather, parallax, extras, easter eggs */
.ts-night { opacity: 0; transition: opacity 2s; pointer-events: none; }
.ts-stars { opacity: 0; transition: opacity 2s; }
.ts-moon { opacity: .35; }
.ts-stars .st { animation: ts-twinkle 3s ease-in-out infinite alternate; } .ts-stars .s1 { animation-delay: -1s; } .ts-stars .s2 { animation-delay: -2s; }
@keyframes ts-twinkle { from { opacity: .35; } to { opacity: 1; } }
#tsSky stop { transition: stop-color 2s, stop-opacity 2s; }
.ts-sunhit, .turf-scene .ts-moon, .turf-scene .ts-rig { pointer-events: auto; cursor: pointer; }
.ts-sunpos { transition: transform 2.4s cubic-bezier(.4, 0, .2, 1), opacity 2s; }
.tod-dawn .ts-sunpos { transform: translate(-900px, 30px); }
.tod-day .ts-sunpos { transform: translate(160px, -380px); }
.tod-dusk .ts-sunpos { transform: translate(120px, 110px); }
.tod-night .ts-sunpos { transform: translate(200px, 260px); opacity: 0; pointer-events: none; }
.tod-day #tsHaze stop { stop-opacity: .06; }
.ts-todtag { position: fixed; left: 50%; top: 14px; z-index: 2; translate: -50% 0; pointer-events: none; font: 700 13px/1 "Segoe UI", system-ui, sans-serif; color: var(--paper); background: rgba(17, 17, 17, .6); padding: 6px 12px; border-radius: 999px; opacity: 0; }
.ts-todtag.is-on { animation: ts-todtag 2.2s ease-out; }
@keyframes ts-todtag { 0% { opacity: 0; } 15%, 75% { opacity: 1; } 100% { opacity: 0; } }
.tod-dawn #tsSky stop:nth-child(1) { stop-color: var(--navy); } .tod-dawn #tsSky stop:nth-child(3) { stop-color: var(--blue); stop-opacity: .6; } .tod-dawn #tsSky stop:nth-child(4) { stop-color: var(--red); stop-opacity: .45; }
.tod-day #tsSky stop:nth-child(1) { stop-color: var(--navy); } .tod-day #tsSky stop:nth-child(2) { stop-color: var(--blue); } .tod-day #tsSky stop:nth-child(3) { stop-color: var(--blue); stop-opacity: .8; } .tod-day #tsSky stop:nth-child(4) { stop-color: var(--line); stop-opacity: .85; }
.tod-dusk #tsSky stop:nth-child(2) { stop-color: var(--ink); } .tod-dusk #tsSky stop:nth-child(3) { stop-color: var(--navy); stop-opacity: 1; } .tod-dusk #tsSky stop:nth-child(4) { stop-color: var(--red); stop-opacity: .45; }
.tod-night #tsSky stop:nth-child(2) { stop-color: var(--ink); } .tod-night #tsSky stop:nth-child(3) { stop-color: var(--navy); stop-opacity: .8; } .tod-night #tsSky stop:nth-child(4) { stop-color: var(--navy); stop-opacity: .9; }
.tod-dawn .ts-night { opacity: .12; } .tod-dusk .ts-night { opacity: .3; } .tod-night .ts-night { opacity: .5; }
.tod-dusk .ts-stars { opacity: .5; } .tod-night .ts-stars, .tod-night .ts-moon { opacity: 1; } .tod-dusk .ts-moon { opacity: .6; }
.tod-day .ts-cloud { fill-opacity: .3; }
.wx-cloudy .ts-cloud { fill-opacity: .35; } .wx-cloudy .ts-sun { opacity: .45 !important; }
.ts-rain { position: absolute; inset: 0; opacity: 0; pointer-events: none; background: repeating-linear-gradient(105deg, transparent 0 14px, rgba(217, 219, 222, .22) 14px 15px, transparent 15px 31px); background-size: 120px 120px; animation: ts-rain .5s linear infinite; }
.wx-rain .ts-rain { opacity: 1; }
@keyframes ts-rain { to { background-position: -32px 120px; } }
.ts-moon { transition: opacity 2s; }
/* [Shared] fireflies at dusk/night */
.ts-fireflies { position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity 2s; }
.tod-night .ts-fireflies, .tod-dusk .ts-fireflies { opacity: 1; }
.ts-fireflies i { position: absolute; width: 4px; height: 4px; border-radius: 50%; background: var(--orange); box-shadow: 0 0 8px 3px rgba(240, 138, 36, .55); animation: ts-ff-drift 9s ease-in-out infinite alternate, ts-ff-blink 2.6s ease-in-out infinite; }
@keyframes ts-ff-drift { 0% { transform: translate(0, 0); } 50% { transform: translate(24px, -18px); } 100% { transform: translate(-16px, -6px); } }
@keyframes ts-ff-blink { 0%, 60%, 100% { opacity: .1; } 75% { opacity: 1; } }
/* [Logins and Security] butterflies and bees appear over freshly treated turf (daytime) */
.ts-bugs { position: absolute; inset: 0; pointer-events: none; }
.ts-bug { position: absolute; width: clamp(14px, 1.4vw, 20px); opacity: 0; transition: opacity 1.5s; animation: ts-bug-path 7s ease-in-out infinite; }
.ts-bug svg { display: block; width: 100%; }
.ts-bug.is-out { opacity: 1; }
.tod-night .ts-bug, .wx-rain .ts-bug { opacity: 0; }
.ts-bug .w { transform-box: fill-box; transform-origin: 50% 60%; animation: ts-flutter .18s ease-in-out infinite alternate; }
@keyframes ts-flutter { to { transform: scaleY(.3); } }
@keyframes ts-bug-path { 0% { transform: translate(0, 0); } 25% { transform: translate(30px, -16px); } 50% { transform: translate(54px, 4px); } 75% { transform: translate(20px, -24px); } 100% { transform: translate(0, 0); } }
/* [Shared] fall leaves (Sep-Nov) */
.ts-leaves { position: absolute; inset: 0; pointer-events: none; display: none; }
.season-fall .ts-leaves { display: block; }
.ts-leaves i { position: absolute; top: -20px; width: 10px; height: 7px; border-radius: 0 70% 0 70%; background: var(--orange); opacity: .85; animation-name: ts-leaf-fall, ts-leaf-sway; animation-timing-function: linear, ease-in-out; animation-iteration-count: infinite; animation-direction: normal, alternate; }
.ts-leaves i.l1 { background: var(--red); } .ts-leaves i.l2 { background: var(--muted); }
@keyframes ts-leaf-fall { from { top: -20px; } to { top: 102vh; } }
@keyframes ts-leaf-sway { from { transform: translateX(-22px) rotate(-40deg); } to { transform: translateX(22px) rotate(50deg); } }
/* [Logins and Security] sprayer easter egg */
.ts-drive .ts-rig { transform-origin: 29.5% 83%; transition: rotate .35s cubic-bezier(.3, 1.6, .5, 1); }
.ts-drive .ts-rig.is-wheelie { rotate: -9deg; }
/* [Settings] Zero-turn mower backdrop (Settings > Style), Travis: four passes, one lane each, every lane just above the last
   (left to right light, right to left dark, twice), then back to lane 1, forever. Off screen it turns into the next lane.
   Stripe widths and the rolling fade are set by includes/turf_scene.php from the mower's real position, so each stripe
   ends exactly at the rear edge of the deck. --ts-w machine width, --ts-sh one lane (deck) height, --ts-b ground line. */
.ts-is-mower { --ts-w: clamp(220px, 26vw, 400px); --ts-sh: calc(var(--ts-w) * .085); --ts-b: max(4vh, 18px); }
.ts-is-mower .ts-trail, .ts-is-mower .ts-ahead { display: none; }
.ts-is-mower .ts-drive { animation: ts-ztr 64s linear infinite; }
.ts-drive .ts-rig.ts-mower { transform-origin: 28% 80%; }
.ts-stripe { position: absolute; bottom: calc(var(--ts-b) + var(--ts-w) * .03); height: var(--ts-sh); width: 0; pointer-events: none; transition: opacity 3s ease; }
.ts-stripe.l1 { bottom: calc(var(--ts-b) + var(--ts-w) * .03 + var(--ts-sh)); }
.ts-stripe.l2 { bottom: calc(var(--ts-b) + var(--ts-w) * .03 + 2 * var(--ts-sh)); }
.ts-stripe.l3 { bottom: calc(var(--ts-b) + var(--ts-w) * .03 + 3 * var(--ts-sh)); }
.ts-stripe.lr { left: 0; background: linear-gradient(rgba(200, 245, 66, .34), rgba(166, 226, 46, .28)); }
.ts-stripe.rl { right: 0; background: linear-gradient(rgba(17, 17, 17, .28), rgba(40, 90, 16, .38)); }
.ts-stripe.is-fading { opacity: 0; }
.ts-stripe.no-fade { transition: none; }
@keyframes ts-ztr {
  0% { transform: translate(-110%, 0) scaleX(1); }
  23% { transform: translate(100vw, 0) scaleX(1); }
  25% { transform: translate(100vw, calc(-1 * var(--ts-sh))) scaleX(-1); }
  48% { transform: translate(-110%, calc(-1 * var(--ts-sh))) scaleX(-1); }
  50% { transform: translate(-110%, calc(-2 * var(--ts-sh))) scaleX(1); }
  73% { transform: translate(100vw, calc(-2 * var(--ts-sh))) scaleX(1); }
  75% { transform: translate(100vw, calc(-3 * var(--ts-sh))) scaleX(-1); }
  98% { transform: translate(-110%, calc(-3 * var(--ts-sh))) scaleX(-1); }
  100% { transform: translate(-110%, 0) scaleX(1); }
}
/* [Logins and Security] the company badge on the body is never mirrored: flipped back while the mower drives right to left */
.ts-badge { transform-box: fill-box; transform-origin: center; }
.ts-back .ts-mower .ts-badge { transform: scaleX(-1); }
@media (max-width: 700px) { .ts-is-mower { --ts-w: 190px; --ts-b: 34px; --ts-sh: 19px; } .ts-is-mower .ts-drive { bottom: 34px; } /* above the phone grass fringe */
  .ts-stripe.lr { background: linear-gradient(rgba(214, 250, 90, .50), rgba(166, 226, 46, .42)); box-shadow: inset 0 -1px rgba(242, 243, 245, .25); }
  .ts-stripe.rl { background: linear-gradient(rgba(17, 17, 17, .38), rgba(30, 80, 12, .50)); } }
@media (prefers-reduced-motion: reduce) { .ts-is-mower .ts-drive { animation: none; transform: translateX(8vw); } .ts-stripe.l0, .ts-stripe.l1 { width: 100vw; } }
.ts-is-plain .ts-drive, .ts-is-plain .ts-weeds { display: none; }
.ts-honk { position: fixed; z-index: 2; pointer-events: none; font: 800 14px/1 "Segoe UI", system-ui, sans-serif; color: var(--ink); background: var(--paper); padding: 4px 8px; border-radius: 10px; opacity: 0; translate: -50% -100%; }
.ts-honk.is-on { animation: ts-honk 1.1s ease-out; }
@keyframes ts-honk { 0% { opacity: 0; transform: scale(.6); } 15% { opacity: 1; transform: scale(1.12); } 70% { opacity: 1; transform: scale(1); } 100% { opacity: 0; transform: translateY(-12px); } }
@media (max-width: 700px) { .ts-fireflies i:nth-child(n+8), .ts-leaves i:nth-child(n+6) { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .ts-fireflies, .ts-bugs, .ts-leaves, .ts-rain { display: none; }
  .ts-honk.is-on { animation: none; opacity: 1; }
}
/* [Route] v340: birds notice typing (turn toward the field, head tilt, hop); small birds on the Forgot password line; pelican; critters */
.ts-perch .pb-front { opacity: 0; transform-box: fill-box; transform-origin: 50% 90%; }
.ts-perch.do-notice svg { animation: pb-hop .45s ease-out 1; }
.ts-perch.do-notice .pb-head { opacity: 0; }
.ts-perch.do-notice .pb-front { opacity: 1; animation: pb-curious 1.8s ease-in-out; }
.ts-perch .pb-eyes { transform-box: fill-box; transform-origin: 50% 50%; }
.ts-perch.do-notice .pb-eyes { animation: pb-blink 1.8s linear; }
/* [Logins and Security] front head is symmetric, so it reads as looking straight at the viewer whichever way the body faces */
@keyframes pb-curious { 0% { transform: rotate(0); } 25% { transform: rotate(-16deg); } 60% { transform: rotate(-12deg); } 80% { transform: rotate(10deg); } 100% { transform: rotate(0); } }
@keyframes pb-blink { 0%, 34%, 42%, 74%, 82%, 100% { transform: scaleY(1); } 38%, 78% { transform: scaleY(.1); } }
@keyframes pb-notice { 0% { transform: rotate(0); } 25% { transform: rotate(26deg) translateY(1px); } 70% { transform: rotate(22deg) translateY(1px); } 100% { transform: rotate(0); } }
.login .login-actions { position: relative; }
.ts-perch.on-line { z-index: 2; }
.ts-perch.on-line .pb-chirp { font-size: 11px; top: -10px; }
.ts-pelican { width: clamp(150px, 15vw, 240px); }
/* [Shared] one group per wing (feathers + black primaries), hinged at the shoulder in SVG coords so the tips never detach */
.ts-pelican .pp-wing { transform-box: view-box; transform-origin: 98px 50px; animation: pp-beat 6.5s ease-in-out infinite; }
@keyframes pp-beat { 0%, 100% { transform: scaleY(1); } 7% { transform: scaleY(-.55); } 14% { transform: scaleY(1); } 21% { transform: scaleY(-.55); } 28% { transform: scaleY(1); } 35% { transform: scaleY(-.5); } 42%, 99% { transform: scaleY(.92); } }
/* [Logins and Security] always-visible time-of-day toggle (top-right corner, clear of the card) */
.ts-todbtn { position: fixed; top: calc(10px + env(safe-area-inset-top, 0px)); right: 10px; z-index: 3; display: inline-flex; align-items: center; justify-content: center; gap: 0; height: 32px; min-width: 32px; padding: 0 7px; line-height: 1; margin: 0; border: 1px solid rgba(242, 243, 245, .25); border-radius: 999px; background: rgba(17, 17, 17, .45); color: var(--paper); font: 600 12px/1 "Segoe UI", system-ui, sans-serif; cursor: pointer; opacity: .7; transition: opacity .2s, background .2s; width: auto; }
.ts-todbtn svg { width: 16px; height: 16px; flex: none; }
.ts-todbtn span { max-width: 0; margin-left: 0; overflow: hidden; white-space: nowrap; transition: max-width .3s ease, margin-left .3s ease; }
.ts-todbtn:hover, .ts-todbtn:focus-visible { opacity: 1; background: rgba(17, 17, 17, .7); }
.ts-todbtn:hover span, .ts-todbtn:focus-visible span { max-width: 140px; margin-left: 6px; }
.ts-todbtn:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.ts-critter { position: absolute; left: 0; top: 0; pointer-events: none; opacity: 0; transition: opacity .6s; }
.ts-critter svg { display: block; width: 100%; height: auto; }
.ts-critter.face-left svg { scale: -1 1; }
.ts-squirrel { width: 34px; }
.ts-squirrel .sq-tail { transform-box: fill-box; transform-origin: 90% 90%; animation: sq-run .22s ease-in-out infinite alternate; }
.ts-squirrel.is-sitting .sq-tail { animation: sq-flick .7s ease-in-out infinite alternate; }
@keyframes sq-run { to { transform: rotate(-8deg); } }
@keyframes sq-flick { 0%, 60% { transform: rotate(0); } 100% { transform: rotate(18deg); } }
.ts-rabbit { top: auto; bottom: 2vh; width: 46px; height: 44px; opacity: 1; overflow: hidden; pointer-events: auto; cursor: pointer; }
.ts-rabbit .rb-pop { position: absolute; left: 7px; bottom: -36px; width: 30px; transition: bottom .5s cubic-bezier(.3, 1.4, .6, 1); }
.ts-rabbit.is-up .rb-pop { bottom: 0; }
.ts-rabbit:not(.is-up) { pointer-events: none; }
.ts-rabbit.is-up .rb-ear.r { transform-box: fill-box; transform-origin: 50% 100%; animation: rb-twitch 1.4s ease-in-out infinite; }
@keyframes rb-twitch { 0%, 70%, 100% { transform: rotate(0); } 80% { transform: rotate(14deg); } }
.ts-dragonfly { width: 30px; }
.ts-dragonfly .df-w { animation: df-buzz .05s linear infinite alternate; }
@keyframes df-buzz { to { opacity: .4; } }
.ts-frog { width: 20px; }
.tod-night .ts-dragonfly { display: none; }
@media (max-width: 700px) { .ts-rabbit { width: 38px; } .ts-dragonfly { width: 24px; } }
@media (prefers-reduced-motion: reduce) { .ts-critter, .ts-todbtn span { display: none; transition: none; } }
/* [Shared] bird-click easter egg: dodge + snickering Catahoula in a Twisted Turf cap */
.ts-perch.is-dodge svg { animation: pb-dodge .5s ease-out; }
@keyframes pb-dodge { 30% { transform: translateY(-10px) rotate(-25deg); } 100% { transform: none; } }
.ts-pelican.is-dodge svg { animation: pb-dodge .6s ease-out; }
.ts-dog { position: absolute; bottom: 0; left: 6vw; width: 150px; height: 150px; pointer-events: none; }
.ts-dog .dg-pop { position: absolute; left: 20px; bottom: -130px; width: 110px; transition: bottom .45s cubic-bezier(.3, 1.5, .6, 1); }
.ts-dog.is-up .dg-pop { bottom: 4px; }
.ts-dog .dg-pop svg { display: block; width: 100%; }
.ts-dog.is-laughing .dg-pop svg { animation: dg-shake .16s ease-in-out infinite alternate; }
@keyframes dg-shake { from { transform: translateY(0) rotate(-3deg); } to { transform: translateY(-3px) rotate(3deg); } }
.ts-dog.is-laughing .dg-mouth { transform-box: fill-box; transform-origin: 50% 0; animation: dg-laugh .16s ease-in-out infinite alternate; }
@keyframes dg-laugh { to { transform: scaleY(.55); } }
/* [Logins and Security] laugh text sits right beside the head: vertically centred on it, ~10px gap; side set by JS (.heh-left) */
.ts-dog .dg-heh { position: absolute; left: 128px; top: 95px; translate: var(--hx, 0px) -50%; width: max-content; white-space: nowrap; text-align: left; font: 800 11px/1.05 "Segoe UI", system-ui, sans-serif; color: var(--ink); background: var(--paper); padding: 3px 6px; border-radius: 8px; opacity: 0; transition: opacity .2s; }
.ts-dog.is-laughing .dg-heh { opacity: 1; }
.ts-dog.heh-left .dg-heh { left: auto; right: 128px; text-align: right; }
@media (prefers-reduced-motion: reduce) { .ts-dog { display: none; } }
.ts-grass .blade.still { animation: none; }
.ts-grass .blade:nth-child(2n) { stroke-opacity: .4; stroke-width: 2.4; }
.ts-grass-back path { fill: none; stroke: var(--grass); stroke-opacity: .35; stroke-width: 3.2; stroke-linecap: round; }
.ts-grass-back path:nth-child(3n) { stroke: var(--ink); stroke-opacity: .35; }
.turf-scene .ts-fringe { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.ts-pelican .pp-head { transform-box: view-box; transform-origin: 138px 28px; transform: rotate(var(--pa, 0deg)); transition: transform .45s ease; }
.ts-pelican.is-perched .pp-wing { animation: none; transform: scaleY(.22); }
.ts-pelican .pp-wing.far { transform-origin: 100px 46px; }
.ts-pelican .pp-eye { transform-box: fill-box; transform-origin: 50% 50%; transition: transform .08s; }
.ts-pelican.do-blink .pp-eye { transform: scaleY(.1); }

/* [Shared] v350 surprises: shooting star, hummingbird, critter click reactions */
.ts-shoot { position: absolute; left: 0; top: 0; width: 90px; height: 2px; border-radius: 2px; opacity: 0; pointer-events: none; transform-origin: 100% 50%; background: linear-gradient(90deg, rgba(242,243,245,0), var(--paper)); box-shadow: 0 0 6px rgba(242,243,245,.8); }
.ts-hum { position: fixed; left: 0; top: 0; width: 34px; z-index: 3; opacity: 0; pointer-events: none; transition: opacity .3s; }
.ts-hum svg { display: block; width: 100%; overflow: visible; }
.ts-hum.face-left svg { transform: scaleX(-1); }
.ts-hum .hb-w { transform-box: view-box; transform-origin: 17px 12px; animation: hb-buzz .05s linear infinite alternate; }
@keyframes hb-buzz { to { transform: scaleY(-.7); } }
.ts-squirrel.is-alarm svg { animation: sq-alarm .11s ease-in-out 8 alternate; transform-origin: 50% 100%; }
@keyframes sq-alarm { to { transform: translateY(-3px) rotate(-6deg); } }
.ts-frog.is-boing svg { animation: fr-boing .6s cubic-bezier(.3,1.6,.5,1); }
@keyframes fr-boing { 40% { transform: translateY(-26px) scale(1.1, .9); } 70% { transform: translateY(0) scale(.9, 1.1); } }
.ts-dragonfly svg { transform-origin: 50% 50%; }
.ts-dragonfly.is-loop svg { animation: df-loop .7s ease-in-out; }
@keyframes df-loop { 50% { transform: translateY(-22px) rotate(180deg); } 100% { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .ts-hum, .ts-shoot { display: none; } }

/* [Route] My Day: Reassign this Service (quiet, full width under the Service rows) */
.job-reassign { display: block; width: 100%; margin-top: 12px; background: #fff; color: var(--ink, var(--ink)); border: 1px solid var(--line); font-weight: 700; }
.job-reassign:hover { border-color: var(--blue); color: var(--blue); }
.field-ask select { width: 100%; }
.field-ask button[disabled] { opacity: .5; cursor: not-allowed; }
/* [Messages and Emails] Email attachments row (emails.php): one line under the message header, scrolls sideways, never wraps. */
.mail-files { display: flex; flex-wrap: nowrap; gap: 8px; overflow-x: auto; margin: 0 0 12px; padding: 2px 0 6px; scrollbar-width: thin; }
.mail-file {
  flex: none; display: inline-flex; align-items: center; gap: 8px; max-width: 260px; height: 40px; padding: 0 12px 0 8px; box-sizing: border-box;
  border: 1px solid var(--line); border-radius: 10px; background: #fff; color: var(--ink); text-decoration: none; white-space: nowrap;
  transition: border-color .15s ease, background-color .15s ease;
}
.mail-file:hover, .mail-file:focus-visible { border-color: var(--blue); background: var(--paper); outline: none; }
.mail-file-ico { position: relative; flex: none; display: inline-grid; place-items: center; width: 28px; height: 28px; color: var(--blue); }
.mail-file-ico .ico { width: 24px; height: 24px; }
.mail-file-ico b { position: absolute; bottom: 1px; left: 50%; transform: translateX(-50%); padding: 0 2px; border-radius: 3px; background: var(--blue); color: #fff; font-size: .5rem; font-weight: 750; line-height: 1.3; }
.mail-file-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; font-weight: 600; font-size: .85rem; }
.mail-file-size { flex: none; color: var(--muted); font-size: .78rem; }
/* [Customers and Properties] Assigned / On This Program table (includes/assign.php): names on one line, number columns only as wide as their content. */
@media (min-width: 801px) {
  table.assigned-table th, table.assigned-table td { white-space: nowrap; text-align: left; }
  table.assigned-table th:nth-child(n+3), table.assigned-table td:nth-child(n+3) { width: 1%; }
  /* Property takes the leftover width and ends in … rather than pushing the page wider than the window. */
  table.assigned-table td:nth-child(2) { max-width: 0; width: 100%; overflow: hidden; text-overflow: ellipsis; }
}
@media (max-width: 800px) {
  /* Phone cards: no desktop table-edge dashes inside the card, badges keep their own width. */
  .card > table.phone-sheet:not(.board) td:first-child, .card > table.phone-sheet:not(.board) td:last-child { border: 0; }
  table.phone-sheet td > .badge { justify-self: start; }
}
/* [Shared] Dispatch list bar: the standard bar sits in a white card like on other pages (the board background is gray). */
.command .list-bar.lb { background: #fff; border-radius: 16px; padding: 10px 14px; }
/* [Shop and Time Clock] Base filter row (Search, All Status, All Teams/Everyone, All Areas): one line, never cut off. Search flexes;
   the filter pills get smaller in steps (1100, 960, 860, phone level, 360). On phones Search has its own line and the pills
   share the next one; if they still don't fit (e.g. a long team name picked) that row slides sideways with an edge fade. */
.command .list-bar.lb .list-search { flex: 1 1 0; min-width: 0; }
@media (min-width: 801px) { .command .list-bar.lb .lb-filters { flex-shrink: 0; } }
@media (max-width: 1100px) {
  .command .lb-filters select { padding: 0 24px 0 10px; font-size: .86rem; }
}
@media (max-width: 960px) {
  .command .list-bar.lb { gap: 8px; padding: 10px 12px; }
  .command .lb-filters { gap: 4px; padding-left: 8px; }
  .command .lb-filters select { padding: 0 20px 0 9px; font-size: .8rem; }
  .command .lb-kbd { display: none; }
  .command .lb .list-search input { padding: 0 34px 0 34px; }
  .command .lb-mag { left: 11px; }
}
@media (max-width: 860px) and (min-width: 801px) {
  .command .list-bar.lb { gap: 6px; padding: 10px; }
  .command .lb-filters { padding-left: 6px; }
  .command .lb-filters select { padding: 0 18px 0 8px; font-size: .78rem; }
  .command .lb .list-search input { padding: 0 30px 0 32px; }
}
@media (max-width: 800px) {
  .command .list-bar.lb { row-gap: 8px; }
  .command .lb-filters { padding-left: 0; }
  .command .lb-filters select { padding: 0 8px 0 10px; }
}
@media (max-width: 360px) {
  .command .list-bar.lb { padding: 10px; }
  .command .lb-filters select { padding: 0 6px 0 8px; font-size: .76rem; }
}

/* [Infrastructure] Debug page: one plain table per card (no inner border), numbers right-aligned on one line */
.debug-scroll { overflow-x: auto; }
.debug-table th, .debug-table td { text-align: left; vertical-align: top; }
.debug-table .num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.debug-table .num .wrap { white-space: normal; text-align: left; min-width: 220px; }
.debug-table pre { margin: 0; white-space: pre-wrap; }
/* [Infrastructure] Debug > Recent Loads (Oct 18, 2026, Travis): When fits its words (left), Page and What Happened are the t-main columns
   and share the room at every width; a cut value shows in full on hover or tap (core.js). Under 801px the table fits the
   phone: When stacks date over time, SQL, Memory, What Happened and Problem fold into one line under the Page. */
body:not(.ps):not(.site) main .card table.dbg-loads { width: 100%; }
body:not(.ps):not(.site) main .card table.dbg-loads tr > td:not(.t-main) { width: 1%; max-width: none; white-space: nowrap; }
body:not(.ps):not(.site) main .card table.dbg-loads tr > td.t-main { width: 50%; max-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
table.dbg-loads td.dbg-when { text-align: left; font-variant-numeric: tabular-nums; }
table.dbg-loads .dbg-sub { display: none; font-size: .8rem; }
table.dbg-loads td .badge { margin: 0; }
/* [Infrastructure] Debug > Problems, Last Day: one row per error (its places counted on a badge); open it for each place and the full message. */
body:not(.ps):not(.site) main .card table.dbg-probs { width: 100%; }
body:not(.ps):not(.site) main .card table.dbg-probs td.dbg-prob-cell { width: 100%; max-width: 0; }
body:not(.ps):not(.site) main .card table.dbg-probs td.num { width: 1%; }
table.dbg-probs details.dbg-prob > summary { display: flex; align-items: center; gap: 6px; cursor: pointer; min-width: 0; }
table.dbg-probs details.dbg-prob > summary .one-line { flex: 0 1 auto; }
table.dbg-probs details.dbg-prob > summary .badge { flex: none; }
table.dbg-probs details[open].dbg-prob > summary .one-line { white-space: normal; overflow-wrap: anywhere; }
table.dbg-probs .dbg-lines { margin: 6px 0 0; padding-left: 18px; font-size: .85rem; }
table.dbg-probs .dbg-lines pre { margin: 2px 0 6px; font-size: .78rem; overflow-wrap: anywhere; }
@media (max-width: 800px) {
  table.dbg-loads .dbg-wide { display: none; }
  table.dbg-loads .dbg-sub { display: block; }
  table.dbg-loads td.dbg-when > span { display: block; }
  table.dbg-loads td.dbg-when > span:first-child { font-size: .8rem; color: var(--muted); }
  body:not(.ps):not(.site) main .card table.dbg-loads tr > td.t-main.dbg-page { width: 100%; }
}

/* [Settings] Settings > Area Types: the add row sits in the table, inputs with their unit after them */
.unit-field { display: flex; align-items: center; gap: 6px; }
.unit-field input { min-width: 0; }
.area-add td { padding-top: 10px; }

/* [Shared] Demo strip (Scorecard sample data and the public demo) */
.sc-demo { display: flex; align-items: center; gap: 10px; margin: 0 0 12px; padding: 10px 14px; border-radius: 12px; background: var(--navy); color: #fff; white-space: nowrap; overflow: hidden; }
.sc-demo b { flex: none; padding: 2px 10px; border-radius: 999px; background: var(--orange); color: var(--ink); font-size: .8rem; }
.sc-demo span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sc-demo a { color: #fff; font-weight: 650; flex: none; }
.sc-demo a:hover { color: var(--grass); }
.content > .sc-demo { margin: 12px 16px 0; }

/* [Estimates] Estimates (R3): option cards sit side by side (siblings, not cards in cards), the signature box, and the Money table. */
.est-options { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; margin-bottom: 14px; }
.est-options > .card { margin: 0; }
.est-opt.rec { border-color: var(--grass); box-shadow: 0 0 0 1px var(--grass); }
.est-opt h2 label.check { font-size: inherit; font-weight: 700; }
label.check input[type="radio"] { width: auto; flex: none; margin: 0; }
.est-price { margin: 0 0 12px; }
.est-price b { font-size: 1.35rem; }
canvas.est-sig { width: 100%; max-width: 600px; height: 160px; border: 1px solid var(--line); border-radius: 10px; background: #fff; touch-action: none; display: block; }
table.est-money { margin-top: 12px; }
/* [Shared] Template Lines: one block per line, a caption on every box, 4 across (2 on a phone). */
.est-line { padding: 14px 0; border-bottom: 1px solid var(--line); }
.est-line:first-child { padding-top: 4px; }
.form-grid.est-line-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px 14px; }
.est-line-grid > label { margin: 0; min-width: 0; }
.est-line-grid > label > input, .est-line-grid > label > select { display: block; margin-top: 4px; min-width: 0; }
.est-line-foot { margin-top: 10px; }
.est-line-foot { flex-wrap: nowrap; }
.est-line-foot label.check { margin-right: auto; white-space: nowrap; }
.est-line-acts { flex-wrap: nowrap; margin: 0; }
.est-line-more { margin: 12px 0 16px; }
@media (max-width: 800px) {
  .form-grid.est-line-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .est-line-foot { flex-direction: column; align-items: flex-start; }
}

/* [Settings] Business Hours rows (Settings > Company): day, opens, closes, Closed on one line; on phones the time picker icon hides so AM/PM fits. */
.hours-row { display: flex; align-items: center; gap: 4px; margin-top: 6px; flex-wrap: nowrap; }
.hours-row > span { flex: 0 0 30px; }
.hours-row input[type=time] { flex: 1 1 0; width: auto; min-width: 0; max-width: 150px; margin: 0; padding: 0 4px; }
.hours-row .check { margin: 0 0 0 2px; white-space: nowrap; }
@media (max-width: 800px) {
  .hours-row input[type=time] { min-width: 84px; }
  .hours-row input[type=time]::-webkit-calendar-picker-indicator { display: none; }
}

/* [Help and Docs] Info tip: a small (i) that shows its hint on hover, keyboard focus or tap. <span class="tip" tabindex="0" role="button" aria-label="..."><span class="tip-body" role="tooltip">...</span></span> */
.tip { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; margin-left: 4px; border: 1px solid var(--blue); border-radius: 999px; color: var(--blue); font-size: 12px; font-weight: 700; font-style: italic; line-height: 1; cursor: help; vertical-align: middle; }
.tip::before { content: "i"; }
.tip:hover, .tip:focus, .tip:focus-within { background: var(--blue); color: #fff; outline: none; }
.tip-body { display: none; position: absolute; right: -6px; bottom: calc(100% + 8px); z-index: 30; width: max-content; max-width: 240px; padding: 8px 10px; border-radius: 8px; background: var(--ink); color: #fff; font-size: 12px; font-weight: 500; font-style: normal; line-height: 1.35; text-align: left; white-space: normal; box-shadow: 0 4px 14px rgba(0, 0, 0, .18); }
.tip-body::after { content: ""; position: absolute; right: 10px; top: 100%; border: 6px solid transparent; border-top-color: var(--ink); }
.tip:hover .tip-body, .tip:focus .tip-body, .tip:focus-within .tip-body { display: block; }
@media (max-width: 800px) {
  /* Phones: the hint shows as a full-width note near the bottom of the screen so it never runs off the edge. */
  .tip-body { position: fixed; left: 16px; right: 16px; bottom: calc(96px + env(safe-area-inset-bottom, 0px)); width: auto; max-width: none; z-index: 80; font-size: 14px; padding: 10px 12px; }
  .tip-body::after { display: none; }
}


/* [Integrations] Shared stat pieces (sx-): status dots and badges, uptime bars, sparklines, ring gauges and the status hero.
   Used by Service Status; any page can reuse them. Colors come from the theme variables. */
.sx-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: #C9CDD2; flex: none; }
.sx-dot.ok { background: var(--grass); }
.sx-dot.warn { background: var(--orange); }
.sx-dot.down { background: var(--red); }
.badge.sx-ok { background: var(--grass); color: var(--ink); }
.badge.sx-warn { background: var(--orange); color: #fff; }
.badge.sx-down { background: var(--red); color: #fff; }
.badge.sx-off, .badge.sx-none { background: var(--paper); color: var(--muted); }
.sx-bars { display: flex; gap: 1px; height: 22px; min-width: 0; }
.sx-bars i { flex: 1 1 0; min-width: 1px; border-radius: 2px; background: var(--grass); }
.sx-bars i.warn { background: var(--orange); }
.sx-bars i.down { background: var(--red); }
.sx-bars i.none { background: #E3E5E8; }
.sx-bars i:hover { opacity: .7; }
.sx-spark { display: block; width: 80px; height: 24px; color: var(--blue); overflow: visible; }
.sx-spark polyline { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linejoin: round; stroke-linecap: round; }
.sx-gauge { display: block; width: 84px; height: 84px; flex: none; }
.sx-gauge circle { fill: none; stroke-width: 9; }
.sx-gauge .track { stroke: var(--paper); }
.sx-gauge .val { stroke: var(--grass); stroke-linecap: round; }
.sx-gauge .val.warn { stroke: var(--orange); }
.sx-gauge .val.down { stroke: var(--red); }
.sx-gauge text { font-size: 17px; font-weight: 700; fill: var(--ink); text-anchor: middle; dominant-baseline: central; }
.sx-hero { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.sx-hero .sx-mark { display: grid; place-items: center; width: 56px; height: 56px; border-radius: 50%; background: var(--grass); color: var(--ink); flex: none; }
.sx-hero .sx-mark.warn { background: var(--orange); color: #fff; }
.sx-hero .sx-mark.down { background: var(--red); color: #fff; }
.sx-hero .sx-mark.none { background: var(--paper); color: var(--muted); }
.sx-hero .sx-mark svg { width: 30px; height: 30px; stroke: currentColor; stroke-width: 2.6; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.sx-hero h2 { margin: 0; font-size: 1.35rem; }
.sx-hero > div:nth-child(2) { flex: 1 1 260px; min-width: 0; }
.sx-meta { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 4px; color: var(--muted); }
.sx-meta b { color: var(--ink); font-weight: 650; font-variant-numeric: tabular-nums; }
.sx-gauges { display: flex; gap: 14px; flex-wrap: wrap; }
.sx-gauges figure { margin: 0; text-align: center; color: var(--muted); font-size: .8rem; }
.sx-table td { vertical-align: middle; }
.sx-table td.sx-name { min-width: 160px; max-width: 280px; }
.sx-table td.sx-name > div { display: flex; align-items: center; gap: 10px; min-width: 0; }
.sx-table td.sx-name > div > div { min-width: 0; overflow: hidden; }
.sx-table td.sx-name span { display: block; color: var(--muted); font-size: .8rem; font-weight: 400; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sx-table td.sx-state { min-width: 130px; max-width: 220px; }
.sx-table td.sx-state .sx-detail { display: block; margin-top: 3px; color: var(--muted); font-size: .8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sx-table th { white-space: nowrap; }
.sx-table td.sx-state .sx-detail em { display: none; font-style: normal; }
.sx-table td.sx-num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.sx-table td.sx-wide { width: 26%; min-width: 100px; }
.sx-table .sx-since { display: block; color: var(--muted); font-size: .72rem; }
.sx-gauges figure figcaption { white-space: nowrap; }
/* [Shared] Tablets and small laptops (sidebar showing): drop the 24-hour sparkline and Checked columns so the table fits; names stay one line. */
@media (min-width: 701px) and (max-width: 1180px) {
  .sx-table th:nth-child(3), .sx-table th:nth-child(4), .sx-table th:nth-child(7), .sx-table td.sx-ms, .sx-table td.sx-phone-hide { display: none; }
  .sx-table td.sx-state .sx-detail em { display: inline; } /* latency moves under the status chip */
  .sx-table td.sx-name { max-width: 220px; }
  .sx-table td.sx-name > div > div { white-space: nowrap; text-overflow: ellipsis; }
}
@media (min-width: 701px) and (max-width: 900px) {
  .sx-table td.sx-name { min-width: 120px; max-width: 180px; }
  .sx-table td.sx-state { min-width: 110px; max-width: 170px; }
  .sx-table td.sx-wide { min-width: 70px; }
}
.sx-bars-short { justify-content: flex-start; }
.sx-bars-short { gap: 2px; }
.sx-bars-short i { flex: 0 0 8px; }
.sx-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 0 16px; }
/* [Infrastructure] Service Status, one line per row (Oct 18, 2026, Travis): the pill, then its detail beside it only when it adds something
   (the rest is on the pill's hover); "…" when the cell is full, full text on hover or tap (core.js). */
.sx-table td.sx-state .sx-st { display: flex; align-items: center; gap: 8px; min-width: 0; }
.sx-table td.sx-state .sx-st .badge { flex: none; }
@media (min-width: 701px) { .sx-table td.sx-state .sx-st .sx-detail { display: block; margin: 0; min-width: 0; flex: 0 1 auto; } } /* phones keep their indented detail line */
/* [Shared] Errors & Slow Pages Today: tiles share the card's width like the other cards' tiles, tables keep the standard gap. */
.sx-err-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.sx-err-stats .stat { min-width: 0; }
.card table.sx-err { width: 100%; margin-top: 16px; }
.card .stats + table.sx-err { margin-top: 0; }
body:not(.ps):not(.site) main .card table.sx-err td.t-main { max-width: 0; width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
body:not(.ps):not(.site) main .card table.sx-err td.t-main > a { display: block; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
table.sx-err .num { text-align: right; white-space: nowrap; width: 1%; }
.sx-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.sx-note { color: var(--muted); font-size: .8rem; margin: 6px 0 0; }
@media (max-width: 700px) {
  /* Phones: one flat row per service inside the group card (no card-on-card), three short lines:
     dot + name + status chip / detail + latency across the full width / history bar + uptime. */
  .sx-bars i:nth-child(-n+60) { display: none; }
  .sx-bars-short i:nth-child(-n+60) { display: block; }
  table.sx-table, table.sx-table tbody { display: block; }
  table.sx-table tr:first-child { display: none; }
  table.sx-table tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name chip" "detail detail" "bars pct"; align-items: center; gap: 4px 10px; padding: 10px 0; border-bottom: 1px solid var(--paper); }
  table.sx-table tr:last-child { border-bottom: 0; }
  table.sx-table td { display: block; padding: 0; border: 0; min-width: 0; width: auto; background: transparent; }
  table.sx-table td.sx-name { grid-area: name; font-weight: 650; min-width: 0; }
  table.sx-table td.sx-name span { display: none; }
  table.sx-table td.sx-name > div > div { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
  table.sx-table td.sx-state, table.sx-table td.sx-state .sx-st { display: contents; }
  table.sx-table td.sx-state .badge { grid-area: chip; justify-self: end; }
  table.sx-table td.sx-state .sx-detail { grid-area: detail; margin: 0 0 0 20px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  table.sx-table td.sx-state .sx-detail em { display: inline; }
  table.sx-table td.sx-ms, table.sx-table td.sx-phone-hide { display: none; }
  table.sx-table td.sx-wide { grid-area: bars; margin-left: 20px; }
  table.sx-table td.sx-wide .sx-bars { height: 12px; }
  table.sx-table td.sx-pct { grid-area: pct; text-align: right; font-size: .8rem; }
  table.sx-table td.sx-pct .sx-since { display: inline; margin-left: 4px; }
  .sx-hero .sx-gauges { width: 100%; justify-content: space-around; }
  .sx-hero .sx-gauges { flex-wrap: nowrap; gap: 6px; }
  .sx-hero .sx-gauges figure { flex: 1 1 0; min-width: 0; }
  .sx-hero .sx-gauges .sx-gauge { width: 76px; height: 76px; margin: 0 auto; }
}
/* [Sprout] Text Assistant (assistant.php): Try It bubbles and the one-line recent texts table. */
.asst-chat { display: flex; flex-direction: column; gap: 6px; }
.asst-chat p { margin: 0; padding: 8px 12px; border-radius: 14px; max-width: 80%; line-height: 1.35; }
.asst-route { margin: 6px 0 0; line-height: 1.4; }
.asst-chat .asst-in { align-self: flex-end; background: var(--blue); color: #fff; }
.asst-chat .asst-out { align-self: flex-start; background: var(--paper); border: 1px solid var(--line); }
/* [Shared] Recent texts: Text and Answer are the main columns (td.t-main, the house rule), When, Who and Result fit their words. */
table.asst-log { width: 100%; }
table.asst-log th, table.asst-log td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
body:not(.ps):not(.site) main .card table.asst-log tr > td:not(.t-main) { width: 1%; max-width: none; }
body:not(.ps):not(.site) main .card table.asst-log tr > td.asst-cut:not(.t-main) { max-width: 24em; } /* Text fits its words up to 24em; Answer (t-main) takes the rest */
body:not(.ps):not(.site) main .card table.asst-log tr > td.t-main { width: 100%; max-width: 0; } /* at every width (the house t-main rule is 801px+ only) */
@media (min-width: 701px) and (max-width: 1100px) { body:not(.ps):not(.site) main .card table.asst-log:has(td.t-main) tr > td.asst-cut:not(.t-main) { max-width: 16vw; } } /* tablets: 24em made the table 22px wider than an 820 screen (Oct 19, 2026) */
@media (max-width: 700px) {
  table.asst-log th.sx-phone-hide, table.asst-log td.sx-phone-hide { display: none; }
  body:not(.ps):not(.site) main .card table.asst-log tr > td.asst-cut:not(.t-main) { width: 100%; max-width: 0; } /* Answer is hidden: Text takes the row */
  /* Text is the last column showing on phones: give it the table's right edge. */
  table.asst-log th:nth-child(3), table.asst-log td:nth-child(3) { border-right: 1px dashed var(--line); }
  table.asst-log th:nth-child(3) { border-top-right-radius: 12px; }
  table.asst-log tr:last-child td:nth-child(3) { border-bottom-right-radius: 12px; }
}

/* [Dashboard] Dashboard widgets (index.php, includes/widgets.php, assets/js/widgets.js). 12 columns on a computer, one on a phone.
   Rows are at least 96px (a 2-row card at least 206px) and grow to fit the tallest card in the row, so short cards don't
   carry empty space (Quick Actions never clips its last row). */
.dw-bar { display: none; align-items: center; gap: 10px; flex-wrap: wrap; position: sticky; top: 0; z-index: 20; margin: 0 0 14px; padding: 10px 14px;
  background: rgba(255,255,255,.82); backdrop-filter: blur(14px) saturate(1.4); -webkit-backdrop-filter: blur(14px) saturate(1.4); border: 1px solid var(--line); border-radius: 12px; }
.dash-editing .dw-bar { display: flex; }
.dw-bar .dw-hint { color: var(--muted); font-size: .85rem; flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (min-width: 701px) { .dw-bar { flex-wrap: nowrap; } .dw-bar .btn, .dw-saved { flex: none; } }
.dw-saved { font-size: .78rem; color: var(--muted); display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.dw-saved .sx-dot { width: 8px; height: 8px; }
.dw-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); grid-auto-rows: minmax(96px, auto); grid-auto-flow: row dense; gap: 14px; }
.dw { position: relative; display: flex; flex-direction: column; min-width: 0; margin: 0; padding: var(--card-pad, 14px 16px); overflow: hidden; transition: box-shadow .15s ease, transform .15s ease; }
.dw h2 { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; font-size: .95rem; min-width: 0; }
.dw h2 svg { width: 18px; height: 18px; color: var(--blue); flex: none; }
.dw h2 .dw-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.dw h2 .dw-more { margin-left: auto; font-size: .78rem; font-weight: 600; flex: none; }
.dw-in { flex: 1; min-height: 0; display: flex; flex-direction: column; min-width: 0; }
.dw-body { flex: 1; min-height: 0; overflow: hidden; }
.dw-in:has(> .dw-empty) { justify-content: center; } /* empty list beside a tall card (Radar): count and note sit in the middle */
.dw-empty { margin: 4px 0 0; }
.dw-gap { margin-top: 8px; }
.dw-in > p.dw-gap { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* Service Status widget line: one line at 820 (rules check, Oct 18) */
.dw-head { display: flex; gap: 10px; align-items: baseline; min-width: 0; margin-bottom: 4px; }
.dw-head .badge { flex: none; }
.dw-t1 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.dw-row { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px solid var(--paper); white-space: nowrap; min-width: 0; }
.dw-row:last-child { border-bottom: 0; }
.dw-row .dw-t { overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 1; }
.dw-row a { color: var(--ink); }
.dw-row a:hover { color: var(--blue); }
.dw-row .muted { flex: none; font-size: .8rem; max-width: 45%; overflow: hidden; text-overflow: ellipsis; }
.dw-big { font-size: 1.9rem; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; flex: none; }
.dw-k-quick { overflow: visible; }
/* [Shared] Quick Actions (Oct 18 2026): one row (data-fit, assets/js/fit-row.js; what doesn't fit goes into More), fonts never shrink;
   a narrow card uses each button's short name from the phone tab bar (Base -> Command). */
.dw-actions { gap: 8px; container: dw-actions / inline-size; }
.dw-actions .btn { white-space: nowrap; }
.dw-actions .pill-short { display: none; }
@container dw-actions (max-width: 520px) {
  .dw-actions .pill-full { display: none; }
  .dw-actions .pill-short { display: inline; }
}
.dw-aging { display: flex; height: 12px; border-radius: 6px; overflow: hidden; margin: 10px 0 8px; background: var(--paper); }
.dw-aging i { display: block; }
.dw-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: .8rem; color: var(--muted); }
.dw-legend b { color: var(--ink); font-variant-numeric: tabular-nums; }
.dw-wx { display: flex; align-items: center; gap: 14px; min-width: 0; }
.dw-wx-ico { font-size: 2.2rem; line-height: 1; flex: none; }
.dw-wx-now { min-width: 0; }
.dw-wx .dw-big { font-size: 2.3rem; }
.dw-wx-line { display: flex; align-items: center; gap: 16px; min-width: 0; }
.dw-wx-line .dw-wx { flex: 0 1 auto; }
.dw-wx-line .dw-days { flex: 1; margin-top: 0; }
.dw-days { display: grid; gap: 6px; margin-top: 12px; text-align: center; font-size: .78rem; min-width: 0; }
.dw-days div { background: var(--paper); border-radius: 10px; padding: 6px 2px; display: grid; gap: 2px; min-width: 0; }
.dw-days span { color: var(--muted); }
.dw-days i { font-style: normal; font-size: 1.1rem; line-height: 1.2; }
.dw-days b { font-size: .95rem; }
.dw-days em { font-style: normal; color: var(--muted); font-size: .72rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dw-days .dw-dwind { font-size: .7rem; }
/* [Dashboard] A 2-row Weather card next to the Radar: the forecast tiles fill the card's height, so no empty band under them. */
.dw-in > .dw-days:last-child { flex: 1 1 auto; align-items: stretch; }
.dw-in > .dw-days:last-child > div { align-content: center; }
.dw-asof { font-size: .72rem; color: var(--muted); display: flex; align-items: center; gap: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 2px; }
.dw-asof .sx-dot { flex: none; }
.dw-asof-old { color: #8A8F98; }
.dw-asof-paused { color: var(--text, #111); font-weight: 600; }
.dw-wx-wait { animation: dw-wx-pulse 1.4s ease-in-out infinite; }
@keyframes dw-wx-pulse { 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .dw-wx-wait { animation: none; } }
.dw-radar { flex: 1; min-height: 0; }
.dw-rmap { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; border-radius: 12px; overflow: hidden; background: #1a1d22; isolation: isolate; }
.dw-rmap .map-hold { flex: 1; min-height: 0; display: flex; border-radius: 12px; overflow: hidden; }
.dw-rmap .dw-rmap-map { flex: 1; min-height: 180px; width: 100%; background: #1a1d22; }
.dw-rmap .leaflet-control-attribution { font-size: 9px; background: rgba(6, 16, 24, .55); color: #9aa4ad; white-space: nowrap; max-width: 70%; overflow: hidden; text-overflow: ellipsis; }
.dw-rmap .leaflet-control-attribution a { color: #9aa4ad; }
.dw-rbar { position: absolute; left: 8px; top: 8px; right: 8px; z-index: 1000; display: flex; align-items: center; gap: 6px; min-width: 0; pointer-events: none; }
.dw-rbar > * { pointer-events: auto; }
.dw-rplay { flex: none; width: 28px; height: 28px; border-radius: 999px; border: 0; background: rgba(6, 16, 24, .78); color: #d7fff4; cursor: pointer; display: grid; place-items: center; padding: 0; }
.dw-rplay::before { content: ""; width: 0; height: 0; border-left: 9px solid currentColor; border-top: 6px solid transparent; border-bottom: 6px solid transparent; margin-left: 2px; }
.dw-rplay.on::before { width: 8px; height: 10px; border: 0; margin: 0; background: linear-gradient(90deg, currentColor 0 3px, transparent 3px 5px, currentColor 5px 8px); }
.dw-rtime { flex: 0 1 auto; min-width: 0; padding: 4px 9px; border-radius: var(--pill-radius, 999px); background: rgba(6, 16, 24, .72); color: #d7fff4; font-size: .72rem; font-weight: 750; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dw-ralert { flex: 0 1 auto; min-width: 0; margin-left: auto; padding: 4px 9px; border-radius: var(--pill-radius, 999px); background: rgba(176, 30, 20, .88); color: #fff; font-size: .72rem; font-weight: 750; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dw-rmap .map-move { display: none; } /* Dashboard Radar has no Move lock */
.dw-rmap .leaflet-top.leaflet-left { top: 8px; } /* no Move button under the play bar */
.map-hold.map-free > .leaflet-container { pointer-events: auto !important; touch-action: pan-y; }
.dw-rmap .map-hold.map-free .leaflet-container { touch-action: pan-y; }
.dw-soil { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.dw-soil div { background: var(--paper); border-radius: 10px; padding: 8px 10px; min-width: 0; display: grid; gap: 1px; }
.dw-soil span { color: var(--muted); font-size: .78rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dw-soil b { font-size: 1.35rem; font-variant-numeric: tabular-nums; }
.dw-soil em { font-style: normal; font-size: .72rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dw-soil .soil-dry { color: var(--red); }
.dw-soil .soil-good { color: var(--ink); }
.dw-soil .soil-fair, .dw-soil .soil-wet { color: var(--blue); }
.dw-totals { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 8px; }
.dw-totals a { display: grid; gap: 2px; padding: 8px 10px; border-radius: 10px; background: var(--paper); color: var(--ink); min-width: 0; }
.dw-totals a:hover { background: rgba(30,144,255,.1); }
.dw-totals b { font-size: 1.35rem; font-variant-numeric: tabular-nums; }
.dw-totals span { display: flex; align-items: center; gap: 5px; color: var(--muted); font-size: .78rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dw-totals svg { width: 14px; height: 14px; flex: none; }
.dw-profit-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.dw-bars { flex: 1; height: auto; min-height: 70px; }
.dw-hours { display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; font-size: .85rem; margin-top: 6px; }
/* [Shared] Edit mode */
.dw-tools { display: none; position: absolute; top: 8px; right: 8px; gap: 4px; z-index: 3; }
.dash-editing .dw-tools { display: flex; }
.dw-tools button { width: 28px; height: 28px; padding: 0; border-radius: 50%; display: grid; place-items: center; }
.dw-tools svg { width: 15px; height: 15px; }
.dw-grip { cursor: grab; touch-action: none; }
.dash-editing .dw { outline: 2px dashed rgba(30,144,255,.45); outline-offset: -2px; animation: dw-wiggle .5s ease 1; }
.dash-editing .dw:hover { box-shadow: 0 10px 28px rgba(22,58,95,.14); }
.dash-editing .dw-in { pointer-events: none; opacity: .92; }
.dash-editing .dw-more { display: none; }
.dash-editing .dw h2 { padding-right: 96px; }
.dw-size { display: none; flex: none; font-size: .72rem; font-weight: 700; color: var(--blue); background: rgba(30,144,255,.1); border-radius: var(--pill-radius, 999px); padding: 2px 8px; }
.dash-editing .dw-size { display: inline-block; }
.dw-resize { display: none; position: absolute; right: 4px; bottom: 4px; width: 22px; height: 22px; cursor: nwse-resize; touch-action: none; z-index: 3;
  background: linear-gradient(135deg, transparent 50%, var(--blue) 50%, var(--blue) 58%, transparent 58%, transparent 70%, var(--blue) 70%, var(--blue) 78%, transparent 78%); border-radius: 0 0 10px 0; }
.dash-editing .dw-resize { display: block; }
@keyframes dw-wiggle { 0%,100% { transform: none; } 30% { transform: rotate(-.5deg); } 60% { transform: rotate(.5deg); } }
@media (prefers-reduced-motion: reduce) { .dash-editing .dw { animation: none; } }
/* [Dashboard] Add Widget gallery: frosted side panel with categories */
.dw-shade { position: fixed; inset: 0; background: rgba(17,17,17,.28); z-index: 60; display: none; }
.dw-gallery { position: fixed; top: 0; right: 0; bottom: 0; width: min(440px, 100%); z-index: 61; display: none; flex-direction: column;
  background: rgba(242,243,245,.86); backdrop-filter: blur(22px) saturate(1.5); -webkit-backdrop-filter: blur(22px) saturate(1.5); border-left: 1px solid rgba(255,255,255,.6); box-shadow: -20px 0 50px rgba(0,0,0,.18); }
.dw-open .dw-shade, .dw-open .dw-gallery { display: flex; }
.dw-gallery header { display: flex; align-items: center; gap: 8px; padding: calc(16px + env(safe-area-inset-top, 0px)) 18px 8px; } /* full-height sheet: header below the iPhone status bar */
.dw-gallery header h2 { margin: 0; font-size: 1.05rem; margin-right: auto; }
.dw-cats { display: flex; gap: 6px; padding: 4px 18px 12px; flex-wrap: wrap; }
.dw-cats button { border-radius: 999px; padding: 5px 12px; font-size: .8rem; }
.dw-cats button.on { background: var(--ink); color: #fff; border-color: var(--ink); }
.dw-list { overflow: auto; padding: 0 18px 18px; display: grid; gap: 10px; align-content: start; }
.dw-pick { display: grid; grid-template-columns: 64px 1fr auto; gap: 12px; align-items: center; padding: 10px; background: rgba(255,255,255,.9); border: 1px solid var(--card-edge, var(--line)); border-radius: 12px; }
.dw-pick:hover { border-color: var(--blue); }
.dw-thumb { height: 52px; border-radius: 8px; background: var(--paper); display: grid; place-items: center; overflow: hidden; color: var(--blue); }
.dw-thumb svg { width: 26px; height: 26px; }
.dw-pick b { display: block; }
.dw-pick span { color: var(--muted); font-size: .8rem; }
.dw-gallery footer { padding: 12px 18px calc(12px + env(safe-area-inset-bottom)); border-top: 1px solid var(--line); font-size: .8rem; color: var(--muted); }
@media (max-width: 700px) {
  .dw-grid { grid-template-columns: minmax(0, 1fr); grid-auto-rows: auto; }
  .dw { grid-column: 1 / -1 !important; grid-row: auto !important; min-height: 120px; }
  .dw[data-h="2"] { min-height: 250px; }
  .dw[data-h="3"] { min-height: 380px; }
  .dw:has(.dw-empty), .dw:is(.dw-k-today, .dw-k-tasks, .dw-k-messages, .dw-k-ar, .dw-k-status, .dw-k-wx_rain) { min-height: 0; } /* lists: shrink to their rows on phones */ /* nothing to list (Today's Services, Rain Since): the card shrinks to its content */
  .dw-radar { min-height: 220px; }
  .dw-bar { position: static; }
  .dw-bar .dw-hint { flex-basis: 100%; white-space: normal; }
  .dw-wx-line { display: block; }
  .dw-wx-line .dw-days { margin-top: 12px; }
  .dw-days { grid-template-columns: repeat(5, minmax(0, 1fr)) !important; }
  .dw-days div:nth-child(n+6) { display: none; }
}
/* [Sprout] Text Assistant share grid: the topic takes the row, role columns stay as narrow as their names. */
.asst-share td:first-child { width: 100%; max-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* one line; "…" only on a narrow phone, the full topic in its hover tip */
.asst-share th:not(:first-child), .asst-share td:not(:first-child) { width: 1%; white-space: nowrap; }
@media (max-width: 700px) {
  .asst-share th:not(:first-child), .asst-share td:not(:first-child) { padding-left: 4px; padding-right: 4px; font-size: .66rem; letter-spacing: 0; }
  .asst-share td:first-child { padding-right: 6px; max-width: 0; font-size: .85rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* one line; full topic on hover and tap */
  /* Dashboard: the clock gives way to the page buttons on phones. */
  .top-actions ~ .live-clock { display: none; }
}

/* [Infrastructure] Service Status incidents: one flat row per event (name + chip, full-width detail, when on one line). */
.sx-inc-row { padding: 10px 0; border-top: 1px solid var(--line); }
.sx-inc-row:first-child { border-top: 0; padding-top: 2px; }
.sx-inc-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.sx-inc-top b { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sx-inc-top .badge { flex: none; }
.sx-inc-detail { margin-top: 3px; font-size: 13px; }
.sx-inc-when { margin-top: 2px; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sx-false .sx-inc-top b { color: var(--muted); font-weight: 600; }
/* [Dashboard] Dashboard widgets: size tiers (small, wide, medium, large). */
.dw-progress { height: 6px; border-radius: 3px; background: var(--paper); overflow: hidden; margin: 8px 0 6px; }
.dw-progress span { display: block; height: 100%; background: var(--grass); border-radius: 3px; }
.dw-spray { margin: 8px 0 4px; }
.dw-spark { width: 60px; height: 16px; flex: none; color: var(--blue); }
.dw-sx .dw-row { color: var(--ink); text-decoration: none; }
.dw-sx .dw-row:hover .dw-t { color: var(--blue); }
.dw-sx .dw-ms { min-width: 52px; text-align: right; }
.dw-soil.dw-one { grid-template-columns: minmax(0, 1fr); }
.dw-mv { display: none !important; }
@media (max-width: 700px) {
  /* Phones: one column; reorder with the arrows (or hold the grip and drag). Resize cycles the size, which changes what the card shows. */
  .dash-editing .dw-mv { display: grid !important; }
  .dash-editing .dw-resize { display: none; }
  .dw-spark { width: 48px; }
}
.dash-editing .dw h2 { touch-action: none; -webkit-user-select: none; user-select: none; }
.dw-hint-phone { display: none; }
@media (max-width: 700px) {
  /* Phone edit mode: arrows, size and remove only (hold the title to drag), so the title keeps its room. */
  .dw-hint-wide, .dash-editing .dw-grip, .dash-editing .dw h2 .dw-size { display: none !important; }
  .dw-hint-phone { display: inline; }
  .dash-editing .dw h2 { padding-right: 138px; }
}
/* [Infrastructure] Transcripts (Admin): one line per row; the title takes the rest and ends in "…". */
.tx-list { width: 100%; table-layout: fixed; }
.tx-list th:first-child, .tx-list td.tx-date { width: 140px; }
.tx-list td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tx-list td a { display: block; color: var(--ink); font-weight: 650; overflow: hidden; text-overflow: ellipsis; }
.tx-list tr:hover td a { color: var(--blue); }
.tx-list td.tx-date { color: var(--muted); font-variant-numeric: tabular-nums; vertical-align: top; }
.tx-list td > .one-line { font-size: .8rem; } /* topics under the title; the time range or reading length under the date */
.tx-doc { max-width: 860px; }
/* [Tasks and Tracker] Procedures (parent CRM): one grid per section, Command | Steps | What It Does | Last Run | Run (Oct 17, 2026).
   Columns size to their content; What It Does (td.t-main) takes the room that is left and is the one that ends in "…"
   (the full phrase is on hover and in Steps). Narrow widths drop What It Does, then Steps and the Last Run counts. */
.proc-grid { width: 100%; }
.proc-grid td, .proc-grid th { white-space: nowrap; height: 52px; }
.proc-grid th { height: auto; }
.proc-grid td.t-main { width: 100%; max-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: .9rem; }
.proc-grid td:first-child a { color: var(--ink); text-decoration: none; } /* the name opens its Steps too (the only way on phones) */
.proc-grid td:first-child a:hover { color: var(--blue); }
.proc-grid.proc-toks { table-layout: fixed; }
.proc-toks td, .proc-toks th { overflow: hidden; text-overflow: ellipsis; }
.proc-toks th:nth-child(1) { width: auto; }
.proc-toks th:nth-child(2), .proc-toks th:nth-child(3) { width: 150px; }
.proc-toks th:nth-child(4) { width: 80px; }
.proc-toks th:nth-child(5) { width: 100px; }
.proc-last { display: flex; align-items: center; gap: 8px; min-width: 0; }
.td-line { display: flex; align-items: center; gap: 6px; min-width: 0; } /* a cell's text (.one-line, "…" only when full) with its badges after it */
.td-line > .one-line { flex: 0 1 auto; }
.proc-last .muted { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .85rem; }
.proc-index { display: flex; align-items: center; gap: 10px; margin: 8px 0 12px; white-space: nowrap; overflow: hidden; }
.proc-index > * { flex: none; }
.proc-index > code, .proc-index > input, .proc-index > .muted { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 1100px) {
  .proc-grid th, .proc-grid td { padding-left: 6px; padding-right: 6px; }
  .proc-toks th:nth-child(2), .proc-toks th:nth-child(3) { width: 130px; }
  .proc-toks th:nth-child(4) { width: 64px; }
  .proc-toks th:nth-child(5) { width: 90px; }
}
@media (max-width: 1020px) { /* narrow two-pane widths: the phrase is in the hover and Steps; the name opens Steps too */
  .proc-grid:not(.proc-toks) :is(th, td):nth-child(2), .proc-grid:not(.proc-toks) :is(th, td):nth-child(3) { display: none; }
  .proc-grid:not(.proc-toks) td:nth-child(4) { width: 100%; max-width: 0; } /* Last Run takes the room; its counts end in "…" when short of it */
}
@media (max-width: 800px) {
  .proc-grid:not(.proc-toks) td:first-child { width: 100%; max-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .proc-grid:not(.proc-toks) td:nth-child(4) { width: auto; max-width: none; }
  .proc-grid .gear-link span, .proc-last .muted { display: none; }
  .proc-toks th:nth-child(2), .proc-toks td:nth-child(2), .proc-toks th:nth-child(4), .proc-toks td:nth-child(4) { display: none; }
  .proc-toks th:nth-child(3), .proc-toks td:nth-child(3) { display: table-cell; }
  .proc-toks th:nth-child(3) { width: 120px; }
  .proc-toks th:nth-child(5) { width: 86px; }
}
/* [Infrastructure] Run Commands (Procedures): the same column widths in every group table; Last Ran is the real time then a small
   status pill. Phones hide the Last Ran column and show the time under the command name instead (Oct 19, 2026). */
.rc-grid { table-layout: fixed; }
.rc-grid th:nth-child(1) { width: 34%; }
.rc-grid th:nth-child(3) { width: 210px; }
.rc-grid th:nth-child(4) { width: 72px; }
.rc-grid td { overflow: hidden; text-overflow: ellipsis; }
.rc-grid td:first-child .one-line { display: block; overflow: hidden; text-overflow: ellipsis; }
.rc-grid .rc-when { display: none; font-size: .8rem; }
.rc-box-out { height: 156px; overflow-y: auto; } /* Command Box: up to 3 matches in a fixed spot, so nothing below jumps */
.rc-grid .badge { flex: none; }
.rc-grid.rc-co th:nth-child(2) { width: 80px; }
.rc-grid.rc-co th:nth-child(3) { width: auto; }
@media (max-width: 1020px) {
  .proc-grid.rc-grid:not(.rc-co) :is(th, td):nth-child(2) { display: none; }
  .proc-grid.rc-grid :is(th, td):nth-child(3), .proc-grid.rc-co :is(th, td):nth-child(2) { display: table-cell; }
  .rc-grid th:nth-child(1) { width: auto; }
  .rc-grid td:nth-child(4) { width: auto; max-width: none; }
}
@media (max-width: 800px) {
  .proc-grid.rc-grid:not(.rc-co) :is(th, td):nth-child(3) { display: none; }
  .rc-grid:not(.rc-co) .rc-when { display: flex; align-items: center; gap: 6px; }
  .rc-grid td { height: auto; padding-top: 8px; padding-bottom: 8px; }
  .rc-grid.rc-co th:nth-child(2) { width: 64px; }
}
.tx-when { margin: 0 0 6px; }
.tx-prose { line-height: 1.6; overflow-wrap: anywhere; }
.tx-prose h2 { font-size: 1.15rem; margin: 6px 0 10px; }
.tx-prose h3 { font-size: 1rem; margin: 18px 0 6px; }
.tx-prose h4 { font-size: .92rem; margin: 14px 0 4px; }
.tx-prose h2, .tx-prose h3, .tx-prose h4 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* headings in Summaries and Procedures stay one line, full text on hover (Oct 17, 2026) */
.tx-prose p { margin: 0 0 10px; }
.tx-prose ul, .tx-prose ol:not(.steps) { margin: 0 0 10px; padding-left: 22px; }
.tx-prose li { margin: 0 0 4px; }
.tx-prose hr { border: 0; border-top: 1px solid var(--line); margin: 14px 0; }
@media (max-width: 700px) {
  .tx-list th:first-child, .tx-list td.tx-date { width: 138px; }
  .tx-list th, .tx-list td { padding-left: 8px; padding-right: 8px; }
}
/* [Customers and Properties] One-tap Call · Text · Email · Directions under a customer, property or Service heading (includes/phone_tabs.php). */
.row.reach-row { margin-top: 10px; }
/* [Route] Tappable one-line rows inside a popup (My Day's See another team): tap a row to switch, a check on the current one. */
.field-ask .pick-list { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: 10px; overflow: hidden auto; max-height: 55dvh; margin: 0 0 12px; }
.field-ask .pick-list .pick { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 46px; padding: 12px 14px; text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.field-ask .pick-list .pick span { overflow: hidden; text-overflow: ellipsis; }
.field-ask .pick-list .pick:last-child { border-bottom: 0; }
.field-ask .pick-list .pick.on { font-weight: 700; }
.field-ask .pick-check { color: var(--grass); font-size: 1.1rem; }
/* [Customers and Properties] One app, three sides (app.php, includes/app_sides.php): the Staff / Customer switch reuses the .tabs pills, stretched to two halves. */
.tabs.sides { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin: 4px 0 12px; padding: 4px; background: var(--paper); border-radius: 999px; overflow: visible; }
.tabs.sides a, .tabs.sides label { display: block; margin: 0; padding: 8px 14px; border-radius: 999px; border: 1px solid transparent; background: transparent; color: var(--ink); text-align: center; text-decoration: none; font-weight: 700; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tabs.sides a:hover, .tabs.sides label:hover { background: #fff; text-decoration: none; }
.tabs.sides a.on, .tabs.sides a.on:hover, .tabs.sides label.on, .tabs.sides label.on:hover { background: var(--blue); border-color: var(--blue); color: #fff; cursor: default; }
.tabs.sides input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.tabs.sides label:has(input:focus-visible) { outline: 2px solid var(--blue); outline-offset: 2px; }
.login .as-sides-note { margin: 10px 0 4px; }
.login > .notices { position: fixed; z-index: 60; top: 0; left: 0; right: 0; max-width: 480px; margin: 0 auto; height: 0; padding: calc(env(safe-area-inset-top, 0px) + 8px) 12px 0; pointer-events: none; }
.login > .notices > .toast { pointer-events: auto; }
.field-menu .tabs.sides, .side .tabs.sides { background: rgba(255, 255, 255, .08); margin: 4px 0 8px; }
.side .tabs.sides { margin: 0 8px 8px; }
.field-menu .tabs.sides a, .side .tabs.sides a { color: #eee; padding: 8px 10px; font-weight: 650; }
.field-menu .tabs.sides a:hover, .side .tabs.sides a:hover { background: var(--navy); color: #fff; }
.field-menu .tabs.sides a.on, .side .tabs.sides a.on { background: var(--blue); border-color: var(--blue); color: #fff; }
.side button.logout { display: block; width: auto; height: auto; min-height: 0; background: transparent; border: 0; box-shadow: none; text-align: left; font-family: inherit; cursor: pointer; }
.side button.logout:hover { background: rgba(255,255,255,.06); color: #fff; }

/* [Route] Products on a Service (includes/service_products.php): one line per product on Route and Base. */
.sp { display: grid; gap: 8px; }
.sp p { margin: 0; }
.sp-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.sp-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 4px 12px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.sp-main { min-width: 0; display: flex; align-items: baseline; gap: 8px; }
.sp-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: none; max-width: 60%; }
.sp-meta { color: var(--muted); font-size: .8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.sp-amount { white-space: nowrap; font-variant-numeric: tabular-nums; }
.sp-amt { display: flex; align-items: center; gap: 6px; margin: 0; font-size: .8rem; color: var(--muted); }
.sp-amt input { width: 130px; }
.sp-acts { display: flex; align-items: center; gap: 2px; white-space: nowrap; }
.sp .sp-btn, .sp-open { background: none; border: 0; height: auto; min-height: 0; padding: 4px 6px; border-radius: 6px; color: var(--blue); font-weight: 600; font-size: .85rem; width: auto; }
.sp .sp-btn:hover, .sp-open:hover { background: var(--paper); color: #1873cc; }
.sp-open { padding: 0; font-size: inherit; }
.sp-row.is-removed .sp-name, .sp-row.is-removed .sp-amount { text-decoration: line-through; color: var(--muted); }
/* .sp-row .badge: shared pill size (Tracker 880) */
.sp-edit { grid-column: 1 / -1; display: grid; gap: 8px; padding: 4px 0 2px; }
.sp-edit[hidden] { display: none; }
.sp-fields { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.sp-fields label { margin: 0; font-size: .8rem; color: var(--muted); display: grid; gap: 2px; }
.sp-fields select { margin: 0; }
.sp-edit-btns, .sp-add { display: flex; gap: 8px; align-items: center; }
.sp-add input { flex: 1; min-width: 0; }
.sp .sp-edit-btns button, .sp .sp-add button { width: auto; flex: none; }
.sp-log { margin: 4px 0 0; padding-left: 18px; color: var(--muted); font-size: .8rem; }
.sp-box { width: min(760px, calc(100vw - 24px)); max-height: calc(100dvh - 32px); overflow: auto; border: 0; border-radius: 16px; padding: 18px 20px calc(18px + env(safe-area-inset-bottom)); box-shadow: 0 18px 48px rgba(16, 24, 40, .25); }
.sp-box > .toast { position: sticky; top: 0; z-index: 2; margin: -6px 0 10px; box-shadow: 0 8px 24px rgba(16, 24, 40, .12); }
.sp-box-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 4px; }
.sp-box-head h3 { margin: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.field-products { margin: 12px; padding: 12px 14px; background: #fff; border-radius: 16px; }
.field-products h3 { margin: 0 0 6px; font-size: .95rem; }
.sheet-step .sp { margin: 2px 0 6px; }
@media (max-width: 640px) {
  .sp-row { grid-template-columns: minmax(0, 1fr) auto; }
  .sp-main { flex-direction: column; gap: 0; grid-column: 1 / -1; }
  .sp-name { max-width: 100%; }
  .sp-meta { white-space: normal; }
  .sp-amt input { width: 120px; }
  .sp-fields { grid-template-columns: 1fr 1fr; }
}

/* [Billing and Plans] ==== Public sales site (twistedturf.com, body.ps; plan 17). Folded in from twistedturf/site.css on Oct 16, 2026 so the sales
   site, the CRM, the parent CRM and client websites load one stylesheet. Only layout lives here; colors, cards, buttons,
   inputs, tables, badges, hints and toasts are the shared classes above. ==== */
.ps { min-height: 100vh; padding-bottom: env(safe-area-inset-bottom, 0px); }
.ps { --ps-top-h: 60px; } /* height of the sticky .ps-top bar, so sticky table headers sit just under it (wraps to 2 rows under 640) */
@media (max-width: 640px) { .ps { --ps-top-h: 94px; } }
.ps-top { position: sticky; top: 0; z-index: 10; background: var(--ink); border-bottom: 3px solid var(--grass); padding-top: env(safe-area-inset-top, 0px); }
.ps-bar { max-width: 1120px; margin: 0 auto; display: flex; align-items: center; gap: 18px; padding: 10px max(18px, env(safe-area-inset-right, 0px)) 10px max(18px, env(safe-area-inset-left, 0px)); }
.ps-brand { color: var(--blue); font-weight: 750; font-size: 1.2rem; letter-spacing: -.02em; }
.ps-brand span { color: var(--grass); }
.ps-brand:hover { text-decoration: none; opacity: .9; }
.ps-nav { display: flex; gap: 4px; margin-left: auto; align-items: center; }
.ps-nav a:not(.btn) { color: #eee; padding: 8px 12px; border-radius: 8px; font-weight: 600; }
.ps-nav a:not(.btn):hover, .ps-nav a.on:not(.btn) { background: rgba(255,255,255,.08); color: #fff; text-decoration: none; }
.ps-nav .btn { margin-left: 6px; }
.ps-main { max-width: 1120px; margin: 0 auto; padding: 20px max(18px, env(safe-area-inset-right, 0px)) 40px max(18px, env(safe-area-inset-left, 0px)); }
.ps-test { background: var(--navy); color: #fff; border-radius: 12px; padding: 10px 14px; margin: 0 0 16px; display: flex; gap: 10px; align-items: center; }
.ps-test .badge { background: var(--orange); color: #fff; flex: none; }
.ps-hero { display: grid; grid-template-columns: 1fr 1.25fr; gap: 28px; align-items: center; padding: 20px 0 8px; }
.ps-hero h1 { font-size: 2.1rem; line-height: 1.15; margin: 0 0 12px; letter-spacing: -.02em; }
.ps-hero p { font-size: 1.05rem; margin: 0 0 6px; }
.ps-shot { width: 100%; height: auto; display: block; border-radius: 12px; border: 1px solid var(--line); background: #fff; }
.ps-phone { max-width: 260px; margin: 0 auto; border-radius: 22px; }
.ps-sec { margin: 28px 0 0; }
.ps-sec > h2, .ps-sec > h1 { font-size: 1.25rem; margin: 0 0 4px; } /* h1: the page heading on Pricing (one per page, for Google), same look as h2 */
.ps-sec > p.muted { margin: 0 0 14px; }
.ps-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.ps-grid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ps-grid.four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.ps-grid.five { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; }
.ps-grid.five .ps-seats { font-size: .8rem; gap: 2px 6px; }
.ps-grid.five .ps-price { font-size: 1.8rem; }
.ps-grid .card { margin: 0; }
.ps-feat h3 { margin: 0 0 6px; font-size: 1rem; display: flex; gap: 8px; align-items: center; }
.ps-feat p { margin: 0; }
.ps-feat ul, .ps-plan ul { margin: 8px 0 0; padding-left: 18px; }
.ps-feat li, .ps-plan li { margin: 3px 0; }
.ps-plan { display: flex; flex-direction: column; }
.ps-plan.ps-on {
  border: 1px solid var(--blue);
  padding: 18px 20px;
  box-shadow: 0 1px 2px rgba(17, 17, 17, .04), inset 0 0 0 2px rgba(30,144,255,.35);
  background: var(--card); color: var(--ink); font-weight: inherit; width: auto; text-align: left;
}
.ps-plan h3 { margin: 0; font-size: 1.1rem; display: flex; gap: 8px; align-items: center; justify-content: space-between; }
.ps-price { font-size: 2rem; font-weight: 750; margin: 8px 0 0; font-variant-numeric: tabular-nums; }
.ps-price small { font-size: .9rem; color: var(--muted); font-weight: 600; }
.ps-plan .row { margin-top: auto; padding-top: 14px; }
.ps-seats { display: grid; grid-template-columns: 1fr auto; gap: 2px 10px; margin: 10px 0 0; font-size: .9rem; }
.ps-seats b { font-variant-numeric: tabular-nums; }
.ps-shots { display: grid; grid-template-columns: 2fr 1fr; gap: 16px; align-items: start; }
.ps-shots figure { margin: 0; }
.ps-shots figcaption { color: var(--muted); font-size: .85rem; margin-top: 6px; }
.ps-foot { max-width: 1120px; margin: 0 auto; padding: 18px max(18px, env(safe-area-inset-right, 0px)) calc(24px + env(safe-area-inset-bottom, 0px)) max(18px, env(safe-area-inset-left, 0px)); color: var(--muted); font-size: .85rem; display: flex; gap: 16px; flex-wrap: wrap; border-top: 1px solid var(--line); }
.ps-foot a { color: var(--muted); }
.ps-foot a:hover { color: var(--ink); }
/* [Websites and Sales Site] Sign-up wizard */
.ps-wiz { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 16px; align-items: start; }
.ps-sum { position: sticky; top: 76px; }
.ps-steps { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 14px; }
.ps-steps button { height: 32px; min-height: 32px; }
.ps-step > h2:first-child { margin-top: 0; }
.ps-step[data-hide] { display: none; }
.ps-opts { display: grid; gap: 8px; }
.ps-opt { display: flex; gap: 10px; align-items: flex-start; border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; cursor: pointer; color: var(--ink); font-weight: 500; margin: 0; }
.ps-opt:hover { border-color: var(--blue); background: var(--paper); }
.ps-opt input[type=radio], .ps-opt input[type=checkbox] { width: auto; margin-top: 3px; flex: none; }
.ps-opt b { display: block; }
.ps-opt .muted { font-size: .82rem; }
.ps-opt:has(input:checked) { border-color: var(--blue); box-shadow: inset 0 0 0 1px var(--blue); }
.ps-opt.off { opacity: .5; }
.ps-opt .qty { width: 70px; margin-left: auto; flex: none; }
.ps-plans { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ps-addr { display: grid; grid-template-columns: 2fr 1fr 70px 100px; gap: 10px; }
.ps-lines { width: 100%; }
/* [Billing and Plans] .ps-lines one-line rules: see sales pricing block below */
.ps-lines td.num { text-align: right; }
.ps-lines tr.total td { font-weight: 750; border-bottom: 0; }
.ps-slug { display: flex; align-items: center; gap: 0; }
.ps-slug span { padding: 9px 10px; background: var(--paper); border: 1px solid #d5deea; border-right: 0; border-radius: 8px 0 0 8px; color: var(--muted); white-space: nowrap; }
.ps-slug input { border-radius: 0 8px 8px 0; min-width: 0; }
.ps-log { width: 100%; }
.ps-log details { border-bottom: 1px solid var(--line); }
.ps-log summary { display: flex; gap: 10px; align-items: center; padding: 10px 4px; cursor: pointer; list-style: none; white-space: nowrap; }
.ps-log summary::-webkit-details-marker { display: none; }
.ps-log summary:hover { background: var(--paper); }
.ps-log summary .n { width: 22px; color: var(--muted); font-variant-numeric: tabular-nums; flex: none; }
.ps-log summary .t { overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; }
.ps-log pre, .ps-log p { white-space: pre-wrap; margin: 0 0 10px 32px; font: inherit; color: var(--muted); font-size: .85rem; }
.ps-legal h2 { margin-top: 22px; }
.ps-legal > h1 { font-size: calc(.95rem * var(--fs-scale, 1)); margin: 0 0 10px; } /* Terms and Privacy page heading (one h1 per page), same look as the h2 it was */
/* [Websites and Sales Site] Home: feature spotlights and screenshot gallery */
.ps-spot { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.7fr); gap: 28px; align-items: center; margin: 22px 0 0; }
.ps-spot.flip .ps-spot-text { order: 2; }
.ps-spot-text h3 { font-size: 1.15rem; margin: 8px 0 6px; }
.ps-spot-text p { margin: 0; }
.ps-spot-pics { display: grid; grid-template-columns: minmax(0, 1fr) 150px; gap: 14px; align-items: end; }
.ps-spot-pics .ps-phone { max-width: 150px; border-radius: 18px; }
.ps-gal { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px 16px; }
.ps-gal.phones { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.ps-gal figure { margin: 0; }
.ps-gal a { display: block; border-radius: 10px; }
.ps-gal a:hover { text-decoration: none; }
.ps-gal img { width: 100%; height: auto; display: block; border-radius: 10px; border: 1px solid var(--line); background: #fff; transition: border-color .15s, box-shadow .15s, transform .15s; }
.ps-gal.phones img { border-radius: 16px; }
.ps-gal a:hover img, .ps-gal a:focus-visible img { border-color: var(--accent, var(--blue)); box-shadow: 0 6px 18px rgba(16,32,64,.12); transform: translateY(-2px); }
.ps-gal figcaption { color: var(--muted); font-size: .85rem; margin-top: 6px; }
.ps-gal-h { font-size: 1rem; margin: 22px 0 10px; }
@media (max-width: 900px) {
  .ps-hero, .ps-shots, .ps-wiz { grid-template-columns: 1fr; }
  .ps-grid, .ps-grid.four, .ps-grid.five { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ps-grid.five .ps-seats { font-size: .9rem; }
  .ps-sum { position: static; }
  .ps-spot, .ps-spot.flip { grid-template-columns: 1fr; gap: 12px; }
  .ps-spot.flip .ps-spot-text { order: 0; }
  .ps-gal { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ps-gal.phones { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .ps-bar { flex-wrap: wrap; gap: 6px 12px; }
  .ps-nav { margin-left: 0; width: 100%; overflow-x: auto; scrollbar-width: none; }
  .ps-nav::-webkit-scrollbar { display: none; }
  .ps-nav a:not(.btn) { padding: 6px 10px; white-space: nowrap; }
  .ps-nav .btn { margin-left: auto; flex: none; }
  .ps-hero h1 { font-size: 1.6rem; }
  .ps-grid, .ps-grid.two, .ps-grid.four, .ps-grid.five, .ps-plans { grid-template-columns: 1fr; }
  .ps-addr { grid-template-columns: 1fr 1fr; }
  .ps-addr > :first-child { grid-column: 1 / -1; }
  .ps-main .form-grid { grid-template-columns: 1fr; }
  .ps-main .form-grid .span-2 { grid-column: auto; }
  .ps-sum { order: 2; }
  .ps-spot-pics { grid-template-columns: minmax(0, 1fr) 110px; gap: 10px; }
  .ps-spot-pics .ps-phone { max-width: 110px; border-radius: 14px; }
  .ps-gal { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 10px; }
  .ps-gal.phones { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ps-gal figcaption { font-size: .8rem; }
}
/* [Billing and Plans] Promotions and bonus lines (Oct 15, 2026). List price struck through; promo price beside it. */
.ps-price s { color: var(--muted); font-weight: 600; font-size: .6em; text-decoration-thickness: 2px; }
.ps-opt b s { color: var(--muted); font-weight: 500; }
.ps-promo { margin: 4px 0 0; font-size: .82rem; color: var(--ink); }
.ps-promo .badge { margin-right: 4px; }
.ps-bonus-h { margin: 10px 0 0; font-size: .72rem; font-weight: 650; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.ps-bonus { margin-top: 4px !important; font-size: .85rem; }
.ps-promo-in { display: flex; gap: 8px; }
.ps-promo-in input { flex: 1; min-width: 0; text-transform: uppercase; }
.ps-promo-in button { flex: none; }

/* [Websites and Sales Site] Motto, Built in, EPA spotlight and Integrations (Oct 15, 2026) */
.ps-motto { letter-spacing: -.01em; }
/* [Websites and Sales Site] Home: the motto on its own full-width line above the two-column hero (parent Website > Home, first Custom HTML part).
   Big on computers, never smaller than the lead paragraph there; assets/js/fit-text.js keeps it on one line on phones. */
.ps-motto-wide { font-size: clamp(1.7rem, 3.3vw, 2.7rem); line-height: 1.15; margin: 18px 0 2px; letter-spacing: -.02em; }
.ps-motto-wide + .ps-hero { padding-top: 8px; }
.ps-lead { font-size: 1.15rem; font-weight: 600; margin: 0 0 6px; }
.ps-motto-lead { font-size: 1.35rem; font-weight: 700; margin: 0 0 4px; color: var(--pal-green); }
/* [Websites and Sales Site] Sales site standouts (What Sets Us Apart): the same spotlight, lifted onto a card with a green edge and bigger shots. */
.ps-star { background: #fff; border: 1px solid var(--line); border-left: 4px solid var(--grass); border-radius: 16px; padding: 22px; box-shadow: 0 10px 28px rgba(16,32,64,.08); }
.ps-star .ps-spot-text h3 { font-size: 1.4rem; letter-spacing: -.01em; }
.ps-star.flip { grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr); } /* the shots keep the wide column when the text moves right */
@media (max-width: 900px) { .ps-star.flip { grid-template-columns: 1fr; } }
.ps-star .ps-spot-pics { grid-template-columns: minmax(0, 1fr) 180px; }
.ps-star .ps-spot-pics .ps-phone { max-width: 180px; }
.ps-free { margin: 14px 0 0; border-left: 4px solid var(--grass); }
.ps-star-more { margin: 22px 0 0; }
.ps-star-card { border-left: 4px solid var(--grass); }
@media (max-width: 700px) {
  .ps-star { padding: 14px; }
  .ps-star .ps-spot-text h3 { font-size: 1.2rem; }
  .ps-star .ps-spot-pics { grid-template-columns: minmax(0, 1fr) 110px; }
  .ps-star .ps-spot-pics .ps-phone { max-width: 110px; }
}
.ps-epa { margin: 22px 0 0; }
.ps-epa h3 { font-size: 1.15rem; margin: 8px 0 6px; }
.ps-epa p { margin: 0; }
.ps-int { margin: 0 0 12px; padding-top: 14px; padding-bottom: 6px; }
.ps-int h3 { margin: 0 0 6px; font-size: 1rem; }
.ps-int h3 .muted { font-weight: 400; font-size: .9rem; margin-left: 6px; }
.ps-int-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.ps-int-table td { padding: var(--t-pad, 8px 6px); border-top: 1px solid var(--t-line, var(--line)); vertical-align: middle; overflow: hidden; text-overflow: ellipsis; }
.ps-int-table tr:first-child td { border-top: 0; }
.ps-int-name { width: 210px; }
.ps-int-state { width: 120px; }
.ps-int-plan { width: 150px; }
@media (max-width: 700px) {
  .ps-int-table, .ps-int-table tbody { display: block; }
  .ps-int-table tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name state" "about about" "plan plan"; gap: 2px 8px; padding: 9px 0; border-top: 1px solid var(--t-line, var(--line)); }
  .ps-int-table tr:first-child { border-top: 0; }
  .ps-int-table td { display: block; width: auto; padding: 0; border: 0 !important; }
  .ps-int-name { grid-area: name; } .ps-int-state { grid-area: state; } .ps-int-about { grid-area: about; } .ps-int-plan { grid-area: plan; font-size: .85rem; }
  .ps-int h3 .muted { display: block; margin: 2px 0 0; }
  .ps-motto-lead { font-size: 1.15rem; }
}
@media (max-width: 640px) { .ps-nav .ps-nav-wide { display: none; } } /* keeps Sign up in view on phones; Integrations is on the page below */
.ps-shot-link { display: block; border-radius: 12px; }
.ps-shot-link:hover { text-decoration: none; }
.ps-shot-link .ps-shot { transition: border-color .15s, box-shadow .15s; }
.ps-shot-link:hover .ps-shot, .ps-shot-link:focus-visible .ps-shot { border-color: var(--accent, var(--blue)); box-shadow: 0 6px 18px rgba(16,32,64,.12); }

/* [Billing and Plans] Sales site pricing + signup: short one-line UI copy, feature matrix. Oct 17 2026. */
.ps-sec table.phone-sheet {
  width: 100%; max-width: 100%; table-layout: auto;
}
@media (min-width: 801px) { .ps-sec table.phone-sheet { border: 1px solid var(--card-edge, var(--line)); border-radius: 12px; border-collapse: separate; border-spacing: 0; overflow: clip; } } /* clip, not hidden: hidden made the table a scroller and pushed the sticky header row down. Pricing Add-Ons: the same edge as a card on both sides */
/* [Billing and Plans] Name and price shrink-wrap on one line (no ellipsis); blurb takes the leftover and may … */
.ps-sec table.phone-sheet td:first-child {
  width: 1%; white-space: nowrap; vertical-align: middle;
}
.ps-sec table.phone-sheet td.num {
  width: 1%; white-space: nowrap; vertical-align: middle;
}
.ps-sec table.phone-sheet td.muted {
  min-width: 0; max-width: 0; width: auto; /* leftover column in a 100% table */
}
.ps-sec table.phone-sheet td.num .one-line,
.ps-sec table.phone-sheet td.muted .one-line {
  display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}
.ps-addon-name, .ps-addon-name.one-line {
  display: inline-flex; align-items: center; gap: 6px; max-width: none;
  white-space: nowrap; overflow: visible;
}
/* [Billing and Plans] Phones (phone-sheet cards): the desktop column widths above (width 1% / max-width 0) must not apply, or the price and
   blurb shrink to a sliver (Travis, Oct 19 2026 8:00 AM). Price stays one line; the blurb wraps. */
@media (max-width: 800px) {
  .ps-sec table.phone-sheet td, .ps-sec table.phone-sheet td:first-child, .ps-sec table.phone-sheet td.num, .ps-sec table.phone-sheet td.muted {
    width: 100%; max-width: 100%; min-width: 0; white-space: normal;
  }
  .ps-sec table.phone-sheet td.num .one-line { white-space: nowrap; overflow: visible; }
  .ps-sec table.phone-sheet td.muted .one-line { white-space: normal; overflow: visible; text-overflow: clip; }
  .ps-sec table.phone-sheet td.muted { grid-template-columns: minmax(0, 1fr); } /* the description gets the card's full width; it is a sentence, so it may wrap (class desc) */
  .ps-sec table.phone-sheet td.muted::before { content: none; }
}
/* [Customers and Properties] Price tiers under an add-on's blurb (Data Move by property count, Task 172): one short line each, never wraps. */
.ps-tiers { list-style: none; margin: 4px 0 0; padding: 0; }
.ps-tiers li { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-addon-name b { white-space: nowrap; overflow: visible; }
.ps-addon-name .badge { flex: none; white-space: nowrap; }
/* [Shared] Compare matrix is too wide under ~900; use the phone picker sooner so 820 never scrolls sideways. */
@media (max-width: 900px) {
  .ps-compare-desk { display: none; }
  .ps-compare-phone { display: block; }
}

.ps-bar, .ps-main, .ps-foot { max-width: 1280px; }
.ps-price-top { margin-top: 0; }
.card .ps-flush, .ps-flush { margin-top: 0; } /* sales site: a card's first heading */
.card .ps-sub, .ps-sub { margin: 10px 0 0; }
.ps-plans-wide { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 18px; align-items: stretch; }
.ps-plans-wide .ps-plan { min-width: 0; }
.ps-plans-wide .ps-plan > h3,
.ps-plans-wide .ps-plan > .ps-price,
.ps-plans-wide .ps-plan > p.muted.hint,
.ps-plans-wide .ps-plan > p.muted.one-line { min-height: 1.25em; }
.ps-plans-wide .ps-plan > p.muted.one-line { white-space: nowrap; overflow: hidden; text-overflow: clip; }
.ps-plans-wide .ps-plan > .ps-promo { min-height: 1.4em; margin: 4px 0 0; }
.ps-plans-wide .ps-plan:not(:has(.ps-promo)) > .ps-price { margin-bottom: 0; }

.ps-plans-wide .ps-price { font-size: 1.85rem; }
.ps-plans-wide .ps-promo { min-height: 1.35em; margin: 4px 0 0; font-size: .82rem; line-height: 1.35; }
.ps-plans-wide .ps-plan > h3 { min-height: 1.35em; line-height: 1.35; }
.ps-plans-wide .ps-seats { font-size: .88rem; gap: 4px 8px; }
.ps-seats > span, .ps-seats > b { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.ps-seats > b { overflow: visible; text-overflow: clip; }
.ps-plan { display: flex; flex-direction: column; }
.ps-plan.ps-on {
  border: 1px solid var(--blue);
  padding: 18px 20px;
  box-shadow: 0 1px 2px rgba(17, 17, 17, .04), inset 0 0 0 2px rgba(30,144,255,.35);
  background: var(--card); color: var(--ink); font-weight: inherit; width: auto; text-align: left;
}
.ps-plan h3 { margin: 0; font-size: 1.1rem; font-weight: 700; }
.ps-plan > p.muted { margin: 6px 0 0; }
.ps-plan > p.muted.hint { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-plan ul { margin: 10px 0 0; padding: 0; list-style: none; min-width: 0; }
.ps-plan ul li {
  margin: 0; padding: 3px 0; font-size: .92rem; font-weight: 500; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: clip; max-width: 100%;
}
.ps-plan ul li::before { content: "✓ "; color: var(--grass); font-weight: 700; }
.ps-plan .ps-bonus-line { margin-top: 8px; font-size: .82rem; }
.ps-plan .row { margin-top: auto; padding-top: 14px; }
.ps-compare { margin-top: 28px; }
.ps-compare > h2 { margin-top: 0; }
.ps-compare-desk { overflow: visible; }
.ps-compare-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.ps-compare-table th, .ps-compare-table td {
  padding: var(--t-pad, 8px 10px); border-top: 1px solid var(--t-line, var(--line)); vertical-align: middle; text-align: center;
}
.ps-compare-table th[scope=row], .ps-compare-table thead th:first-child { text-align: left; }
.ps-compare-table thead th {
  position: sticky; top: var(--ps-top-h, 0); z-index: 2; background: var(--card); border-top: 0;
  color: var(--ink); font-weight: 700; font-size: .9rem; padding-top: 10px; padding-bottom: 10px;
  box-shadow: inset 0 -1px 0 var(--line);
}
.ps-compare-table thead th .muted { display: block; font-weight: 600; font-size: .78rem; margin-top: 2px; }
.ps-compare-table thead th.ps-on, .ps-compare-table td.ps-on { background: rgba(30,144,255,.06); }
.ps-compare-table thead th.ps-on { background: linear-gradient(rgba(30,144,255,.06), rgba(30,144,255,.06)), var(--card); } /* solid while stuck, rows don't show through */
/* [Billing and Plans] Pricing: the Add-Ons header row sticks under the site bar while its table scrolls by (PC; phones turn rows into cards). */
@media (min-width: 801px) {
  .ps-sec table.phone-sheet tr:first-child th { position: sticky; top: var(--ps-top-h, 0); z-index: 2; background: var(--card); box-shadow: inset 0 -1px 0 var(--line); }
}
.ps-compare-table th[scope=row] { font-weight: 500; }
.ps-compare-table thead th:first-child { width: 16.5rem; } /* fixed layout sizes columns from the first row: room for the longest feature name (par_compare) */
.ps-compare-group th {
  text-align: left; font-size: .75rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); background: var(--paper); font-weight: 700; padding-top: 10px; padding-bottom: 6px;
  border-top: 1px solid var(--t-line, var(--line));
}
.ps-check { color: var(--grass); font-weight: 800; font-size: 1.05rem; }
.ps-dash { opacity: .45; }
.ps-compare-phone { display: none; }
.ps-compare-pick { display: block; font-weight: 600; margin: 0 0 6px; }
.ps-compare-phone #ps-plan-pick { position: sticky; top: var(--ps-top-h, 0); z-index: 2; } /* phones: the Plan picker stays in view while its pane scrolls, then leaves with the section */
.ps-compare-phone select { width: 100%; margin: 0 0 12px; }
.ps-compare-pane .row { margin-top: 12px; }
.ps-compare-pane ul { margin: 8px 0 0; padding: 0; list-style: none; }
.ps-compare-pane li {
  margin: 0; padding: 4px 0; font-weight: 500; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: clip;
}
.ps-compare-pane li::before { content: "✓ "; color: var(--grass); font-weight: 700; }
/* [Billing and Plans] Plan Studio on Sign-ups > Plans (plans/plan-studio.md): live plan cards, the Add-Ons list and one slide-over editor. */
.pgs-preview [id^=plan-] { cursor: pointer; }
.pgs-preview .pgs-editing { box-shadow: 0 0 0 2px var(--blue); }
.pgs-preview [hidden] { display: none; }
/* [Billing and Plans] Plan Studio preview sits beside the menu, narrower than the sales site: 2 cards a row under 1000px so no feature line is cut (Oct 20 2026). */
.pgs-preview { container-type: inline-size; }
@container (min-width: 600px) and (max-width: 1000px) {
  .pgs-preview .ps-plans-wide[class*=ps-plans-n] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pgs-preview .ps-slim { grid-template-columns: minmax(0, 1fr) auto auto; }
  .pgs-preview .ps-slim-lines { grid-column: 1 / -1; grid-row: 2; }
}
/* [Billing and Plans] Add-On status pills stay on one line. */
.pgs-pills { white-space: nowrap; }
.pgs-pills .badge + .badge { margin-left: 4px; }
.pgs-addons .pgs-row { cursor: pointer; }
.pgs-addons .pgs-row.pgs-editing td { background: var(--paper); }
.pgs-addons td .badge + .badge { margin-left: 4px; }
.pgs-more[hidden] { display: none; }
.pgs-panel { position: fixed; z-index: 60; top: 0; right: 0; bottom: 0; width: min(440px, 100%); margin: 0; border-radius: 0; overflow-y: auto; box-shadow: -16px 0 40px rgba(11, 42, 69, .16); padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px)); }
.pgs-panel[hidden] { display: none; }
.pgs-panel-top { justify-content: space-between; align-items: center; flex-wrap: nowrap; margin: 0 0 12px; }
.pgs-panel-top h2 { margin: 0; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pgs-line { display: flex; gap: 6px; align-items: center; margin-top: 6px; }
.pgs-line input { flex: 1; min-width: 0; }
.pgs-incl { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 12px; }
@media (max-width: 800px) {
  .pgs-panel { width: 100%; padding-top: max(24px, env(safe-area-inset-top, 0px)); }
  .pgs-panel .form-grid { grid-template-columns: 1fr; }
}
/* [Billing and Plans] Compare grid on Sign-ups > Plans (plans/plan-studio.md): the public Compare table, editable. Phones show one plan (Plan picker). */
.pg-table .pg-label, .pg-table .pg-gname, .pg-table .pg-word { width: 100%; min-width: 0; }
.pg-table .pg-word { text-align: center; }
.card > table.pg-table tbody th { position: static; } /* only the plan header sticks (the card table rule makes every th sticky) */
.pg-table input[hidden] { display: none; }
.pg-table .pg-act { width: 8rem; text-align: right; white-space: nowrap; }
.pg-table .pg-act .bm-move { justify-content: flex-end; }
.pg-table .pg-detail td, .pg-table .pg-add td { text-align: left; }
.pg-table .pg-detail td { background: var(--paper); }
.pg-lock { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }
.pg-phone, button.quiet.pg-phone-move { display: none; }
@media (max-width: 800px) {
  .pg-phone { display: block; }
  .pg-phone select { width: 100%; margin: 0 0 12px; }
  .pg-table { table-layout: auto; }
  .pg-table .pg-off { display: none; }
  .pg-table thead th:first-child, .pg-table th[scope=row] { width: 100%; }
  .pg-table [data-col] { width: 5.5rem; min-width: 5.5rem; }
  .pg-table .pg-act { min-width: 0; width: 3rem; }
  .pg-table tr[data-row] .pg-act :is([data-pg-up], [data-pg-down]) { display: none; }
  .pg-detail button.quiet.pg-phone-move { display: inline-flex; }
  .pg-table th, .pg-table td { padding-left: 4px; padding-right: 4px; }
  .pg-lock.form-grid, .pg-table .pg-detail .form-grid { grid-template-columns: 1fr; }
}
/* [Shared] Signup opts: one short line each (we control the words). */
.ps-opt > span { min-width: 0; flex: 1; }
.ps-opt b.one-line, .ps-opt .muted.one-line {
  display: block; white-space: nowrap; overflow: hidden; text-overflow: clip; max-width: 100%;
}
.ps-opt .muted.one-line { font-size: .82rem; }
.ps-lines { width: 100%; table-layout: fixed; }
.ps-lines td { padding: var(--t-pad, 7px 4px); white-space: nowrap; overflow: hidden; text-overflow: clip; }
.ps-lines td:first-child { width: 58%; }
.ps-lines td.num { width: 42%; text-align: right; font-variant-numeric: tabular-nums; }
.ps-lines tr.total td { font-weight: 750; border-bottom: 0; }
@media (max-width: 1100px) {
  .ps-plans-wide { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 800px) {
  .ps-plans-wide { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .ps-compare-desk { display: none; }
  .ps-compare-phone { display: block; }
}
@media (max-width: 520px) {
  .ps-plans-wide { grid-template-columns: minmax(0, 1fr); }
}
/* [Billing and Plans] Plan cards from data (includes/parent_site.php pt_plan_cards_html): 4 cards + the slim Enterprise row, badges. */
.ps-plans-wide.ps-plans-n4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.ps-plans-wide.ps-plans-n3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ps-plan > h3 { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }
.ps-plan > h3 .one-line { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: clip; }
.ps-plan > h3 .badge { flex: none; white-space: nowrap; }
.ps-plan.ps-badged.ps-on { transform: translateY(-4px); }
.ps-slim { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 2.6fr) auto auto; gap: 8px 18px; align-items: center; margin: 18px 0 0; }
.ps-slim h3 { margin: 0; font-size: 1.1rem; }
.ps-slim-name { min-width: 0; }
.ps-slim-name .one-line, .ps-slim-lines .one-line { display: block; white-space: nowrap; overflow: hidden; text-overflow: clip; }
.ps-slim-lines { display: flex; flex-wrap: wrap; gap: 4px 14px; min-width: 0; font-size: .92rem; font-weight: 500; }
.ps-slim-lines .one-line::before { content: "✓ "; color: var(--grass); font-weight: 700; }
.ps-slim .ps-price { margin: 0; font-size: 1.5rem; white-space: nowrap; }
.ps-slim-go .btn { white-space: nowrap; }
.ps-plans-home > h2 { margin-top: 0; }
.ps-plans-home .ps-free { margin: 14px 0 18px; }
.ps-plans-go { margin-top: 18px; }
@media (max-width: 1100px) {
  .ps-plans-wide.ps-plans-n4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ps-slim { grid-template-columns: minmax(0, 1fr) auto auto; }
  .ps-slim-lines { grid-column: 1 / -1; grid-row: 2; }
}
@media (max-width: 800px) {
  .ps-plans-wide.ps-plans-n3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 520px) {
  .ps-plans-wide.ps-plans-n4, .ps-plans-wide.ps-plans-n3 { grid-template-columns: minmax(0, 1fr); }
  .ps-plan.ps-badged.ps-on { transform: none; }
  .ps-slim { grid-template-columns: minmax(0, 1fr) auto; }
  .ps-slim-go { grid-column: 1 / -1; }
  .ps-slim-go .btn { width: 100%; text-align: center; }
  .ps-slim-name { grid-column: 1 / -1; } /* Pricing (Oct 20 2026): the plan's one-line summary gets the full row, so Enterprise's line is never cut at 375 */
}

/* [Customers and Properties] Customer contract (contract.php): one-line rows with an amount on the right. */
.mc-amt { flex: none; font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums; min-width: 86px; text-align: right; }
.mc-sub { flex: none; color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; font-size: .9rem; min-width: 70px; text-align: right; }
.set-row .badge.mc-keep { display: inline-flex; }
.set-row.mc-total { background: var(--paper); }
.set-row.mc-total b.mc-amt { font-size: 1.05rem; }
.set-savebar.mc-bar > .muted { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.set-savebar.mc-bar ~ section.set-list > h2 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.set-row.mc-line .set-txt b { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 800px) {
  .mc-sub { display: none; }
  .mc-amt { min-width: 0; }
}

/* [Route] Add item (includes/add_item.php, assets/js/add-item.js): the one shared picker for Route, Base, Estimate and Contract. */
.ai-open { flex: none; white-space: nowrap; width: auto; }
.sp .sp-ai { margin-top: 8px; }
.ai-bar { display: flex; gap: 10px; justify-content: flex-end; padding: 10px 18px; border-top: 1px solid var(--line); }
dialog.ai-sheet { width: min(600px, calc(100% - 20px)); max-height: 88vh; padding: 0; flex-direction: column; overflow: hidden; border: 0; border-radius: 16px; box-shadow: 0 20px 50px rgba(16, 24, 40, .3); }
dialog.ai-sheet[open] { display: flex; }
.ai-head { display: flex; align-items: baseline; gap: 10px; padding: 14px 16px 8px; min-width: 0; }
.ai-head h2 { margin: 0; flex: none; font-size: 1.15rem; }
.ai-head .muted { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: .9rem; }
/* .ai-x: shared X close (Tracker 880) */
#ai-s1, #ai-s2 { flex: 1; min-height: 0; overflow: auto; padding: 0 16px 8px; }
#ai-s1[hidden], #ai-s2[hidden] { display: none; }
.ai-search { display: block; margin: 0 0 8px; }
.ai-search input { width: 100%; }
.tabs.ai-tabs { margin: 0 0 8px; gap: 6px; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
.tabs.ai-tabs a { padding: 5px 12px; font-size: .88rem; white-space: nowrap; flex: none; }
dialog.ai-sheet .set-list.ai-list { border: 1px solid var(--line); border-radius: 12px; box-shadow: none; margin: 0 0 10px; overflow: hidden; padding: 0; }
.ai-list .set-row { min-height: 48px; padding: 6px 10px; gap: 8px; }
.ai-list .set-row:first-child { border-top: 0; }
.ai-list .set-txt { min-width: 0; }
.ai-list .set-txt b, .ai-list .set-txt .muted { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ai-row { cursor: pointer; }
.ai-row.on { background: color-mix(in srgb, var(--grass) 14%, #fff); }
.ai-row .set-txt b { flex: 0 1 auto; }
.ai-row .set-txt .muted { flex: none; font-variant-numeric: tabular-nums; }
#ai-review .set-txt .muted { flex: 0 1 auto; }
.ai-star { flex: none; width: 30px; height: 30px; min-height: 0; padding: 0; border: 0; background: none; box-shadow: none; color: var(--muted); font-size: 1.15rem; line-height: 1; }
.ai-star.on { color: #d79b00; }
.ai-star[disabled] { cursor: default; opacity: 1; }
.ai-add { flex: none; width: 36px; height: 36px; min-height: 0; padding: 0; border-radius: 999px; font-size: 1.3rem; line-height: 1; }
.ai-step { flex: none; display: inline-flex; align-items: center; gap: 2px; }
.ai-step button { width: 30px; height: 32px; min-height: 0; padding: 0; font-size: 1.1rem; }
.ai-step input { width: 56px; height: 32px; padding: 0 4px; margin: 0; text-align: center; font-variant-numeric: tabular-nums; }
.ai-h3 { font-size: .95rem; margin: 4px 0 6px; }
#ai-bill label.set-row { cursor: pointer; margin: 0; color: var(--ink); font-size: 1rem; font-weight: 400; }
#ai-bill input, .ai-chk input { flex: none; width: 18px; height: 18px; margin: 0; }
#ai-bill .ai-off { opacity: .5; }
.ai-more summary { cursor: pointer; font-weight: 650; margin: 2px 0 8px; color: var(--navy); }
.ai-adv-row select { flex: none; width: 104px; padding: 5px 6px; margin: 0; }
.ai-adv-row select.ai-wide { flex: 1; width: auto; min-width: 0; }
.ai-adv-row input[type=number] { flex: none; width: 90px; padding: 5px 6px; margin: 0; }
.ai-adv-row .set-txt { flex: 1; }
label.ai-chk { cursor: pointer; margin: 0; color: var(--ink); font-size: 1rem; font-weight: 400; }
.ai-foot { display: flex; align-items: center; gap: 10px; padding: 10px 16px; border-top: 1px solid var(--line); background: var(--paper); }
.ai-foot .ai-sum { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.ai-foot button { flex: none; white-space: nowrap; width: auto; }
.ai-err { color: var(--danger, #b42318); margin: 0 0 8px; }
.badge.ai-flag { white-space: nowrap; }
@media (max-width: 800px) {
  dialog.ai-sheet { width: 100%; max-width: 100%; height: 100dvh; max-height: 100dvh; margin: 0; border-radius: 0; }
  #ai-s1, #ai-s2 { padding: 0 10px 8px; }
  .ai-head { padding: 12px 10px 6px; }
  .ai-foot { padding: 10px; }
  .ai-list .ai-row > .ico { display: none; }
  .ai-adv-row input[type=number] { width: 76px; }
  .ai-adv-row select { width: 88px; }
}
.ai-bar { align-items: center; }
.ai-bar .ai-bar-note { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* [Billing and Plans] Invoice Templates (invoices.php?view=templates, plans/invoice-templates-plan.md) */
.itpl-list table { width: 100%; border-collapse: collapse; }
.itpl-list th, .itpl-list td { padding: var(--t-pad, 9px 14px); text-align: left; white-space: nowrap; border-bottom: 1px solid var(--t-line, var(--line)); }
.itpl-list tr:last-child td { border-bottom: 0; }
.itpl-list tr.on td { background: var(--paper); }
.itpl-list td.n { text-align: right; width: 1%; }
.itpl-list td.itpl-use { max-width: 320px; overflow: hidden; text-overflow: ellipsis; }
.itpl-list form { margin: 0; }
.itpl-mini { min-height: 0; padding: 3px 12px; font-size: .85rem; }
.itpl-dot { display: inline-block; width: 12px; height: 12px; border-radius: 50%; margin-right: 6px; vertical-align: -1px; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .15); }
.itpl-ed { display: grid; grid-template-columns: minmax(0, 1fr) calc(8.5in * .42 + 42px); gap: 16px; align-items: start; }
.itpl-ed > .card { margin-bottom: 16px; min-width: 0; }
.itpl-prev { position: sticky; top: 12px; }
.itpl-prev-top { display: flex; justify-content: space-between; align-items: center; gap: 10px; white-space: nowrap; }
.itpl-prev-top h2 { margin: 0; }
.itpl-thumb { --s: .42; width: calc(8.5in * var(--s)); height: calc(11in * var(--s)); overflow: hidden; border: 1px solid var(--line); border-radius: 6px; background: #fff; flex: none; }
.itpl-thumb > .itpl { transform: scale(var(--s)); transform-origin: 0 0; }
.itpl-thumb.itpl-mini-t { --s: .068; border-radius: 3px; display: block; }
.itpl-kv { width: 100%; border-collapse: collapse; table-layout: fixed; }
.itpl-kv th, .itpl-kv td { padding: var(--t-pad, 10px 8px); border-bottom: 1px solid var(--t-line, var(--line)); text-align: left; vertical-align: top; }
.itpl-kv th { width: 100px; padding-top: 16px; color: var(--muted); font-size: .85rem; font-weight: 650; white-space: nowrap; }
.itpl-kv td { min-width: 0; }
.itpl-kv input:not([type]), .itpl-kv select, .itpl-kv textarea { width: 100%; max-width: 520px; }
/* [Shared] Design / Color / Show: one row always. Shrink Design thumbs a little; when the row is still too wide (phones), scroll sideways inside the row, never the page. */
.itpl-dzs, .itpl-sws, .itpl-cks { display: flex; flex-wrap: nowrap; gap: 6px; max-width: 100%; min-width: 0; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; }
.itpl-dzs::-webkit-scrollbar, .itpl-sws::-webkit-scrollbar, .itpl-cks::-webkit-scrollbar { display: none; }
.itpl-cks { gap: 6px 14px; }
.itpl-cks > label { flex: none; white-space: nowrap; }
.itpl-dzc { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 4px; border: 2px solid transparent; border-radius: 8px; cursor: pointer; font-size: .78rem; flex: none; white-space: nowrap; }
.itpl-dzc { position: relative; }
.itpl-dzc input, .itpl-sw input[type=radio] { position: absolute; left: 0; top: 0; width: 1px; height: 1px; min-height: 0; margin: 0; padding: 0; opacity: 0; pointer-events: none; }
.itpl-dzc:has(input:checked) { border-color: var(--blue); background: var(--paper); }
.itpl-sw { position: relative; display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px 4px 5px; border: 1px solid var(--line); border-radius: 99px; font-size: .82rem; cursor: pointer; white-space: nowrap; flex: none; }
.itpl-sw i { width: 18px; height: 18px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .15); }
.itpl-sw input[type=color] { width: 22px; height: 22px; padding: 0; border: 0; border-radius: 50%; background: none; cursor: pointer; }
.itpl-sw:has(input[type=radio]:checked) { border-color: var(--ink); box-shadow: 0 0 0 1px var(--ink); }
.itpl-mf-pop { border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; margin: 6px 0 8px; background: #fff; box-shadow: 0 6px 20px rgba(0, 0, 0, .08); max-width: 520px; }
.itpl-mf-find { width: 100%; margin-bottom: 8px; }
.itpl-mf-g { display: flex; gap: 10px; align-items: baseline; padding: 4px 0; border-top: 1px solid var(--line); }
.itpl-mf-g:first-of-type { border-top: 0; }
.itpl-mf-g > b { width: 72px; flex: none; font-size: .75rem; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.itpl-mf-chips { display: flex; flex-wrap: wrap; gap: 5px; }
.itpl-chip { background: var(--paper); color: var(--ink); border: 0; border-radius: 99px; padding: 3px 10px; font-size: .8rem; font-weight: 600; min-height: 0; }
.itpl-chip:hover { background: var(--blue); color: #fff; }
.itpl-mf textarea { margin-top: 6px; font-family: ui-monospace, Menlo, monospace; font-size: .85rem; }
.itpl-bad { color: var(--red); }
.itpl-as { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; font-size: .9rem; }
.itpl-as select { width: auto; }
@media (max-width: 1100px) { .itpl-ed { grid-template-columns: 1fr; } .itpl-prev { position: static; } }
@media (max-width: 800px) {
  .itpl-list .itpl-use, .itpl-list .itpl-dz, .itpl-list .itpl-cn { display: none; }
  .itpl-list.slim-list > table td:nth-child(4) { display: block; flex: none; }
  .itpl-list.slim-list > table td:first-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .itpl-list th, .itpl-list td { padding: 9px 10px; }
  .itpl-kv th, .itpl-kv td { display: block; width: auto; border: 0; padding: 4px 0; }
  .itpl-kv tr { display: block; border-bottom: 1px solid var(--line); padding: 8px 0; }
  .itpl-thumb.itpl-big { --s: .36; }
  .itpl-mf-g { flex-direction: column; gap: 4px; }
  .itpl-mf-g > b { width: auto; }
}
/* [Estimates] Estimates list on wider screens: one line per row (Travis: nothing wraps). The Stage badge and Number stay whole, a long
   customer or salesperson name ends in an ellipsis, and narrower screens drop the least-needed columns first (Viewed,
   Weighted and Sent, then Prob., then Salesperson); checked in the Default and LMN Styles. Phones (800px and less) keep the stacked cards.
   Only the Estimates list (the one bulk-send table with a Prob. column); Invoices keeps its own layout. */
@media (min-width: 801px) {
  form[data-bulk-send] > table.phone-sheet:has(td[data-label="Prob."]) th, form[data-bulk-send] > table.phone-sheet:has(td[data-label="Prob."]) td { white-space: nowrap; padding-left: 7px; padding-right: 7px; }
  form[data-bulk-send] > table.phone-sheet:has(td[data-label="Prob."]) td[data-label="Customer"], form[data-bulk-send] > table.phone-sheet:has(td[data-label="Prob."]) td[data-label="Salesperson"] { max-width: 170px; overflow: hidden; text-overflow: ellipsis; }
}
/* [Customers and Properties] From 1001px the Customer name really gets its 170px before "…" (the house 13vw cap won over the rule above, so at 1024 a
   name was cut while other columns had room: rules check, Oct 18 2026). Below that the table is tight and keeps the old caps (801-900: 80px). */
@media (min-width: 1001px) {
  body:not(.ps):not(.site) main .card form[data-bulk-send] > table.phone-sheet:has(td[data-label="Prob."]) td[data-label="Customer"] { max-width: 170px; }
  body:not(.ps):not(.site) main .card form[data-bulk-send] > table.phone-sheet:has(td[data-label="Prob."]) td[data-label="Customer"] > a:first-child { max-width: 100%; }
}
@media (min-width: 801px) and (max-width: 1180px) {
  form[data-bulk-send] > table.phone-sheet:has(td[data-label="Prob."]) tr > :nth-child(7), form[data-bulk-send] > table.phone-sheet:has(td[data-label="Prob."]) tr > :nth-child(8), form[data-bulk-send] > table.phone-sheet:has(td[data-label="Prob."]) tr > :nth-child(9) { display: none; }
}
@media (min-width: 801px) and (max-width: 1024px) {
  form[data-bulk-send] > table.phone-sheet:has(td[data-label="Prob."]) tr > :nth-child(6) { display: none; }
}
@media (min-width: 801px) and (max-width: 900px) {
  form[data-bulk-send] > table.phone-sheet:has(td[data-label="Prob."]) tr > :nth-child(10) { display: none; }
  form[data-bulk-send] > table.phone-sheet:has(td[data-label="Prob."]) td[data-label="Customer"] { max-width: 80px; }
}
/* [Shared] Control rows never wrap (Travis's rule, Oct 16, 2026): they shrink a little and step down by width instead.
   Phone list bar: the search box keeps its own line, the filter pills and the count/page-size share the next line
   (pills slide sideways as before); a bar with no filters puts the count beside the search box. Filters that carry
   their own Show/Find button keep their own wrapping line (that button must never scroll out of sight). */
@media (max-width: 800px) {
  .lb-filters:not(:has(> button[type="submit"])) { flex: 1 1 0; }
  .lb-filters:not(:has(> button[type="submit"])) ~ .lb-tail { flex: none; max-width: 50%; margin-left: auto; }
  .lb:not(:has(> .lb-filters:not(.is-empty))) .list-search { flex: 1 1 0; min-width: 0; }
  .lb:not(:has(> .lb-filters:not(.is-empty))) .lb-tail { flex: none; max-width: 50%; }
  /* Filters with their own Show button: the count/page size moves up beside the search box instead of taking a line of its own. */
  .lb:has(> .lb-filters > button[type="submit"]) .list-search { flex: 1 1 0; min-width: 0; }
  .lb:has(> .lb-filters > button[type="submit"]) .lb-tail { order: 1; flex: none; max-width: 50%; }
  .lb:has(> .lb-filters > button[type="submit"]) .lb-filters { order: 2; }
  .phone-list .list-bar.lb { display: flex; } /* was a one-column grid (line 1164): same stacked rows, but the count can share a line */
  .lb-tail { white-space: nowrap; }
}
/* [Billing and Plans] Bulk action rows under a list and the action row on an invoice (div.row.no-print): one line; when the buttons do not
   fit they step down a size and the row slides sideways like the filter pills. */
.row.no-print { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.row.no-print::-webkit-scrollbar { display: none; }
.row.no-print > * { flex: none; }
@media (max-width: 800px) {
  .row.no-print { gap: 6px; }
  .row.no-print > button, .row.no-print > .btn, .row.no-print > form > button, .row.no-print > select { height: 34px; min-height: 34px; padding-left: 12px; padding-right: 12px; font-size: .85rem; }
  .row.no-print > select { padding-right: 28px; }
}

/* [Shared] ---------- Default refine (Oct 16, 2026): look only, same layout, zero-specificity (:where) so every existing rule still wins ---------- */
/* [Shared] Checkboxes, radios, range and progress in the brand color (a company's own Brand color, or its Style's) instead of the browser's blue. */
html { accent-color: var(--blue); }
/* [Shared] Keyboard focus: one ring for every button, link, tab and menu row (mouse clicks show nothing, :focus-visible only). */
:where(button, .btn, a, summary, [tabindex]):focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
:where(.side, .portal-top, .phone-dock, .toast.bad) :where(a, button, summary):focus-visible { outline-color: #fff; outline-offset: -2px; }
/* [Shared] A button that can't be used looks it (it looked clickable before). */
:where(button:disabled, button[aria-disabled="true"], .btn[aria-disabled="true"]) { opacity: .55; cursor: not-allowed; }
/* [Shared] Same gray for every placeholder on every browser (Chrome's gray; Safari's was much lighter). */
:where(input, textarea)::placeholder { color: #767A80; opacity: 1; }
/* [Shared] Numbers in boxes line up like the numbers in tables. */
:where(input[type="number"], input[inputmode="decimal"], input[inputmode="numeric"]) { font-variant-numeric: tabular-nums; }
/* [Shared] Selected text in the brand tint. */
::selection { background: rgba(30, 144, 255, .22); background: color-mix(in srgb, var(--blue) 22%, transparent); }


/* [Shared] ---------- Control rows never wrap, part 2 (Oct 16, 2026; Travis's rule): shrink a little, then the extra buttons go into a More menu ---------- */
/* [Shared] A row marked data-fit (assets/js/fit-row.js) stays on one line. Before the script runs, or without it, the row slides sideways
   like the filter pills; with it, the last buttons that don't fit move into the house More menu (details.top-more) at the end. */
[data-fit], .command .board-tools[data-fit] { display: flex; flex-wrap: nowrap; align-items: center; overflow-x: auto; scrollbar-width: none; }
[data-fit]::-webkit-scrollbar { display: none; }
[data-fit].fit-on, .command .board-tools[data-fit].fit-on { overflow: visible; }
[data-fit] > * { flex: none; }
.fit-more[hidden] { display: none; }
.fit-more .status-menu { top: calc(100% + 6px); min-width: 200px; padding: 6px; }
.fit-more .status-menu > .fit-moved { display: flex; align-items: center; width: 100%; height: 40px; min-height: 40px; margin: 0; padding: 0 10px; justify-content: flex-start;
  background: none !important; border: 0 !important; border-radius: 10px; box-shadow: none; color: var(--ink) !important; font-size: .9rem; font-weight: 600; text-decoration: none; white-space: nowrap; }
.fit-more .status-menu > .fit-moved:hover, .fit-more .status-menu > .fit-moved:focus-visible { background: var(--paper) !important; }
.top-pills .pill-short { display: none; }
/* [Customers and Properties] Call · Text · Email · Directions: one line; the buttons may shrink (never grow, so desktop is unchanged). */
.row.reach-row { flex-wrap: nowrap; }
.row.reach-row > .btn { flex: 0 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; }
@media (max-width: 800px) {
  [data-fit], .row.reach-row { gap: 6px; }
  [data-fit] > .btn, [data-fit] > button, [data-fit] > details > summary.btn, .row.reach-row > .btn { height: 34px; min-height: 34px; padding: 0 12px; font-size: .85rem; }
}
@media (max-width: 420px) {
  [data-fit] > .btn, [data-fit] > button, [data-fit] > details > summary.btn, .row.reach-row > .btn { padding: 0 10px; }
  /* Header with a title pill (Base's Today's score): the page icon steps out and the pill shrinks so the
     title keeps one line (names are never cut, plans/naming.md). */
  .top:has(.top-pills) .top-title h1 > .ico, .top:has(.top-pills) .top-title h1 > svg,
  .top-title:has(> .pc-test) h1 > .ico, .top-title:has(> .pc-test) h1 > svg { display: none; } /* the Test mode pill too */
  .top:has(.top-pills) { gap: 6px; }
  .top-pills .pill { height: 30px; padding: 0 10px; font-size: 12px; }
  .top-pills .pill-full { display: none; } /* a pill with a short label ("Score 92 A") uses it here */
  .top-pills .pill-short { display: inline; }
}

/* [Shared] Quick Actions keep the house button size on phones (Travis: no shrinking fonts); the short name or More makes room instead. */
.dw-actions[data-fit] > .btn, .dw-actions[data-fit] > details > summary.btn { height: 36px; min-height: 36px; padding: 0 16px; font-size: inherit; }
/* [Shared] Quick Actions in a narrow card (4 columns on an 820px tablet, Oct 18 2026): the actions stack as a list, one per line,
   instead of all going into More; same font, the short names (Command) from the container rule above. */
.dw-k-quick { container: dwquick / inline-size; }
@container dwquick (max-width: 260px) {
  .dw-actions[data-fit] { flex-direction: column; align-items: stretch; }
  .dw-actions[data-fit] > .btn { justify-content: flex-start; }
}

/* [Help and Docs] Find my company (find.php): the "explain simpler" line (same look as .est-help on the builders) and the pick list
   (one button per company and side; a long company name shortens, the side never wraps). */
.login .est-help { font-size: .8rem; margin: 14px 0 0; }
.login .est-help summary { cursor: pointer; color: var(--blue); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.login .est-help p { margin: 6px 0 0; }
.login .af-picks { display: flex; flex-direction: column; gap: 10px; margin: 14px 0 12px; }
.login .af-picks button { width: 100%; display: flex; justify-content: space-between; align-items: center; gap: 12px; white-space: nowrap; min-width: 0; }
.login .af-picks button b { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.login .af-picks button span { flex: none; font-weight: 600; opacity: .85; }

/* [Shared] ---------- No sideways scrolling (Oct 17, 2026; Travis's rule): control rows never slide sideways to hide things ---------- */
/* [Route] Day picker chips: the weekday and the number sit as one tight stack, centered with even space above and below. */
.command .week-days a { gap: 2px; padding-top: 4px; padding-bottom: 4px; }
.command .week-days a > span, .command .week-days a > b { line-height: 1.1; margin: 0; }
.command .board-top { row-gap: 8px; }
.command .week-jump .wj-stack { display: none; }
/* [Route] Phones: the whole Day picker fits the line. Wait, the 7 days and Up (and Today when it isn't this week) are equal
   two-line chips: a small word over a number. Nothing hides off the edge, so there is no sliding and no edge fade. */
@media (max-width: 800px) {
  .command .day-picker {
    display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 4px; overflow: hidden; width: 100%;
    -webkit-mask-image: none !important; mask-image: none !important;
  }
  .command .day-picker .week-days { display: contents; }
  .command .day-picker .week-days a { order: 2; }
  .command .day-picker .week-days a, .command .day-picker .week-jump {
    min-width: 0; width: auto; padding: 4px 1px; flex-direction: column; justify-content: center; align-items: center; gap: 2px; overflow: hidden;
  }
  .command .day-picker .week-jump .wj-full { display: none; }
  .command .day-picker .week-jump .wj-stack { display: contents; }
  .command .day-picker .week-days a > span, .command .day-picker .week-jump .wj-stack > span {
    display: block; max-width: 100%; overflow: hidden; color: var(--muted); font-size: .6rem; font-weight: 700; letter-spacing: .02em; line-height: 1.1; text-transform: uppercase;
  }
  .command .day-picker .week-days a > b, .command .day-picker .week-jump .wj-stack > b { display: block; font-size: .92rem; line-height: 1.1; }
  .command .day-picker .week-jump.on .wj-stack > span, .command .day-picker .week-days a.on > span { color: #fff; }
  .command .day-picker .jump-today .wj-stack > span { font-size: .52rem; letter-spacing: 0; }
}
@media (max-width: 360px) {
  .command .day-picker { gap: 3px; }
  .command .day-picker .week-days a > span, .command .day-picker .week-jump .wj-stack > span { font-size: .55rem; letter-spacing: 0; }
  .command .day-picker .week-days a > b, .command .day-picker .week-jump .wj-stack > b { font-size: .85rem; }
}

/* [Shared] List bars (assets/listbar.js): on a phone, filter pills that don't fit their line fold into one Filters button with a count;
   it opens a small sheet from the bottom with the same pills, full width. Desktop never folds. */
.lb-fbtn, .lb-sheet-head { display: none; }
.lb-filters.lb-measure { flex-wrap: nowrap !important; overflow: hidden !important; }
.lb-filters.lb-measure > * { flex: none !important; }
@media (max-width: 800px) {
  .lb.lb-folded .list-search, .command .list-bar.lb.lb-folded .list-search { flex: 1 1 0; min-width: 0; }
  .lb.lb-folded > .lb-fbtn {
    display: inline-flex; align-items: center; gap: 6px; flex: none; height: 38px; min-height: 38px; margin: 0; padding: 0 14px;
    border-radius: 999px; background: var(--paper); border: 1px solid transparent; color: var(--ink); font-weight: 650; white-space: nowrap;
  }
  :not(.card):not(.command) > .list-bar.lb.lb-folded > .lb-fbtn { background: #fff; border-color: var(--line); }
  .lb.lb-folded > .lb-fbtn .ico { width: 16px; height: 16px; }
  .lb.lb-folded > .lb-fbtn.is-active { background: rgba(15, 159, 147, .1); border-color: var(--teal); color: var(--teal); }
  .lb-fn { display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box; border-radius: 999px; background: var(--teal); color: #fff; font-size: .7rem; font-weight: 750; }
  .lb-fn[hidden] { display: none; }
  .lb.lb-folded > .lb-filters { display: none; }
  .lb.lb-folded > .lb-filters.is-open {
    display: flex; position: fixed; z-index: 1000; left: 0; right: 0; bottom: 0; flex: none; flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 10px;
    margin: 0; padding: 14px 16px calc(18px + env(safe-area-inset-bottom, 0px)); max-height: 75vh; overflow-x: hidden; overflow-y: auto; box-sizing: border-box;
    background: #fff; border: 0; border-radius: 18px 18px 0 0; box-shadow: 0 -10px 30px rgba(11, 42, 69, .18); -webkit-mask-image: none; mask-image: none;
  }
  .lb.lb-folded > .lb-filters > * { flex: none; width: 100%; max-width: none; min-width: 0; margin: 0; box-sizing: border-box; }
  .lb.lb-folded > .lb-filters select { width: 100% !important; max-width: none; height: 44px; min-height: 44px; }
  /* With a count or Reset: search on its own line, then Filters on the left and the count on the right. Without: one line. */
  form.lb.lb-folded > .lb-tail { flex: 0 1 auto; order: 0; min-width: 0; max-width: none; margin-left: auto; justify-content: flex-end; }
  form.lb.lb-folded:has(> .lb-tail > :not([hidden])) > .list-search { flex: 1 1 100%; }
  form.lb.lb-folded > .lb-tail:not(:has(> :not([hidden]))) { display: none; }
  .lb.lb-folded > .lb-filters .status-filter summary { width: 100%; max-width: none; min-width: 0 !important; height: 44px; min-height: 44px; justify-content: space-between; }
  .lb.lb-folded > .lb-filters .status-filter .status-menu { position: static; width: auto; max-width: none; margin-top: 6px; box-shadow: none; }
  .lb.lb-folded > .lb-filters > button, .lb.lb-folded > .lb-filters > .btn { height: 44px; min-height: 44px; }
  .lb.lb-folded > .lb-filters > label:not(.check) { justify-content: space-between; }
  .lb.lb-folded > .lb-filters .month-pick { justify-content: space-between; }
  .lb.lb-folded .mp-pop { z-index: 1002; }
  .lb.lb-folded > .lb-filters > .lb-sheet-head { display: flex; align-items: center; justify-content: space-between; }
  .lb-sheet-head strong { font-size: 1rem; }
  .lb-sheet-head .lb-done { height: 34px; min-height: 34px; width: auto; margin: 0; padding: 0 16px; border-radius: 999px; }
  .lb-shade { position: fixed; inset: 0; z-index: 999; background: rgba(11, 24, 40, .35); }
  .lb-shade[hidden] { display: none; }
}

/* [Top Bar and Menus] Page tabs (nav.tabs) use the More menu too (assets/js/fit-row.js): the picked tab stays; tabs that don't fit go in More. */
.tabs > .fit-more > summary {
  display: inline-flex; align-items: center; height: auto; min-height: 0; margin: 0; padding: 8px 14px; border-radius: 999px;
  background: #fff; border: 1px solid var(--line); color: var(--ink); font-weight: 700; line-height: inherit; cursor: pointer;
}
.tabs > .fit-more { flex: none; }
.fit-more .status-menu > form.fit-moved { display: block; height: auto; min-height: 0; padding: 0; }
.fit-more .status-menu > form.fit-moved > button { width: 100%; height: 40px; min-height: 40px; margin: 0; padding: 0 10px; justify-content: flex-start; text-align: left;
  background: none !important; border: 0 !important; box-shadow: none; color: var(--ink) !important; font-size: .9rem; font-weight: 600; border-radius: 10px; }
.fit-more .status-menu > select.fit-moved { height: 40px; padding: 0 28px 0 10px; border: 1px solid var(--line) !important; background-color: #fff !important; }
/* [Billing and Plans] Invoice action row: "Print as" can shrink a little so the More menu stays on screen. */
.row.no-print > .itpl-as { flex: 0 1 auto; min-width: 150px; }
.row.no-print > .itpl-as select { flex: 1 1 auto; min-width: 0; max-width: 100%; text-overflow: ellipsis; }
@media (max-width: 800px) {
  /* Long hint text in a box ends in "…" instead of a hard cut. */
  input[placeholder] { text-overflow: ellipsis; }
  /* Property > Billing switch: the two choices share one line. */
  .bill-switch { flex-wrap: nowrap; }
  .bill-switch > span { flex: none; }
  .bill-switch > .btn { flex: 1 1 auto; min-width: 0; padding-left: 8px; padding-right: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* Program > Preview Size: label, box and Update on one line. */
  .row.preview-size { flex-wrap: nowrap; align-items: center; }
  .row.preview-size > label { flex: none; width: auto; margin: 0; white-space: nowrap; font-size: .82rem; }
  .row.preview-size > input { flex: 1 1 0; width: auto; min-width: 60px; margin: 0; }
  .row.preview-size > button { flex: none; margin: 0; padding-left: 12px; padding-right: 12px; }
}

/* [Bottom Menu and Companies] Settings > Bottom Menu (includes/bottom_menu.php): pick list with up/down, text/icon switches, phone preview. */
/* [Route] Role switcher (Route, Office, Owner, Sales, Crew Lead, Dispatcher, Portal): an even grid of pills, never a ragged wrap. */
.bm-switch { margin: 0 0 16px; }
.bm-pills { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 6px; margin: 0 0 10px; }
.bm-pills .btn { justify-content: center; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.bm-pills .btn.on { background: var(--blue); border-color: var(--blue); color: #fff; }
.bm-grid { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 20px; align-items: start; }
.bm-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; counter-reset: bm; }
.bm-item { display: flex; align-items: center; gap: 8px; padding: 4px 8px; border: 1px solid var(--line); border-radius: 10px; background: #fff; min-width: 0; }
.bm-item.off { background: var(--paper); }
.bm-item.off label span { color: var(--muted); }
.bm-item label.check { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px; margin: 0; white-space: nowrap; overflow: hidden; }
.bm-item label.check span { overflow: hidden; text-overflow: ellipsis; }
.bm-item .ico { width: 18px; height: 18px; flex: none; }
.bm-move { display: flex; gap: 4px; flex: none; }
.bm-move button { min-width: 32px; padding: 0 8px; }
.bm-look { display: flex; gap: 18px; margin-top: 10px; white-space: nowrap; }
.bm-look label.check { margin: 0; }
.bm-phone { border: 1px solid var(--line); border-radius: 22px; overflow: hidden; background: var(--paper); position: sticky; top: 76px; }
.bm-screen { height: 120px; display: flex; align-items: center; justify-content: center; }
.bm-bar { display: grid; grid-template-columns: repeat(var(--tabs, 5), minmax(0, 136px)); justify-content: space-evenly; background: var(--ink); border-top: 3px solid var(--grass); padding: 6px 4px 10px; }
.bm-bar a { display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 0; padding: 4px 0; color: #c8c8c8; font-size: .68rem; text-decoration: none; }
.bm-bar a.on { color: #fff; }
.bm-bar .ico { width: 18px; height: 18px; }
.bm-bar span { max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.15; }
.bm-bar.bm-notext span { display: none; }
.bm-bar.bm-notext .ico { width: 24px; height: 24px; }
.bm-bar.bm-notext a { padding: 6px 0 7px; }
.bm-bar.bm-noicon .ico { display: none; }
.bm-bar.bm-noicon a { justify-content: center; min-height: 37px; font-size: .78rem; font-weight: 650; }
.bm-sub { margin: 26px 0 4px; font-size: 1.05rem; }
.sx-bm { display: grid; gap: 2px; min-width: 0; }
.sx-bm span { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.sx-bm-send { margin-top: 6px; display: flex; gap: 6px; align-items: center; }
.sx-bm-send select { width: auto; }
@media (max-width: 1100px) { /* tablets too: beside the preview the list was ~200px and cut every name to one letter */
  .bm-grid { grid-template-columns: minmax(0, 1fr); }
  .bm-phone { position: static; order: -1; }
  .bm-grid > div:last-child { order: -1; }
  .bm-screen { height: 56px; }
}

/* [Billing and Plans] ---------- Detail-page title row stays one line on phones (Oct 17, 2026; Travis's invoice screenshot) ----------
   An invoice header (Back · "Invoice INV-2026-2476" · PDF · Print · Take Card Payment) squeezed the title pill to one
   letter per line. On a phone a page with a Back pill folds its quiet actions into the house More menu (.ta-narrow,
   includes/format.php top_actions), the title shows its short form ($titleShort: the number) and a primary with a
   'short' label shows icon + short word (Pay). Desktop (and pages without a Back pill) are unchanged. */
.top-actions .ta-narrow, .top h1 .tt-short, .top-primary .ta-short { display: none; }
@media (max-width: 600px) {
  .top-actions:has(> .top-action.ta-wide) .ta-wide { display: none; } /* a worded quiet action folds too, so the title keeps its room (Products) */
  .top-actions:has(> .top-action.ta-wide) .ta-narrow { display: block; }
  .top-title.has-back ~ .top-actions .ta-wide { display: none; }
  .top-title.has-back ~ .top-actions .ta-narrow { display: block; }
  .top h1 .tt-full { display: none; }
  .top h1 .tt-short { display: inline; white-space: nowrap; }
  .top-primary.has-ico.has-short { width: auto; padding: 0 12px 0 10px; gap: 5px; }
  .top-primary.has-short .ta-short { display: inline; white-space: nowrap; }
}

/* [Dashboard] Toasts (and the floating weather / Red Flag alert, a .toast in .notices) float over the page at z-index 40, above the
   sticky header (8) and the side menu (30). While a menu or sheet is open (a ⋯ / More menu, a status picker, the Filters
   sheet, the side menu or the phone More menu, the task panel) they step below it, so nothing covers the choices
   (Oct 17, 2026; Travis's invoice screenshot). They come back up when it closes. */
body:has(details[open] > .status-menu, .lb-filters.is-open, .tag-menu:not([hidden]), #task-panel:not([hidden]), .field-shade:not([hidden])) .notices,
body.nav-open .notices { z-index: 1; }
/* [Shared] ---------- One line by default (Oct 17, 2026; Travis: "NO WRAPPING ANYWHERE, ever") ----------
   Short values (names, Service names, titles in cards, pills, buttons, labels) stay on one line and end in "…"; core.js puts the
   full text in a title (hover) and opens it in place on tap. Real paragraphs (p, notes, descriptions, terms) still flow.
   New screens: put .one-line on any short value, or use the structures below, which already do it (docs/ui-patterns.md). */
.one-line { display: block; min-width: 0; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
span.one-line, a.one-line, b.one-line { display: inline-block; vertical-align: bottom; }
.nw-open { white-space: normal !important; overflow: visible !important; } /* tapped open (core.js) */
.pill, .badge, .btn, .tag, label > b, th { white-space: nowrap; }
.stat { min-width: 0; }
:is(.stat > b, .stat > span:not(.badge)):not(:has(input, select, textarea, button, details, form)) { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; max-width: 100%; }
.stat > span:not(.badge) { display: block; }
:is(.card > h2, .card > h3, .card > div > h2, .stand-head h2):not(:has(input, select, textarea, button, details, form, .btn, .menu)) { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.svc-name { min-width: 0; max-width: 100%; }
.profile > div > .muted { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.task-open { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.portal-prog { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; min-width: 0; }
:is(.form-grid > label, .form-grid > div > label):not(:has(input, select, textarea, button)) { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; } /* a caption only: a label that holds its box is never clipped */
/* [Route] A settings switch (module_field_html, setting_field: label.check with its box first) stays one line too; the box never clips. */
.form-grid > div > label.check:not(:has(select, textarea, button, input:not([type=checkbox]):not([type=hidden]))) { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.form-grid > div > label.check > input[type=checkbox] { display: inline-block; vertical-align: middle; margin: 0 8px 0 0; }
@media (max-width: 800px) {
  .stat > span:not(.badge) { white-space: nowrap; }
  .stats > .stat:has(> b > a[href*="customers.php"]) { grid-column: 1 / -1; } /* a customer's name gets the whole row */
  .stats .stat > b { font-size: 1.2rem; }
  table td:has(> a.svc-name) { max-width: 0; width: 100%; }
  a.svc-name { display: flex; }
  /* Phone cards (table.phone-sheet): a plain-text value is one line with "…" after its label; a lone link or name too. */
  table.phone-sheet td[data-label]:not([data-label=""]):not(:has(*)) { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  table.phone-sheet td[data-label]:not([data-label=""]):not(:has(*))::before { display: inline-block; width: 92px; margin-right: 8px; vertical-align: baseline; }
  table.phone-sheet td > :is(a, b, strong, span.one-line):not(:has(input, select, textarea, button, details, form)), table.phone-sheet td[data-label=""]:not(:has(input, select, textarea, button, details, form, .btn)) { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}
@media (max-width: 400px) {
  .stats .stat > b { font-size: 1.1rem; }
}
/* [Shared] Computer lists (.list-results): names, links and short values in table cells stay on one line ("…" past 170px); list-bar labels too. */
.list-size > span, .lb-filters label > span { white-space: nowrap; }
@media (min-width: 801px) {
  .list-results table td > a:first-child:not(.btn):not(.svc-name) { display: inline-block; max-width: 170px; vertical-align: bottom; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .list-results table td:not(:has(input, select, button, textarea, form, .badge, .tag, .pill, div, ul, p, img, svg)) { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 170px; }
}
/* [Customers and Properties] Laptop widths: lists with many columns (Properties: 8 + actions) fit their card with no sideways scroll: tighter cell
   padding, name/text caps that follow the screen (90-170px) and a compact Reason menu next to Inactive. */
@media (min-width: 801px) and (max-width: 1440px) {
  .list-results table :is(td, th) { padding-left: 7px; padding-right: 7px; }
  .list-results table td > a:first-child:not(.btn):not(.svc-name) { max-width: clamp(90px, 10.5vw, 170px); }
  .list-results table td:not(:has(input, select, button, textarea, form, .badge, .tag, .pill, div, ul, p, img, svg)) { max-width: clamp(90px, 10.5vw, 170px); }
  .list-results table td:last-child form.drop select.reason { max-width: 84px; }
}
/* [Top Bar and Menus] Tablet widths (container queries on .list-results, so the side menu's width counts): nothing wider than its card.
   The 720px table floor goes away under a 900px card; lower-priority columns step out (.lc-a under 960px, .lc-b under
   820px, .lc-c under 600px: Properties Pond/Surface, Landscape, Address; Customers Email; Tasks Customer), the Reason
   menu and Inactive stack, and names/text cap at 150px, then 120px. The same values stay on the detail pages. */
@media (min-width: 801px) {
  .list-results { container-type: inline-size; }
}
@container (max-width: 960px) {
  .list-results .lc-a { display: none; }
  .list-results table td:last-child form.drop { flex-direction: column; align-items: stretch; gap: 4px; }
  .list-results table td:last-child form.drop select.reason { max-width: 110px; }
}
@container (max-width: 900px) {
  .list-results table { min-width: 0; width: 100%; }
  .list-results table td > a:first-child:not(.btn):not(.svc-name), .list-results table td:not(:has(input, select, button, textarea, form, .badge, .tag, .pill, div, ul, p, img, svg)) { max-width: 150px; }
}
@container (max-width: 820px) {
  .list-results .lc-b { display: none; }
  .list-results table td > a:first-child:not(.btn):not(.svc-name), .list-results table td:not(:has(input, select, button, textarea, form, .badge, .tag, .pill, div, ul, p, img, svg)) { max-width: 120px; }
}
@container (max-width: 600px) {
  .list-results .lc-c { display: none; }
}
/* [Shared] Every app table in a card fits and uses its space (Oct 17, 2026, rules check: no wrapped cells, no sideways scroll, no
   text cut short while there is room). Short cells stay on one line at their natural width (up to 13% of the screen, 90px to 16em, then "…"; full text
   on hover and tap via core.js). The row's main column (its first linked cell, or the first cell when no cell has a link)
   (or the cell marked td.t-main) takes all the room that is left and is the one that ends in "…" when space runs out. Tables that would still not fit mark
   columns .lc-a/.lc-b/.lc-c to step out by their card's width, like Properties. The sales site and company websites
   (body.ps, body.site) keep their own rules. */
@media (min-width: 801px) {
  body:not(.ps):not(.site) main .card table:not(.board) td > a:first-child:not(.btn):not(.svc-name):not(.one-line) { display: inline-block; max-width: clamp(90px, 13vw, 16em); vertical-align: bottom; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* .board (Base) keeps full Service names */
  body:not(.ps):not(.site) main .card table:not(.board) td:not(:has(input, select, button, .btn, textarea, form, .badge, .tag, .pill, div, ul, p, img, svg)) { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: clamp(90px, 13vw, 16em); } /* .board keeps column %; a cell with a button (.btn, e.g. the portal's Review & Sign) keeps the whole button */
  body:not(.ps):not(.site) main .card table:not(:has(td.t-main)) tr > td:has(> a:not(.btn)):not(td:has(> a:not(.btn)) ~ td),
  body:not(.ps):not(.site) main .card table:not(:has(td > a:not(.btn), td.t-main)) tr > td:first-child:not(:has(input, select, button, textarea, form)),
  body:not(.ps):not(.site) main .card table tr > td.t-main { max-width: 0; width: 100%; }
  body:not(.ps):not(.site) main .card table:not(.board) tr > td.t-main > a:first-child:not(.btn):not(.svc-name):not(.one-line) { max-width: 100%; } /* Tracker 885: the main column's link uses the whole column before "…" (Service roster names) */
  body:not(.ps):not(.site) main .card table:not(:has(td.t-main)) tr > td:has(> a:not(.btn)):not(td:has(> a:not(.btn)) ~ td) > a:first-child:not(.btn) { max-width: 100%; }
  body:not(.ps):not(.site) main .card table td.t-main { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* td.t-main: this column takes the room instead */
  body:not(.ps):not(.site) main .card table td.t-main > a:first-child:not(.btn) { max-width: 100%; } /* a link in that column may use all of it */
  /* A table with a td.t-main: that column gives way, so the other cells may show more before "…" (users, equipment, reviews). */
  body:not(.ps):not(.site) main .card table:has(td.t-main) td:not(.t-main):not(:has(input, select, button, textarea, form, .badge, .tag, .pill, div, ul, p, img, svg)),
  body:not(.ps):not(.site) main .card table:has(td.t-main) td:not(.t-main) > a:first-child:not(.btn):not(.svc-name):not(.one-line) { max-width: clamp(120px, 24vw, 26em); }
  body:not(.ps):not(.site) main .card table a.svc-name { display: flex; }
  :is(.card, .card > form):has(> table :is(.lc-a, .lc-b, .lc-c)) { container-type: inline-size; }
}
@media (min-width: 1200px) { body:not(.ps):not(.site) main .card.slim-list > table td.svc-prog { max-width: none; } } /* Services: Program shows in full on a wide screen; the Service name gives way */

@media (min-width: 801px) and (max-width: 1440px) {
  body:not(.ps):not(.site) main .card table :is(td, th) { padding-left: 7px; padding-right: 7px; }
}
@container (max-width: 960px) { .lc-a { display: none; } }
@container (max-width: 820px) { .lc-b { display: none; } }
@container (max-width: 600px) { .lc-c { display: none; } }
/* [Customers and Properties] Billing's due list under an 820px card: Property and Area have stepped out, so the customer name gives way to What
   (the 150px tablet cap above, which the t-main rule would otherwise lift); a longer name ends in "…", full on hover/tap. */
@container (max-width: 820px) {
  body:not(.ps):not(.site) main .list-results.sheet table.bill-due td:not(.t-main) > a:first-child:not(.btn):not(.svc-name):not(.one-line) { max-width: 150px; }
}
/* [Websites and Sales Site] Sales site gallery captions: one line with "…" (the full caption is the picture's alt text). */
.ps-gal figcaption { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 600px) { .ps-gal figcaption { font-size: .8rem; } }
/* [Tasks and Tracker] Sign-in heading: one line; a long company name steps down a little, then ends in "…". */
.login h1 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 480px) { .login h1 { font-size: clamp(1.15rem, 6.2vw, 1.6rem); } }
/* [Shared] One-line strip above a board (Oct 17, 2026; was routing.css only): a bold label, muted text that takes the room left and
   ends in "…", then buttons. Base's Smart Routing lines (includes/routing_ui.php) and Tasks today (includes/tasks.php
   task_today_strip). Never wraps. */
.rt-strip { display: flex; flex-wrap: nowrap; align-items: center; gap: 10px; background: #fff; border: 1px solid var(--line); border-radius: 12px; padding: 8px 8px 8px 14px; margin-bottom: 12px; min-width: 0; }
.rt-strip > span { flex: 1; min-width: 0; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rt-strip > b, .rt-strip > .btn, .rt-strip > button { white-space: nowrap; flex: none; }
/* [Shared] Long name + minutes: the name gives way (…), the minutes and Review stay whole (Oct 20 2026, 375 overflow). */
.rt-strip > b.rt-warn { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* [Tasks and Tracker] Tasks list (Oct 17, 2026, rules check "use the space"): the Task column is the row's main column. Its title link sits
   inside the meta block, so the shared first-linked-cell rule above would pick Customer; Customer stays a short column. */
@media (min-width: 801px) {
  body:not(.ps):not(.site) main .card table.task-table tr.task-row > td:has(> div > a.task-open) { max-width: 0; width: 100%; }
  body:not(.ps):not(.site) main .card table.task-table tr.task-row > td.lc-c:has(> a:not(.btn)) { width: auto; max-width: clamp(90px, 13vw, 16em); }
  body:not(.ps):not(.site) main .card table.task-table tr.task-row > td.lc-c:has(> a:not(.btn)) > a { max-width: clamp(90px, 13vw, 16em); }
}
/* [Customers and Properties] Phone cards: the task title and its customer use the card's full width (no column caption), like a card heading. */
@media (max-width: 800px) {
  table.phone-sheet.task-table tr.task-row > td:nth-child(2), table.phone-sheet.task-table tr.task-row > td.lc-c { grid-template-columns: minmax(0, 1fr); }
  table.phone-sheet.task-table tr.task-row > td:nth-child(2)::before, table.phone-sheet.task-table tr.task-row > td.lc-c::before { content: none; }
}
/* [Tasks and Tracker] Bar sizes in 5% steps for charts drawn from data (no inline style=): pct_class() in includes/format.php. */
.pct-h-0 { height: 0%; } .pct-h-5 { height: 5%; } .pct-h-10 { height: 10%; } .pct-h-15 { height: 15%; } .pct-h-20 { height: 20%; } .pct-h-25 { height: 25%; } .pct-h-30 { height: 30%; } .pct-h-35 { height: 35%; } .pct-h-40 { height: 40%; } .pct-h-45 { height: 45%; } .pct-h-50 { height: 50%; } .pct-h-55 { height: 55%; } .pct-h-60 { height: 60%; } .pct-h-65 { height: 65%; } .pct-h-70 { height: 70%; } .pct-h-75 { height: 75%; } .pct-h-80 { height: 80%; } .pct-h-85 { height: 85%; } .pct-h-90 { height: 90%; } .pct-h-95 { height: 95%; } .pct-h-100 { height: 100%; }
.pct-w-0 { width: 0%; } .pct-w-5 { width: 5%; } .pct-w-10 { width: 10%; } .pct-w-15 { width: 15%; } .pct-w-20 { width: 20%; } .pct-w-25 { width: 25%; } .pct-w-30 { width: 30%; } .pct-w-35 { width: 35%; } .pct-w-40 { width: 40%; } .pct-w-45 { width: 45%; } .pct-w-50 { width: 50%; } .pct-w-55 { width: 55%; } .pct-w-60 { width: 60%; } .pct-w-65 { width: 65%; } .pct-w-70 { width: 70%; } .pct-w-75 { width: 75%; } .pct-w-80 { width: 80%; } .pct-w-85 { width: 85%; } .pct-w-90 { width: 90%; } .pct-w-95 { width: 95%; } .pct-w-100 { width: 100%; }
/* [Route] Today's Teams (teams-day.php, assets/js/teams-day.js): team cards in a grid, one-line names, drag on a computer, tap menu (field-ask). */
.td-date { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; white-space: nowrap; min-width: 0; }
.td-date b { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.td-date .btn { flex: none; }
.td-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; align-items: start; }
.td-grid > .card { margin: 0; min-width: 0; }
.td-grid + .td-to { margin-top: 16px; } /* Time Off under the team board: the standard card gap */
.td-to-acts { justify-content: flex-end; } .td-to-acts button { flex: none; } /* Approve and Deny stay on one line */
td .one-line.qw-fit { width: 0; min-width: 100%; } /* the note under Reason never widens the table; it ends in "…" */
@media (min-width: 801px) {
  .td-to { container-type: inline-size; }
  @container (max-width: 620px) { .td-to-rows .td-to-why { display: none; } } /* a narrow card (tablet, side menu open): Reason steps out so the row fits */
}
.td-team h2 { display: flex; align-items: center; gap: 8px; min-width: 0; white-space: nowrap; }
.td-team h2 svg { flex: none; }
.td-tn { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.td-sub { margin: 0 0 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.td-list { display: flex; flex-direction: column; gap: 6px; min-height: 38px; }
.td-person { display: flex; align-items: center; justify-content: flex-start; gap: 8px; width: 100%; min-width: 0; height: auto; min-height: 40px; padding: 6px 12px; border: 1px solid var(--line); border-radius: 10px; background: #fff; color: var(--ink); text-align: left; font-weight: 600; white-space: nowrap; }
button.td-person { cursor: grab; touch-action: manipulation; }
.td-nm { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.td-from { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; font-weight: 500; } /* the team gives way first, so the name shows in full */
.td-person .badge { flex: none; }
.td-empty { display: flex; align-items: center; gap: 8px; margin: 10px 0 0; font-weight: 650; white-space: nowrap; min-width: 0; }
.td-empty span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.td-move { display: flex; gap: 8px; margin-top: 8px; min-width: 0; }
.td-move select { flex: 1 1 auto; min-width: 0; }
.td-move button { flex: none; }
#td-days label { display: flex; flex-direction: column; gap: 4px; margin: 0 0 8px; font-weight: 650; }
.dw-row .badge { flex: none; }
@media (max-width: 600px) {
  .td-grid { grid-template-columns: minmax(0, 1fr); }
}

/* [Shared] Reference (reference.php): the product lookup. The shared list bar on top (outside a card), then one .card per product in
   a grid. What it controls is grouped by effect (Kills, Prevents, Burns, Suppresses, Limited) as .badge chips in the .pills
   row; the facts (rates, re-entry, wind, temperature, on hand) are a label-over-value grid. Labels and facts stay one line;
   the target chips, ingredients and notes are real lists and paragraphs, so they flow. */
.ref-page { min-width: 0; }
.ref-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 420px), 1fr)); gap: 14px; align-items: start; }
.ref-grid > .card.ref-card { margin: 0; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.ref-card[hidden] { display: none !important; }
.ref-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ref-head h2 { margin: 0; flex: 1 1 auto; min-width: 0; font-size: 1.05rem; }
.ref-head h2 a { color: var(--ink); }
.ref-badges { display: flex; gap: 4px; flex: none; }
/* .ref-badges .badge: shared pill size (Tracker 880) */
.ref-sub { margin: -6px 0 0; font-size: .8rem; }
.ref-does { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 10px; margin: 0; align-items: baseline; }
.ref-does dt, .ref-facts dt { color: var(--muted); font-size: .68rem; letter-spacing: .04em; text-transform: uppercase; font-weight: 650; white-space: nowrap; }
.ref-does dt { padding-top: 4px; }
.ref-does dd { margin: 0; gap: 4px; }
/* .ref-does .badge: shared pill size (Tracker 880) */
.ref-facts { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); grid-auto-flow: row dense; gap: 8px 12px; margin: 0; padding: 10px 0 0; border-top: 1px solid var(--line); }
.ref-facts > div { min-width: 0; }
.ref-facts > .ref-wide { grid-column: span 2; }
.ref-facts > .ref-full { grid-column: 1 / -1; }
.ref-facts > .ref-full dd { white-space: normal; overflow: visible; }
.ref-facts > .ref-full dd.one-line { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* a long list kept to one line (Product Lookup: Labeled For, Other Names); tap shows it all */
.ref-said { flex: 1 1 100%; font-size: .82rem; line-height: 1.4; }
.ref-page .list-bar .list-search { flex: 1 1 260px; min-width: 220px; }
.ref-facts dd { margin: 2px 0 0; font-weight: 600; font-variant-numeric: tabular-nums; }
.ref-ing, .ref-notes { margin: 0; font-size: .82rem; line-height: 1.4; }
.ref-ing b { color: var(--muted); font-size: .68rem; letter-spacing: .04em; text-transform: uppercase; font-weight: 650; margin-right: 4px; }
.ref-notes { color: var(--muted); }
.ref-links { margin: auto 0 0; gap: 8px; }
.ref-none { margin: 4px 0 14px; }
mark.hit { background: color-mix(in srgb, var(--orange) 40%, transparent); color: inherit; padding: 0 1px; border-radius: 2px; }
@media (max-width: 800px) {
  .ref-grid { gap: 10px; }
  .ref-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ref-page .list-bar .list-search { min-width: 0; }
}

/* [Shop and Time Clock] On Hand (inventory.php): the On Hand box and Low badge on one line; on phones the Products-list row (icon + name … On Hand · Receive) keeps that cell too. */
.inv-list form.inv-set { display: inline-flex; align-items: center; gap: 6px; margin: 0; white-space: nowrap; }
.inv-list form.inv-set input.rate-in { width: 90px; }
@media (max-width: 800px) {
  .inv-list.slim-list > table td.inv-hand { display: block; flex: none; padding: 6px 0; }
  .inv-list form.inv-set input.rate-in { width: 64px; height: 36px; min-height: 36px; padding: 0 8px; }
  .inv-list.slim-list > table td:last-child .btn { white-space: nowrap; }
}

/* [Shared] Back pill + title on tablets (rules check: "truncated with room", Oct 18 2026): the title keeps its room. The Back pill's
   words give way first ("Back to Dash…", never below its arrow), and a Settings section's Save uses its short label (Save). */
.top-title.has-back > .back-link { flex: 0 100 auto; min-width: 32px; }
.top-title.has-back > .back-link span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.top-title.has-back > h1 { flex: 0 1 auto; }
@media (min-width: 801px) { .top-title.has-back > h1 { flex-shrink: 0; max-width: calc(100% - 40px); } } /* on a phone the Back pill is already just its arrow */
.top-title > .pc-test .tt-short { display: none; }
@media (max-width: 600px) { .top-title.has-back > .pc-test .tt-full { display: none; } .top-title.has-back > .pc-test .tt-short { display: inline; } } /* "Test" beside a Back pill on phones */
.dw-wx > .dw-t1 { flex: 1 1 auto; } /* the Scorecard widget's words use the card's width beside the gauge */
.dw-k-score .dw-in { container-type: inline-size; }
@container (max-width: 200px) { .dw-k-score .dw-wx { flex-direction: column; align-items: flex-start; gap: 8px; } .dw-k-score .dw-wx > .dw-t1 { flex: none; max-width: 100%; } } /* a narrow Scorecard card: words under the gauge, never cut */
@media (max-width: 1100px) { .top:has(.top-title.has-back) .set-topsave-n { display: none; } }
@media (max-width: 420px) { .rcw-hero .rc-day:nth-child(3) { display: none; } }
/* [Dashboard] Freeze Alert bar on the Dashboard (includes/freeze_alert.php), above the widgets. */
.fz-bar { display: flex; align-items: center; gap: 10px; margin: 0 0 14px; padding: 10px 14px; border-left: 4px solid var(--blue); background: color-mix(in srgb, var(--blue) 7%, #fff); white-space: nowrap; min-width: 0; }
.fz-ico { flex: none; font-size: 1.3rem; color: var(--blue); }
.fz-txt { flex: 1 1 auto; min-width: 0; }
.fz-bar > button { flex: none; } /* only the bar's own button: the Pause All sheet opened from it sits inside the bar's markup */
@media (max-width: 600px) { .fz-txt .muted { display: none; } }

/* [Top Bar and Menus] Page sections in the top bar, one pattern on every page (assets/js/page-nav.js, Travis Oct 19 2026,
   plans/nav-overhaul-2026-10-19.md): the title is the Menu and opens the section sheet; Back is
   the round chevron and New the round + on every width; the Settings gear is always last (format.php top_actions). */
.top .pn-tabs { margin: 0; flex: 1 1 auto; min-width: 0; }
.pn-switch { display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%; min-height: 32px; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-transform: inherit; letter-spacing: inherit; cursor: pointer; }
.pn-switch { border-radius: 8px; -webkit-tap-highlight-color: transparent; }
.pn-switch:hover, .pn-switch:active { background: color-mix(in srgb, currentColor 10%, transparent); color: inherit; box-shadow: none; } /* subtle, inside its own shape (1.4.35) */
.pn-switch:focus { outline: none; } .pn-switch:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.pn-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pn-caret { flex: none; color: var(--muted); }
.pn-cur { flex: none; color: var(--blue); white-space: nowrap; }
.pn-dots { display: none; }
.pn-sheet .pn-head { justify-content: space-between; align-items: center; flex-wrap: nowrap; margin: 0 0 12px; }
.pn-sheet .pn-head button { flex: none; width: auto; margin: 0; }
.pn-sheet .pn-head b { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pn-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; } /* two across so long section names (Revenue by Service, Stages & Reasons) show in full */
.pn-item { display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0; padding: 12px 6px; border: 1px solid var(--line); border-radius: 12px; background: #fff; color: var(--ink); font-weight: 700; text-align: center; text-decoration: none; }
.pn-item span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pn-item .ico { width: 22px; height: 22px; }
.pn-item.on { background: var(--blue); border-color: var(--blue); color: #fff; }
.back-link { flex: none; width: 32px; padding: 0; justify-content: center; }
.back-link span { display: none; }
.top-title.has-back > .back-link { flex: none; width: 32px; }
.top h1 .pn-switch .pn-title, .top h1 .pn-switch .pn-cur { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; overflow-wrap: normal; } /* the phone h1 span rule must not wrap the switcher (1.4.27 fix) */
.top-primary.top-new { width: 32px; padding: 0; }
.top-primary.top-new .ta-ico { display: inline-flex; }
.top-primary.top-new .ta-label { display: none; }
@media (min-width: 801px) {
  .top .pn-tabs ~ .top-actions, .top .pn-tabs ~ .top-pills { margin-left: auto; }
}
@media (max-width: 800px) {
  .top .pn-tabs { display: none; }
  .pn-dots { display: flex; gap: 4px; position: absolute; left: 50%; bottom: 3px; transform: translateX(-50%); pointer-events: none; }
  .pn-dots i { width: 5px; height: 5px; border-radius: 50%; background: var(--line); }
  .pn-dots i.on { background: var(--blue); }
}
/* [Sprout] Quick Calc widget (includes/quick_calc.php) */
.qc { display: grid; gap: 8px; min-width: 0; }
.qc-q { width: 100%; }
.qc-in:empty { display: none; }
.qc-out { display: grid; gap: 2px; margin: 0; font-weight: 600; }
.qc-out { min-height: 8.5rem; align-content: start; } /* fixed answer slot: typing never moves the hint panel under it */
.qc-line { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* [Route] Quick Calc polish (Travis Oct 19 2026): answer card, even button group, tidy fields, hint panel foot. */
.qc .qc-picks { display: flex; flex-wrap: nowrap; gap: 4px; min-width: 0; }
.qc .qc-picks .btn { flex: 1 1 auto; min-width: 0; width: auto; padding-left: 4px; padding-right: 4px; white-space: nowrap; }
.qc .qc-short { display: none; }
@container qc (max-width: 500px) { .qc .qc-full { display: none; } .qc .qc-short { display: inline; } }
/* [Help and Docs] Hint panel inside a card: in the flow with its own scroll, so a short widget never cuts it off. */
.qc .qa-help.qc-help { position: static; display: none; margin-top: 2px; max-height: 240px; box-shadow: 0 6px 18px rgba(11, 42, 69, .10); }
.qc .qa-help.qc-help.qa-open { display: block; }
.dw-in:has(> .qc) { overflow-y: auto; }
/* [Sprout] Narrow Quick Calc (pop-up, phone, small widget): sized by its own width, not the screen. Hint columns stack, nothing clips. */
.qc { container: qc / inline-size; }
.qc-pop { width: min(560px, calc(100% - 32px)); }
.qc-pop .qc { min-width: 0; }
.qc-pop .qc .qc-picks .btn, .qc-pop .qc button.qa-ex, .qc-pop .qc .qc-copy { width: auto; }
@container qc (max-width: 640px) {
  .qc-help .qa-cols { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .qc-help .qa-cols > section { padding: 0; }
  .qc-help .qa-cols > section + section { border-left: 0; border-top: 1px dashed var(--line); padding-top: 10px; }
  .qc-help .qa-exs { flex-direction: row; flex-wrap: wrap; }
  .qc-help .qa-tpls > div { grid-template-columns: auto minmax(0, 1fr); align-items: baseline; gap: 8px; }
}
.qc-help { overflow-x: hidden; }
.qc .qc-in { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 8px; }
.qc .qc-in select { margin-bottom: 0; } /* even field heights: the area picker and its Custom box swap in place (1.4.61) */
.qc-out { font-weight: 500; color: var(--muted); padding: 10px 14px; border-radius: 12px; box-sizing: border-box; }
.qc-out.qc-ans { position: relative; padding: 10px 14px; border-radius: 12px; background: color-mix(in srgb, var(--grass) 9%, #fff); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--grass) 28%, #fff); color: var(--ink); animation: qa-pop .16s ease-out; }
.qc-out.qc-ans .qc-line:first-child { font-size: 1.05rem; font-weight: 700; }
.qc-copy { justify-self: start; margin-top: 4px; height: auto; min-height: 0; padding: 2px 10px; }
.qc-help .qa-tpls code { white-space: nowrap; }
.qc-help .qa-tpls .muted, .qc-help button.qa-ex { white-space: nowrap; }
.qc-help-foot { margin: 10px 0 0; padding-top: 8px; border-top: 1px dashed var(--line); }

/* [Customers and Properties] Add Property: plain Save & Add Another / Cancel left, main Save far right, one row (no wrap at 375). */
.row.save-split { flex-wrap: nowrap; align-items: center; }
.row.save-split > * { white-space: nowrap; margin-top: 0; }
.row.save-split .save-main { margin-left: auto; }
/* [Customers and Properties] Property Name duplicate note: one reserved line so nothing jumps when it shows. */
.hint.name-dupe { min-height: 1.4em; margin: 4px 0 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* [Shared] Pick chips (includes/conditions.php, Oct 20 2026): grouped quick-tap toggles, a real checkbox inside each pill.
   Used by the Property form's Conditions drawer, Route > What went down > Conditions Seen, and (read-only badges)
   What We Noticed in the portal. Property drawers reuse .zone-fold + .set-row; the bar's summary stays one line. */
.pick-groups { display: grid; gap: 10px; padding: 4px 0 12px; }
.pick-head { margin: 0 0 4px; font-size: .8rem; font-weight: 650; color: var(--muted); }
.pick-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; }
.pick-chip { position: relative; display: inline-flex; align-items: center; min-height: 36px; margin: 0; cursor: pointer; }
.pick-chip > input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.pick-chip > span { display: inline-flex; align-items: center; min-height: 36px; padding: 0 12px; border: 1px solid var(--line); border-radius: 99px; background: #fff; color: var(--ink); font-size: .88rem; white-space: nowrap; }
.pick-chip:hover > span { border-color: var(--blue); }
.pick-chip > input:checked + span { background: var(--blue); border-color: var(--blue); color: #fff; }
.pick-chip > input:focus-visible + span { outline: 2px solid var(--blue); outline-offset: 2px; }
.prop-drawers { margin: 14px 0; border-bottom: 1px solid var(--line); }
.prop-drawers > .zone-fold > summary .set-txt .muted { flex: 1; }
.cond-seen { margin: 4px 0 8px; }

/* [Shared] Load Out / Refill: Water header, products one per line, long names end in … (Travis Oct 20, 2026) */
.lo-list { list-style: none; margin: 2px 0 0; padding: 0; min-width: 0; }
.lo-list li { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#lo-dlg .form-grid { grid-template-columns: minmax(0, 1fr); }
#lo-dlg .lo-prod label { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* [Top Bar and Menus] Shared Top Bar (tasks 555 and 564, Oct 20 2026; js/topbar-save.js). Save sits far right, quiet until something changed. */
.top .pn-tabs { display: none; } /* Top Bar rule (tasks 553, 555, 564, Oct 20 2026): the Menu (title ▾) is the only section switcher; no pill row on any width */
[data-topsave-for]:not(.is-dirty) { opacity: .55; }
.tb-unsaved { align-self: center; color: var(--muted); font-size: 12px; white-space: nowrap; visibility: hidden; }
.tb-unsaved.is-on { visibility: visible; }
/* [Top Bar and Menus] Standard Top Bar button (task 573): one height and shape, icon + word; main filled with the Style color, others outlined. */
.top-actions .top-std { height: 32px; min-height: 32px; padding: 0 12px; gap: 6px; flex: none; white-space: nowrap; }
.top-actions .top-std .ico { width: 16px; height: 16px; flex: none; }
.top-actions .top-std.quiet { border-color: var(--blue); color: var(--blue); }
.tb-changed { background: color-mix(in srgb, var(--blue) 7%, #fff); }
@media (max-width: 480px) { .tb-unsaved { display: none; } .top-actions .top-std { width: 32px; padding: 0; } .top-actions .top-std .ts-word { display: none; } }

/* [Top Bar and Menus] Task 574 Icon Tiles (Oct 20 2026, Travis exact). One tile everywhere: rounded square, soft gradient from the Style's own
   white and gray (--card, --paper), bigger icon, no words. Hover/focus: Style blue, icon white. .attn: the same blue,
   pulsing softly (glow only, never a size change). .emerg: red, same rules. Tokens below so new states can be added. */
:root { --tile: 36px; --tile-r: 10px; --tile-ico: 20px;
  --tile-rest: linear-gradient(180deg, var(--card), var(--paper));
  --tile-on: linear-gradient(180deg, color-mix(in srgb, var(--blue) 78%, #fff), var(--blue));
  --tile-red: linear-gradient(180deg, color-mix(in srgb, var(--red) 78%, #fff), var(--red)); }
.tile { display: inline-flex; align-items: center; justify-content: center; flex: none; box-sizing: border-box;
  width: var(--tile); height: var(--tile); min-height: var(--tile); padding: 0; margin: 0; gap: 0;
  border: 1px solid var(--line); border-radius: var(--tile-r); background: var(--tile-rest); color: var(--muted);
  cursor: pointer; text-decoration: none; list-style: none; position: relative; transition: background .15s ease, color .15s ease, border-color .15s ease; }
.tile::-webkit-details-marker { display: none; }
.tile .ico, .tile > svg { width: var(--tile-ico); height: var(--tile-ico); }
.tile:hover, .tile:focus-visible, details[open] > summary.tile, .tile.attn, .tile.is-on {
  background: var(--tile-on); border-color: var(--blue); color: #fff; text-decoration: none; outline: none; }
.tile.emerg, .tile.emerg:hover { background: var(--tile-red); border-color: var(--red); color: #fff; }
.tile.attn { animation: tile-pulse 1.8s ease-in-out infinite; }
.tile.emerg.attn { animation-name: tile-pulse-red; }
@keyframes tile-pulse { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--blue) 0%, transparent); } 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--blue) 30%, transparent); } }
@keyframes tile-pulse-red { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--red) 0%, transparent); } 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--red) 30%, transparent); } }
@media (prefers-reduced-motion: reduce) { .tile.attn { animation: none; } }
span.tile:not(.tb-page-ico):hover, .tb-page-ico { cursor: default; }
.tb-page-ico, .tb-page-ico:hover { background: var(--tile-rest); border-color: var(--line); color: var(--muted); }
/* [Shared] Save is always in its slot: dimmed (muted icon, faint blue outline) until something changed, then blue + pulse. */
.tile.tb-save[aria-disabled="true"] { background: var(--tile-rest); color: color-mix(in srgb, var(--muted) 55%, transparent);
  border-color: color-mix(in srgb, var(--blue) 35%, var(--line)); cursor: default; box-shadow: none; animation: none; }
/* [Top Bar and Menus] Right side: fixed slots Save, Add, Edit, More, then Profile; empty ones keep their room so nothing moves. */
.top-actions.tb-slots { gap: 6px; margin-left: auto; }
.tb-slot.tb-empty { display: inline-block; width: var(--tile); height: var(--tile); flex: none; }
.top-more.tb-slot .status-menu, .pm .status-menu { top: calc(var(--tile) + 6px); }
.pm { position: relative; flex: none; margin-left: 6px; }
.pm > summary { list-style: none; }
.pm-photo { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; display: block; }
.tb-profile:has(.pm-photo), .pm-face:has(.pm-photo) { padding: 0; overflow: visible; }
.tb-profile .pm-photo { border-radius: calc(var(--tile-r) - 1px); }
.pm-dot { position: absolute; top: -5px; right: -5px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px;
  background: var(--blue); color: #fff; font-size: 10px; font-weight: 700; line-height: 16px; text-align: center; border: 1.5px solid #fff; box-sizing: content-box; }
.pm-dot.is-urgent { background: var(--red); }
.pm-menu { min-width: 240px; padding: 6px; }
.pm-who { display: flex; align-items: center; gap: 10px; padding: 6px 8px 10px; min-width: 0; }
.pm-name { display: flex; flex-direction: column; min-width: 0; }
.pm-menu .top-more-item .nav-count { margin-left: auto; }
.pm-top.is-urgent { color: var(--red); }
.pm-rule { border: 0; border-top: 1px solid var(--line); margin: 6px 0; }
.pm-sec { margin: 4px 8px 2px; font-size: .75rem; letter-spacing: .04em; text-transform: uppercase; } /* Task 709: Top Task label */
.pf-photo { align-items: center; margin-top: 8px; }
.hc-version { display: flex; align-items: center; gap: 6px; }
/* [Top Bar and Menus] Left side: Back is a tile in its reserved spot; with no Back the page icon tile sits there (Dashboard grid icon). */
.top-title .back-link.tile { padding: 0; width: var(--tile); gap: 0; color: var(--muted); }
.top-title .back-link.tile:hover, .top-title .back-link.tile:focus-visible { color: #fff; }
.top-title .tb-page-ico { order: -1; }
.top-title.back-phone .tb-page-ico { display: inline-flex; }
.top-title.back-phone .back-link.tile { display: none; }
@media (max-width: 800px) {
  .top-title.back-phone .back-link.tile { display: inline-flex; width: var(--tile); }
  .top-title.back-phone .tb-page-ico { display: none; }
}
/* [Top Bar and Menus] Company pill: the company name only, one line. */
.top-title .pc-test { max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 0 1 auto; }
/* [Top Bar and Menus] Name pill (opens the section grid): same gradient and hover as the tiles, filling the whole pill; text like the title. */
.pn-switch.tile-wide { height: var(--tile); min-height: var(--tile); padding: 0 12px; border: 1px solid var(--line); border-radius: var(--tile-r); background: var(--tile-rest); }
.pn-switch.tile-wide:hover, .pn-switch.tile-wide:focus-visible, .pn-switch.tile-wide:active { background: var(--tile-on); border-color: var(--blue); color: #fff; }
.pn-switch.tile-wide:hover .pn-caret, .pn-switch.tile-wide:hover .pn-cur, .pn-switch.tile-wide:focus-visible .pn-caret, .pn-switch.tile-wide:focus-visible .pn-cur { color: #fff; }
/* [Top Bar and Menus] Section grid: standard tiles with their short labels, current section blue, Close is an X tile. */
.pn-item { background: var(--tile-rest); border-radius: var(--tile-r); color: var(--muted); }
.pn-item span { color: var(--ink); }
.pn-item .ico { width: 24px; height: 24px; }
.pn-item:hover, .pn-item:focus-visible, .pn-item.on { background: var(--tile-on); border-color: var(--blue); color: #fff; text-decoration: none; }
.pn-item:hover span, .pn-item:focus-visible span, .pn-item.on span { color: #fff; }
.pn-sheet .pn-head button.tile { width: var(--tile); }
.top .top-title h1:has(.pn-switch.tile-wide) { background: none; border: 0; padding: 0; height: auto; } /* one pill, not a pill inside a pill */
.pn-switch.tile-wide .ico { width: var(--tile-ico); height: var(--tile-ico); flex: none; }
.pn-grid .pn-item { padding: 12px 2px; }
.top .top-actions.tb-slots, .top .pn-tabs ~ .top-actions.tb-slots { margin-left: auto; } /* slots sit right beside Profile on every page */
@media (max-width: 480px) {
  :root { --tile: 34px; }
  .tb-slot.tb-empty { display: none; } /* phones: unused slots give their room to the title; Save still never appears or moves within a page */
  .top-title .pc-test { display: none; } /* phones: the Test Mode banner already says it */
  .pn-switch.tile-wide .pn-cur { display: none; } /* phones: the name gets the room; the dots and the grid show the section */
  .top-actions.tb-slots { gap: 4px; }
  .pm { margin-left: 4px; }
}

/* [Tasks and Tracker] Task 574 name pill on pages with no sections (static: same gradient, border, height and text as the switcher; no hover since it opens nothing). */
.top h1 .tb-name { display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%; height: var(--tile); padding: 0 12px;
  border: 1px solid var(--line); border-radius: var(--tile-r); background: var(--tile-rest); color: inherit; }
.top h1 .tb-name .ico { width: var(--tile-ico); height: var(--tile-ico); flex: none; }
.top .top-title h1:has(.tb-name) { background: none; border: 0; padding: 0; height: auto; }

/* [Top Bar and Menus] Task 578: the red emergency tile stays red in every state (darker on hover and open), red pulse, never blue. */
.tile.emerg, details[open] > summary.tile.emerg { background: var(--tile-red); border-color: var(--red); color: #fff; }
.tile.emerg:hover, .tile.emerg:focus-visible, details[open] > summary.tile.emerg { background: linear-gradient(180deg, var(--red), color-mix(in srgb, var(--red) 75%, var(--ink))); border-color: color-mix(in srgb, var(--red) 75%, var(--ink)); }
.tile.emerg.attn { animation-name: tile-pulse-red; }
.brand-tiles { display: flex; align-items: center; gap: 6px; flex: none; align-self: flex-start; padding: calc((48px - var(--tile)) / 2) 12px 0 4px; } /* Task 720: same size and same center line as the Top Bar tiles (48px bar) */
/* [Top Bar and Menus] Task 722: the Sprout logo in the Office left menu top row is the same size as View Site and Settings (--tile) and sits on their center line; the name under it never wraps. */
.brand.brand-stack { padding-top: calc((48px - var(--tile)) / 2); }
.brand-stack .ttm.ttm-logo { --ttm-size: var(--tile); margin: 0; }
.brand-stack .brand-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; overflow-wrap: normal; }
/* [Top Bar and Menus] Task 725: the company name sits fully below the View Site and Settings tiles and uses the full menu width (tiles float over the top row at the same spot as 1.4.130/1.4.131); an ellipsis only when a name is wider than the whole menu. */
.brand-row { position: relative; }
.brand-row .brand-tiles { position: absolute; top: 0; right: 0; z-index: 1; }
.brand-row .brand.brand-stack { width: 100%; padding-right: 12px; }
/* [Top Bar and Menus] Task 578: My Profile picture row lines up (picture tile, Picture and Remove on one center line, same height). */
.pf-photo { display: flex; align-items: center; gap: 10px; flex-wrap: nowrap; }
.pf-photo .pf-face { width: 48px; height: 48px; }
.pf-photo .btn, .pf-photo button { margin: 0; }
.top h1 .tb-name > span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* Task 574: the title never wraps */
.top-more .top-more-item span { white-space: nowrap; }

/* [Tasks and Tracker] My Files (Task 715, my_files.php): Explorer-style list, breadcrumbs, preview. */
.mf-crumbs { display: block; font-weight: 650; margin: 0 0 10px; }
.mf-crumbs a { text-decoration: none; }
.mf-name { display: inline-flex; align-items: center; gap: 8px; max-width: 100%; text-decoration: none; }
.mf-name .ico { flex: none; width: 20px; height: 20px; }
.mf-name span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mf-preview { display: block; max-width: 100%; height: auto; border-radius: 8px; }
.mf-frame { display: block; width: 100%; height: 70vh; border: 1px solid var(--line); border-radius: 8px; }
.mf-hidden-form { display: none; }
.mf-new { margin: 0 0 10px; }
.mf-save { gap: 6px; margin: 4px 0 8px; flex-wrap: nowrap; }
.mf-save select { max-width: 180px; }

/* [Tasks and Tracker] Tick All Steps confirm (Task 723, assets/js/steps-done.js) */
.steps-done-ask { border: 1px solid var(--line); border-radius: 12px; padding: 18px 20px; max-width: min(92vw, 380px); }
.steps-done-ask::backdrop { background: rgba(0, 0, 0, .35); }
.steps-done-ask h2 { margin: 0 0 6px; font-size: 1.1rem; }
.steps-done-ask p { margin: 0 0 14px; }
.steps-done-ask .row { display: flex; gap: 8px; justify-content: flex-end; flex-wrap: nowrap; }

.is-due-now { font-weight: 700; } /* shared: a task due today or overdue, title bold, same size and color (Travis, Oct 20 2026) */

/* [Top Bar and Menus] Office Top Bar Dark (Oct 20 2026, Travis): the iPhone status-bar strip above the Office Top Bar is dark (#111111), like Route; the bar itself stays light. */
/* [Bottom Menu and Companies] Office Phone Menu (Oct 20 2026, same pattern as Route): phones have no slide-out left menu; the Menu tile by the title and More on the tab bar open the shared pop-up (pn-sheet, includes/header.php #office-menu). Computers keep the left menu. */
.office-menu-ico { display: none; }
.pn-grid .pn-wide { grid-column: 1 / -1; } /* long tiles (CarPlay Preview, Android Auto Preview) take the full row so the name shows in full */
@media (max-width: 800px) {
  .top::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: env(safe-area-inset-top, 0px); background: var(--sb-bg, var(--top-bg)); pointer-events: none; }
  .top .menu-btn { display: none; } /* 1.4.144: the tile Menu button below replaces the plain one; the left slide-out menu is back on phones (Travis, Oct 21 2026) */
  .top { padding-right: calc(env(safe-area-inset-right, 0px) + 10px); } /* Profile never cut off by a notch or narrow phone */
  .top-actions, .top-actions.tb-slots { min-width: 0; flex-shrink: 1; }
  .top .pm { flex: none; }
  .top .office-menu-ico { display: inline-flex; flex: none; align-items: center; justify-content: center; }
  .top .office-menu-ico ~ .top-title .tb-page-ico, .top .office-menu-ico ~ .top-title + .tb-page-ico { display: none; }
  .office-menu { max-height: 100dvh; overflow-y: auto; }
}
.print-view .office-menu-ico { display: none; }
/* [Shared] Small button (Oct 20 2026, Travis): a real button sized like the row pills (.badge), so list rows keep one height; normal button hover. Used as class="quiet small". */
button.small, .btn.small { min-height: var(--pill-h); height: var(--pill-h); padding: var(--pill-pad, 0 9px); font-size: var(--pill-fs, .75rem); line-height: 1; border-radius: var(--pill-radius, 999px); } /* the pill-sized button = the shared pill size (Tracker 880) */
/* [Top Bar and Menus] One Top Bar button (1.4.144, Travis Oct 21 2026): every Top Bar icon button (Menu, page icon, actions, Profile) on office pages and Route is the same .tile box, radius and border. Profile keeps its count badge (.pm-dot) but no red fill, glow or pulse ring, so the sizes read the same. */
.top .tile, .top .tb-profile { width: var(--tile); height: var(--tile); min-height: var(--tile); border-radius: var(--tile-r); box-sizing: border-box; }
.top .tb-profile.emerg, .top .tb-profile.attn { animation: none; box-shadow: none; }
.top .tb-profile.emerg, .top .tb-profile.attn { background: var(--tile-rest); border-color: var(--line); color: var(--muted); }
.top .tb-profile .pm-photo { border-radius: calc(var(--tile-r) - 1px); }
/* [Top Bar and Menus] Icons-Only Top Bar (1.4.145, Travis Oct 21 2026): the Top Bar shows icons only on every page, phone and computer, office and Route. No title, name pill, company or Test pill, or button words. Buttons sit fully inside the bar with 8px above and below, never on its bottom line. */
:root { --top-h: calc(var(--tile) + 16px); }
.top { min-height: var(--top-h); padding-top: 8px; padding-bottom: 8px; box-sizing: border-box; }
.top .top-title, .top h1, .top .back-link, .top .pn-switch { font-size: 0; }
.top-title.has-back h1, .top h1 .pn-switch { height: auto; padding: 0; background: none; border: 0; min-width: 0; width: auto; }
.top h1 .pn-switch:has(svg) .pn-caret, .top h1 .pn-title, .top h1 .pn-cur { display: none; }
.top h1 .pn-switch > svg.ico { width: var(--tile); height: var(--tile); padding: calc((var(--tile) - var(--tile-ico)) / 2); box-sizing: border-box; border: 1px solid var(--line); border-radius: var(--tile-r); background: var(--tile-rest); color: var(--muted); }
.top .pn-caret { font-size: 14px; }
.top h1 .tb-name > span, .top h1 > span:not(.tile), .top-title > .badge, .top > .badge, .top h1 .tb-name:not(:has(svg)), .top .top-pills, .top .pc-test, .top h1 .badge, .top .live-clock, .top .tb-unsaved, .top-actions .top-std .ts-word { display: none; }
.top-actions .top-std { width: var(--tile); height: var(--tile); padding: 0; }
.top h1 .tb-name { width: var(--tile); padding: 0; justify-content: center; gap: 0; }
/* [Shared] Tile Menu pop-ups (1.4.145): never under the iPhone clock or home bar; the list scrolls inside. */
dialog.pn-sheet { max-height: calc(100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 16px); margin-top: calc(env(safe-area-inset-top, 0px) + 8px); margin-bottom: calc(env(safe-area-inset-bottom, 0px) + 8px); overflow-y: auto; overscroll-behavior: contain; box-sizing: border-box; }
@media (max-width: 800px) {
  .top { padding-top: calc(env(safe-area-inset-top, 0px) + 8px); }
  html { background: #111111; } /* Status Strip Dark (1.4.145): the strip above the Top Bar stays #111111 with the left menu open or closed and on overscroll; body keeps the page color */
  body.nav-open .side { padding-top: max(47px, calc(env(safe-area-inset-top, 0px) + 12px)); }
}
/* [Top Bar and Menus] Even Top Bar Gap (1.4.149, Travis Oct 21 2026): the same 8px between every Top Bar button (Menu, page actions, Profile) on office pages and Route, phone and computer; Profile no longer gets an extra margin. */
.top, header.top { column-gap: 8px; }
.top .top-actions.tb-slots { gap: 8px; }
.top .pm { margin-left: 0; }
/* [Route] Route Save on the Top Bar (Task 755, 1.4.149): the Service sheet opens under the shared Top Bar, so Menu, Save, Edit and Profile stay on screen; the in-page Save and Change buttons are only visually hidden (the Top Bar tiles click them, js/topbar-save.js). */
.field-body .field-sheet { top: calc(env(safe-area-inset-top, 0px) + var(--top-h) + 1px); }
.field-body .field-sheet-bar { padding-top: 14px; }
.field-body .tb-moved { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* [Top Bar and Menus] Profile Button Initials (Task 778, Travis Oct 21 2026): the Profile button is the person's initials in a thin ring (their photo when set), inside the same rounded-square .tile as every other Top Bar button: same size, same gray rest and blue hover/open, the line weight of the other icons. Red only on the count badge. */
.pm-av { display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; width: var(--tile-ico); height: var(--tile-ico); border: 1.6px solid currentColor; border-radius: 50%; font-size: 8.5px; font-weight: 800; letter-spacing: -.02em; line-height: 1; color: inherit; overflow: hidden; flex: none; }
.top .tile .pm-av, .pm-face .pm-av { width: calc(var(--tile-ico) + 4px); height: calc(var(--tile-ico) + 4px); }
.pm-av.has-photo { border-width: 1px; }
.pm-av[data-ini]::before { content: attr(data-ini); }
.pm-av .pm-photo, .top .tb-profile .pm-av .pm-photo { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; display: block; }
.tb-profile:has(.pm-photo), .pm-face:has(.pm-photo) { padding: 0; }
.pf-face .pm-av { width: 30px; height: 30px; font-size: 11px; }
/* [Top Bar and Menus] Profile Open State (Task 763): open looks like any open tile (blue), never red; tap outside or Esc closes it (profile_menu.php). */
.top details.pm[open] > summary.tb-profile, .top details.pm[open] > summary.tb-profile:hover { background: var(--tile-on); border-color: var(--blue); color: #fff; animation: none; box-shadow: none; }
/* [Top Bar and Menus] Profile Menu Layout (Task 766, Travis Oct 21 2026 mockup): picture + name opens My Profile with My Files at the right; Office | Customer switch; Top Task; 2x2 tiles; a bottom row of icon tiles (Help, Go to Demo, Switch Company, Sign Out). */
.pm-menu { min-width: 260px; }
.pm-who { justify-content: space-between; }
.pm-me { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 1 1 auto; color: inherit; text-decoration: none; border-radius: var(--tile-r); }
.pm-me:hover { text-decoration: none; }
.pm-me:hover .pm-name b { color: var(--blue); }
.pm-menu .tabs.sides { margin: 0 4px 8px; }
.pm-grid { margin: 0 2px 4px; }
.pm-grid .pn-item { position: relative; }
.pm-grid .pm-n { position: absolute; top: 6px; right: 6px; margin: 0; }
.pm-foot { display: flex; justify-content: space-between; gap: 8px; padding: 2px 4px 4px; }
.pm-foot .tile { flex: 1 1 0; width: auto; }
.pm-foot .pm-sub { top: -5px; right: -5px; }
/* [Top Bar and Menus] Page Icon Box (Task 778): the page icon next to Back or Menu is a full rounded-square tile at every width (the title box no longer clips it into a circle), and phones show it right of the Menu button (Task 768, rule C Task 762). */
.top .top-title:has(.pn-switch, .tb-name) { overflow: visible; }
.top .top-title.has-back h1, .top .top-title.back-phone h1 { height: var(--tile); padding: 0; border-radius: var(--tile-r); overflow: visible; flex: none; }
@media (max-width: 800px) {
  .top .office-menu-ico ~ .top-title .tb-page-ico, .top .office-menu-ico ~ .top-title + .tb-page-ico { display: inline-flex; }
}
/* [Customers] Customer Card Tiles (Task 779, Travis Oct 21 2026): Invoices, Contract, Offer Add-on and Payment Methods are the section Menu tiles (.pn-item), one row on computers, two across on phones. */
.cust-tiles { margin-top: 12px; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); }
@media (max-width: 800px) { .cust-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* [Shared] No Card Edit Arrows (Task 777, Oct 20 FINAL Task 553/Task 555): an edit fold has no arrow row; the Top Bar Edit opens it and the Top Bar Save saves it. */
details[data-edit-fold] > summary { display: none; }
details[data-edit-fold]:not([open]) { display: none; }
/* [Base] Stray Mark (Task 770): on phones the board's table edges (dashed sides of the header and first cells) drew a "(" above the first card; cards keep their own border. */
@media (max-width: 800px) {
  .command table.board tr:first-child th:first-child, .command table.board tr:first-child th:last-child,
  .command table.board tr.job-row td:first-child, .command table.board tr.job-note-row td:first-child,
  .command table.board tr.job-row td:last-child, .command table.board tr.job-note-row td:last-child { border-left: 0; border-right: 0; }
}
/* [Base] Late Warning Fits (Task 772): on phones the late warning gets the whole line, so it is cut only when the row is really full. */
@media (max-width: 480px) { .rt-strip > b.rt-warn ~ span { display: none; } } /* phones: the muted detail line gives its room (and its two gaps) to the warning */
/* [Route] Question card (task 774, 1.4.157): icon + Header, Body, Yes filled, No plain */
.field-ask.ask-q h2 { display: flex; align-items: center; gap: 8px; }
.field-ask.ask-q h2 .ico { width: 22px; height: 22px; flex: none; color: var(--accent, currentColor); }
.field-ask.ask-q #geo-ask-text { margin: 0; color: var(--ink); font-weight: 600; }
.field-ask.ask-q #geo-ask-sub { margin: 0 0 14px; }
/* [Shared] Question popup (assets/js/ask.js, 1.4.203): same Question card, title + short question, OK filled (red when it deletes), Cancel plain */
.field-ask.tt-ask h2 { margin: 0; font-size: 1.1rem; line-height: 1.3; color: var(--ink); }
.field-ask.tt-ask .tt-ask-text { margin: 0 0 8px; color: var(--muted); white-space: pre-line; overflow-wrap: anywhere; }
.field-ask.tt-ask .pn-head { gap: 8px; }
.field-ask.tt-ask .pn-head .sheet-x { flex: none; }
/* [Route] Job sheets: Products, Conditions, Equipment (task 774, 1.4.157) */
.field-ask.job-sub { width: 100%; max-width: 560px; max-height: 88dvh; margin: auto auto 0; border-radius: 16px 16px 0 0; overflow: auto; }
.field-ask.job-sub .pn-head { align-items: center; justify-content: space-between; }
.cond-open { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 0; }
.cond-open b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cond-pick { display: flex; gap: 6px; flex: none; }
.cond-mini { display: flex; gap: 4px; margin: 2px 0; }
.cond-mini i { font-style: normal; font-size: .75rem; padding: 1px 8px; border-radius: 999px; background: var(--line); color: var(--ink); white-space: nowrap; max-width: 120px; overflow: hidden; text-overflow: ellipsis; }
/* [Route] Sheets sit over the Top Bar, so their Save shows in the sheet (task 774/task 800, 1.4.157) */
.field-ask.job-sub .tb-moved { position: static; width: auto; height: auto; margin: 8px 0 0; padding: 10px 16px; overflow: visible; clip: auto; white-space: nowrap; }
#sub-ticket .row a.btn.quiet { display: none; }
.field-ask.job-sub.qc-pop { width: 100%; }
/* [Top Bar and Menus] Score tile (task 761, 1.4.157): the Scorecard score as its own Top Bar icon */
.tile.tb-score b { font-size: .85rem; font-weight: 750; font-variant-numeric: tabular-nums; line-height: 1; }
.tile.tb-score { border: 2px solid var(--line); border-radius: 999px; }
.tile.tb-score.sc-g-a, .tile.tb-score.sc-g-b { border-color: var(--grass); } .tile.tb-score.sc-g-c { border-color: var(--orange); } .tile.tb-score.sc-g-d, .tile.tb-score.sc-g-f { border-color: var(--red); }
/* [Route] Toasts sit below the Top Bar and never cover Menu or Profile (task 774, Travis Oct 21 10:38 AM; 1.4.157) */
.field-body .notices { padding-top: calc(env(safe-area-inset-top, 0px) + var(--top-h, 60px) + 8px); }
/* [Route] Page icon tile next to Menu, same as Base; it opens the Route tile Menu (Oct 21 2026, 1.4.162) */
.field-app .top .tb-page-ico { display: inline-flex; cursor: pointer; margin-left: 8px; }
/* [Top Bar and Menus] Office | Customer switch (Travis Oct 21 2026 11:04 AM): slim row, the house set-switch between two labels */
.side-switch { display: flex; align-items: center; justify-content: center; gap: 10px; margin: 6px 0; font-weight: 600; color: var(--ink); cursor: pointer; }
.side-switch span { white-space: nowrap; }
/* [Top Bar and Menus] Profile tiles: 3 columns, 2 rows (Travis Oct 21 2026 11:12 AM); a little space before the divider */
.pm-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); margin-bottom: 10px; }
/* [Top Bar and Menus] Score tile on the left after the page icon (Oct 21 2026 11:14 AM) */
.top .top-left-score { display: flex; align-items: center; flex: none; }
/* [Top Bar and Menus] Profile menu: fixed width; Top Tasks one line each, "…" only when full (Oct 21 2026 11:16 AM) */
.pm-menu { width: min(320px, calc(100vw - 24px)); min-width: 0; max-width: min(320px, calc(100vw - 24px)); box-sizing: border-box; }
.pm-menu .pm-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.pm-menu .pm-top .one-line { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pm-menu .pm-top .ico { flex: none; }
/* [Route] The office left menu on Route (office users): the same aside.side, hidden until the three-line button opens it, every width */
.field-body .side { left: -320px; transform: none; transition: left .2s ease; width: min(280px, 86%); z-index: 80; padding-top: max(47px, calc(env(safe-area-inset-top, 0px) + 12px)); }
.field-body.nav-open .side { left: 0; }
.field-body.nav-open .nav-shade { display: block; position: fixed; inset: 0; background: rgba(8, 20, 32, .45); z-index: 79; }
/* 1.4.168: Profile tile labels fit at 390 (Shared Notes, My Timesheet) */
.pm-grid .pn-item span:not(.pm-n) { font-size: 11.5px; line-height: 1.15; white-space: normal; overflow-wrap: anywhere; text-align: center; }
/* Tracker 770: Select All above the Base job cards (phone only; the table header has its own) */
.board-all { display: none; }
@media (max-width: 700px) { label.check.board-all { display: flex; margin: 4px 2px 8px; } }
@media (max-width: 700px) { .command:has(label.board-all) table.board tr:first-child { display: none; } } /* Task 530 (Tracker 770): the phone's Select All label replaces the table header row, so the old header (its dashed rounded edge was the stray "(" and an empty ~45px gap) is hidden */
/* 1.4.168 (Tracker 773, Travis 11:43 AM): with a job open, the Top Bar, the iPhone safe area and the page behind follow the
   job's status color (the same colors as .field-sheet), so there is no white band at the top. */
body.has-job { --job-bg: var(--navy); --page-bg: var(--job-bg); --top-bg: var(--job-bg); --top-line: rgba(255, 255, 255, .18); }
body.has-job.job-driving { --job-bg: var(--blue); }
body.has-job.job-paused { --job-bg: var(--orange); }
html:has(body.has-job), body.has-job { background: var(--job-bg); }
body.has-job header.top { background: var(--top-bg); box-shadow: none; /* the thin line under the Top Bar stays (Travis 8:58 AM), soft on color */ }
body.has-job header.top .tile { background: rgba(255, 255, 255, .14); border-color: rgba(255, 255, 255, .22); color: #fff; }
/* Tracker 773 Job Dock (Travis Oct 21 9:00-9:04 AM): buttons fill from the right with even room (Pause/Play, only when
   usable, far right with padding from the edge), the Team circle is the last one, and the status centers in what is left. */
.job-dock-card { padding: 8px 14px 8px 12px; }
.job-dock-card > .dock-status { flex: 1 1 auto; width: auto; }
.job-dock-card { --dock-gap: 14px; } @media (max-width: 430px) { .job-dock-card { --dock-gap: 8px; } } /* ONE gap between every dock item, ring included (Travis 12:47 PM) */
.job-dock-card .dock-end, .job-dock-card .dock-tools { gap: var(--dock-gap); }
@media (max-width: 430px) { .job-dock-card .dock-end, .job-dock-card .dock-tools { gap: var(--dock-gap); } /* tighter so the reserved Pause slot fits (Travis 12:46 PM) */ }
/* 1.4.168 (Travis 11:47 AM): no lingering highlight on Job Dock / bottom bar buttons after a tap (iOS sticky hover/focus).
   The tap look comes only from real hover devices; touch gets no fill. */
.job-dock button:is(:hover, :focus, :focus-visible, :active), .phone-dock :is(a, button):is(:hover, :focus, :active) { background: transparent; box-shadow: none; outline: none; }
.job-dock .dock-mini { -webkit-tap-highlight-color: transparent; }
@media (hover: hover) { .job-dock .dock-mini:hover { background: rgba(255, 255, 255, .1); } }
/* The one person ring (standing rule, Travis Oct 21 2026 11:48-11:50 AM): .pm-av from includes/profile_menu.php
   pm_face_html() (photo or initials), sized only by these shared modifiers. No per-page avatar styles. */
.pm-av.av-md { width: var(--tile); height: var(--tile); }
.pm-av.av-lg { width: 48px; height: 48px; font-size: 15px; margin: 0 auto 4px; }
span.pm-av.av-lg, span.pm-av.av-md { display: flex; align-items: center; justify-content: center; line-height: 1; overflow: hidden; }
/* Shared tooltip, ONE system (assets/js/tips.js, Spot Clean Oct 21 2026): the dark tip that opens underneath the item, on
   the first hover or tap. Every icon-only button and tile has data-tip + aria-label (rules check "Icon button rule"); title= becomes the tip. */
[data-tip]:not([data-tip-auto]) { position: relative; } /* kept from the old tip so nothing shifts */
.tt-tip { position: fixed; left: 0; top: 0; z-index: 2147482000; max-width: 260px; padding: 4px 8px; border-radius: 6px; background: var(--ink); color: #fff; font-size: 12px; font-weight: 600; line-height: 1.2; pointer-events: none; opacity: 0; visibility: hidden; transition: opacity .1s; }
.tt-tip.on { opacity: 1; visibility: visible; }
/* Flip card (Travis 12:04 PM): the ⇄ sits on the person ring's corner; tapping it flips the menu like a card. */
.pm-who.has-flip, .pm-who-ring { position: relative; }
.pm-flip { position: absolute; z-index: 3; width: 22px; height: 22px; min-height: 22px; padding: 0; border-radius: 50%; font-size: 13px; line-height: 1; display: inline-flex; align-items: center; justify-content: center; text-decoration: none; background: var(--blue); color: #fff; border: 2px solid #fff; }
.pm-who.has-flip .pm-flip { position: relative; left: auto; top: auto; margin-left: auto; flex: none; } /* right end of the name row (Travis 1:06 PM) */
.pm-who-ring { display: flex; justify-content: flex-end; }
.pm-who-ring .pm-flip { position: relative; width: 34px; height: 34px; font-size: 18px; }
.pm-flipping { transition: transform .26s ease-in; transform: perspective(800px) rotateY(90deg); }
/* Route top (Travis Oct 21 2026 12:23 PM, replaces the keep-line note on Tracker 773): NO line under the Top Bar on
   Route; one color from the iPhone status bar through the Top Bar and the area below it, driven by ONE variable per
   state: --route-top-bg (day view = the page gray; an open job = its status color). Change it here, every Route screen follows. */
body.field-body { --route-top-bg: var(--paper); --page-bg: var(--route-top-bg); --top-bg: var(--route-top-bg); --top-line: transparent; }
body.field-body.has-job { --route-top-bg: var(--job-bg); }
body.field-body header.top { border-bottom-color: transparent; }
/* Tracker 774 Route Finish Products: read-only list until the Top Bar Edit (shared .sp panel, .sp-ro state) */
.sp-edit-all { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); } /* shows as the Top Bar Edit tile */
.sp.sp-ro .sp-amt, .sp.sp-ro [data-sp-do="edit"], .sp.sp-ro [data-sp-do="remove"], .sp.sp-ro .sp-add, .sp.sp-ro .sp-edit { display: none; }
.sp:not(.sp-ro) .sp-ro-only { display: none; }
.sp.sp-ro .sp-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.sp.sp-ro .sp-main { flex: 1 1 100%; }
/* Sheet fit (Travis Oct 21 2026 12:38 PM): every Sheet. The page behind is locked while one is open, and the Sheet
   fits the visible viewport (--vvh / --kb from tips.js), so the keyboard never covers its content. */
html.sheet-open, html.sheet-open body { overflow: hidden; overscroll-behavior: none; }
/* Scrollbar space rule (1.4.219) rolled back in 1.4.220 (Travis Oct 21 2026 11:40 PM CT: "menu borked and fading and links not working or sluggish"). */
/* [Office PC] Oct 22 2026 (Travis Oct 21 11:23 PM "it makes the scroll disaappear"): only while a popup lock is on, and only
   on computers, the page keeps its scrollbar space so nothing shifts sideways. Never a page-wide rule (see 1.4.220). */
@media (min-width: 801px) {
  html.sheet-open, html.mt-lock, html.ttv-lock { scrollbar-gutter: stable; }
  /* Travis Oct 22 2026 7:57 PM: no gray strip on the left menu while a Sheet is open. Its scrollbar keeps its space and goes see-through. */
  html.sheet-open aside.side, html.mt-lock aside.side, html.ttv-lock aside.side { scrollbar-color: transparent transparent; }
}
dialog[open].job-sub, dialog[open].field-ask, dialog[open].pn-sheet { max-height: calc(var(--vvh, 100dvh) - env(safe-area-inset-top, 0px) - 12px); margin-bottom: var(--kb, 0px); }
.qc-out { min-height: 0; } /* answer box only when there is an answer (Travis 12:39 PM) */
/* Quick Calc help (Travis Oct 21 2026 12:39 PM): plain line + 2-3 examples always under the input; no empty answer box. */
.qc-quick { display: grid; gap: 6px; margin: 6px 0 8px; }
.qc-quick .qc-guide { margin: 0; font-size: .82rem; line-height: 1.35; }
.qc-quick .qa-exs { display: flex; flex-wrap: wrap; gap: 6px; }
.qc-quick.qc-typing { display: none; } /* Tracker 886: hides once typing starts (tank.js) */
.qc-out.qc-empty { display: none; }
.qc-ask { display: flex; gap: 8px; align-items: center; }
.qc-ask .qc-q { flex: 1; min-width: 0; }
.qc-mic.on { background: var(--red); border-color: var(--red); color: #fff; }
/* Job Dock Pause slot (Travis Oct 21 2026 12:46 PM): the far-right spot is always kept; empty when Pause can't be used. */
.job-dock .dock-slot { visibility: hidden; pointer-events: none; background: none; border: 0; box-shadow: none; }
.job-dock .job-dock-card { column-gap: var(--dock-gap); } .job-dock .dock-mini { margin: 0; } /* one gap: status → icons */
/* Job Dock room (Travis 12:47-12:48 PM): ring removed, so the status gets its full label, one equal gap, and the Pause slot. */
@media (max-width: 430px) { .job-dock-card { --dock-gap: 10px; } }
.job-dock #dock-state { white-space: nowrap; }
.qc .qc-ask > .qc-q { flex: 1 1 auto; width: auto; min-width: 0; margin: 0; }
.qc .qc-ask > .qc-mic { flex: 0 0 var(--tile, 40px); width: var(--tile, 40px); min-width: 0; height: var(--tile, 40px); padding: 0; margin: 0; display: inline-grid; place-items: center; }
.qc .qc-ask > .qc-mic[hidden] { display: none; }
/* Toast spot (Travis Oct 21 2026 12:54-12:57 PM; standing rule "Toast spot", rules check): ONE fixed spot per layout
   (Route phone, Route PC, Office phone, Office PC), the same on every page of that layout: laid over the Top Bar itself,
   one line at the Top Bar's height, so it never covers a header or page content. Change --toast-top here only. */
:root { --toast-top: calc(env(safe-area-inset-top, 0px) + 6px); } /* 40px toast inside the ~52px Top Bar */
.content > .notices, body.field-body .notices { position: fixed; z-index: 60; top: 0; bottom: auto; left: 0; right: 0; height: 0; max-width: 480px; margin: 0 auto; padding: var(--toast-top) 12px 0; pointer-events: none; display: block; }
.content > .notices > .toast, body.field-body .notices > .toast { min-height: 40px; max-height: 40px; margin: 0; padding-top: 0; padding-bottom: 0; box-sizing: border-box; pointer-events: none; box-shadow: 0 8px 24px rgba(16, 24, 40, .22); }
.content > .notices > .toast span, body.field-body .notices > .toast span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; overflow-wrap: normal; }
.content > .notices .toast-x, .content > .notices a, .content > .notices button { pointer-events: auto; }
@media (min-width: 801px) { body:not(.field-body) .content > .notices { left: 220px; } } /* Office PC (left menu is 220px, .side): centred over the Top Bar, right of the left menu */
/* Layers (Travis Oct 21 2026 1:04 PM; docs/components.md "Layers"): one shared order. Page content < Job Dock < job sheet
   < Top Bar (its Profile / ⋯ menus drop from it) < toasts. Open menus win: a toast hides while a Top Bar menu or the
   Menu is open, and Sheets (<dialog>) are always the browser's top layer. A closed menu is display:none, never peeking. */
:root { --z-dock: 30; --z-jobsheet: 25; --z-top: 45; --z-toast: 60; --z-menu: 70; }
header.top, .top { z-index: var(--z-top); }
.field-sheet { z-index: var(--z-jobsheet); }
.content > .notices, body.field-body .notices { z-index: var(--z-toast); }
body:has(header.top details[open]) .notices, body.nav-open .notices, body:has(dialog[open]) .notices { visibility: hidden; }
header.top details:not([open]) > :not(summary) { display: none !important; }
.notices:empty { display: none; }
/* Flip ⇄ (Travis 1:06 PM): a Top Bar-style icon button, 44px tap target, off the ring. Profile menu ring = the shared ring as is. */
.pm-flip, .top .pm-who .tile.pm-flip, .pm-who .tile.pm-flip { width: 28px; height: 28px; min-height: 28px; min-width: 28px; padding: 0; border-radius: 8px; font-size: 16px; background: var(--tile-rest); color: var(--muted); border: 1px solid var(--line); }
.pm-flip::before { content: ""; position: absolute; left: 50%; top: 50%; width: 44px; height: 44px; transform: translate(-50%, -50%); } /* invisible 44px tap area */
.pm-who .pm-face { background: none; border: 0; padding: 0; display: inline-flex; }
/* [Top Bar] 1.4.211 (Travis Oct 21 2026 9:43 PM "put same size as top bar one"): the Profile menu's picture is the same size as
   the Top Bar Profile picture (the tile size, var(--tile)); same shared ring. */
.pm-who .pm-face .pm-av { width: var(--tile); height: var(--tile); border-radius: var(--tile-r); font-size: 12px; }

/* Person in a box (Travis Oct 21 2026 1:13 PM; standing rule "Person in a box", rules check): when the shared person
   ring sits inside a square button or tile (Top Bar Profile, the 'You' picture tile, any .tile), there is no circle:
   the photo or initials fill the box itself with the box's rounded corners. Every page, Route and Office, phone and PC. */
.tile:has(> .pm-av) { position: relative; }
.tile > .pm-av, .top .tile > .pm-av { position: absolute; inset: 0; width: auto; height: auto; border: 0; border-radius: inherit; font-size: 12px; }
.tile > .pm-av .pm-photo, .top .tb-profile .pm-av .pm-photo { border-radius: inherit; }
/* ⇄ Switch Sheet (Travis 1:29 PM): shared pull-up Sheet; a check on the current destination; companies below Office/Customer. */
#pm-swap .pn-item { position: relative; }
#pm-swap .sw-check { position: absolute; top: 6px; right: 8px; font-style: normal; font-weight: 700; color: var(--grass-dark, var(--ink)); }
#pm-swap .sw-cos { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line); }
#pm-swap .sw-cos[hidden] { display: none; }
#pm-swap .sw-div { grid-column: 1 / -1; width: 100%; margin: 2px 0; border: 0; border-top: 1px solid var(--line); } /* Switch picker: a divider between each company (Travis Oct 21 2026) */
.portal-top .pm-flip { position: relative; left: auto; top: auto; flex: none; margin-left: 4px; } /* portal header way back to Office (Travis 1:30 PM) */

/* [Top Bar and Menus] Left Menu on top (Travis Oct 21 2026 1:57 PM): on phones the slide-out Menu is the top layer, full height from the
   status bar down, covering the Top Bar on its side (company name at the top, its own X). Top Bar icons do not move. Floating pills hide while it is open. */
.side-x { display: none; }
@media (max-width: 800px) {
  .side, body.nav-open .side { z-index: var(--z-menu); top: 0; bottom: 0; height: 100dvh; padding-top: calc(env(safe-area-inset-top, 0px) + 8px); }
  body.nav-open .nav-shade { z-index: calc(var(--z-menu) - 1); }
  .side .side-x { display: inline-flex; align-items: center; justify-content: center; flex: none; }
  body.nav-open .ttf, body.nav-open .ttmo, body.nav-open .ttl-say, body.nav-open .ttl-roam, body.nav-open .notices { visibility: hidden; }
}

/* [Route] Week strip, thinned (Travis Oct 21 2026 2:03 PM): only the dates slide (js/week-swipe.js [data-week-track]); ‹ › stay fixed at the ends. */
.field-days { padding: 4px 8px 6px; gap: 2px; align-items: center; }
.field-days-track { display: flex; flex: 1 1 auto; min-width: 0; gap: 4px; justify-content: center; overflow: hidden; }
/* Oct 22 2026 (Travis Oct 21 11:36 PM, week strip swipe): the rail holds 3 weeks side by side; the middle one shows. */
.field-days-track { display: block; position: relative; }
.field-days-rail { display: flex; width: 300%; transform: translateX(-33.3333%); will-change: transform; }
.field-week { flex: 0 0 33.3333%; display: flex; gap: 4px; justify-content: center; min-width: 0; }
.field-days .field-day { height: 44px; border-radius: 10px; }
.field-days .field-step { flex: 0 0 32px; height: 44px; }
.field-day span { font-size: .66rem; }
.field-day b { font-size: 1rem; }
.field-month { padding-top: 6px; }
@media (max-width: 800px) { .side { overflow-x: hidden; } .side .brand-row { min-width: 0; } }

/* Task 531 Load Out / Refill card: the bold Water line above the product summary (Travis Oct 20 2026) */
.task-stop .lo-water { display: block; font-weight: 750; }

/* Task 523 Order Stops bar under the Route map: plain buttons left, Save far right (Travis Oct 20 2026) */
.po-bar { display: flex; align-items: center; gap: 8px; padding: 8px 12px 0; flex-wrap: nowrap; min-width: 0; }
.po-bar .po-hint { flex: 1 1 auto; min-width: 0; font-size: .8rem; }
.po-bar .po-save { margin-left: auto; flex: none; }
.route-pin.po-on { background: var(--grass); color: var(--ink); }

/* [Shared] Whole-row drag (Task 524, js/row-drag.js): one look for Base stops, Dashboard widgets and Today's Teams. */
.rd-lift { transform: scale(1.02) rotate(-.4deg); box-shadow: 0 18px 40px rgba(22, 58, 95, .25); position: relative; z-index: 10; opacity: .95; }
tr.rd-lift { transform: none; outline: 2px solid var(--blue); outline-offset: -2px; }
.rd-over { outline: 2px dashed var(--pal-green); outline-offset: -2px; background: color-mix(in srgb, var(--pal-green) 6%, transparent); } /* Task 878: the same green dashed spot everywhere */
body.rd-on, body.rd-on * { user-select: none; -webkit-user-select: none; cursor: grabbing; }
.job-row, .dw, .td-person { -webkit-touch-callout: none; }

/* Task 532 Load Out / Refill fill timer (Start, Pause, Stop icon tiles + minutes so far) */
.lo-fill { display: flex; align-items: center; gap: 6px; margin: 0; }
.lo-fill-t { font-size: .78rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.task-stop .field-acts { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; }
/* Task 532 (Travis Oct 21 2026 2:25 PM): Load Out / Refill card = title + short status; tap opens the page (job Products list). Skip and Drive grayed out until Loaded. */
.task-stop.lo-card { cursor: pointer; }
.field-acts .field-skip[disabled], .field-acts .field-drive[disabled] { opacity: .45; cursor: not-allowed; pointer-events: none; }
.lo-page h3 { margin: 10px 0 4px; font-size: 15px; }
.lo-page .sp-sub { margin: 0 0 4px; }
.task-stop.lo-mini { min-height: 0; padding-top: 6px; padding-bottom: 6px; cursor: pointer; } /* Task 532 one-line Loaded (Travis 2:56 PM) */
.task-stop.lo-mini > i { width: 24px; height: 24px; }
/* Top Bar right side, one line (Travis Oct 21 2026 3:00 PM): every right-side button shares one height and vertical center.
   The Profile <details> was a block, so its inline-flex summary sat on a text baseline 3px above the other tiles. */
header.top details.pm { display: flex; align-items: center; align-self: center; height: auto; margin: 0; }
header.top details.pm > summary.tb-profile { display: flex; vertical-align: middle; }
header.top .top-actions > .tile, header.top .top-actions > form > .tile, header.top details > summary.tile { align-self: center; }
/* Contract Price card (Tracker 852): big number left, shared .sx-gauge rings right; edit fields fold under the down arrow. */
.cp-hero { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 6px 14px 12px; flex-wrap: wrap; }
.cp-big { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cp-big b { font-size: 2rem; font-weight: 750; letter-spacing: -.02em; font-variant-numeric: tabular-nums; line-height: 1.1; }
.cp-big .muted { font-size: .85rem; }
.cp-gauges { gap: 18px; }
/* [Billing] Contract page card hints sit inside the card padding, in line with the card title (Tracker 852 fix). */
.set-list > .hint-box { padding: 0 18px; }
.cp-edit { border-top: 1px solid var(--line, #e6e6e6); }
.cp-edit summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 10px; padding: 12px 14px; font-weight: 600; }
.cp-edit summary::-webkit-details-marker { display: none; }
.cp-edit summary::after { content: ""; margin-left: auto; width: 7px; height: 7px; border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted); transform: rotate(45deg) translateY(-2px); flex: none; }
.cp-edit[open] summary::after { transform: rotate(-135deg) translateY(-1px); }
.cp-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px 14px; padding: 0 14px 14px; }
.cp-form label { display: flex; flex-direction: column; gap: 4px; font-size: .85rem; color: var(--muted); }
.cp-form label.check { flex-direction: row; align-items: center; color: var(--ink); }
.cp-form .row { grid-column: 1 / -1; }
@media (max-width: 600px) { .cp-big b { font-size: 1.7rem; } .cp-gauges .sx-gauge { width: 68px; height: 68px; } }

/* [Shared] 1.4.205 look fixes (Travis Oct 21 2026 8:34 PM). Hint text: one darker token so tips are easy to read. */
:root { --hint: color-mix(in srgb, var(--muted) 55%, var(--ink)); }
.hint, .hint-box, .hint-more, .muted.hint, .qa-idle, .hint-dl dt { color: var(--hint); }
/* [Shared] 1.4.x Sign-in/portal footer pill readable (Travis Oct 23 2026: "That grey text hard to see at bottom"). The
   .muted.hint rule above was turning the footer dark-gray on the dark pill. One token pair for text over the scene scrim,
   same in Light and Dark (the pill is always dark over the business-type background). Measured >= 4.5:1 (WCAG AA). */
:root { --scrim-bg: rgba(17, 17, 17, .78); --on-scrim: #F2F3F5; --on-scrim-link: #FFFFFF; }
.login > .hint, .login > .muted.hint, .login > .login-foot.muted.hint { background: var(--scrim-bg); color: var(--on-scrim); }
.login > .hint a, .login > .login-foot a { color: var(--on-scrim-link); }
:where(input, textarea)::placeholder { color: var(--hint); }
/* [Route] Quick Calc Sheet on a computer = the phone job site Sheet (Travis Oct 21 2026 10:01-10:04 PM: "slide up from bottom
   yes, but stay on bottom", "they are poking out from bottom literally", "look like the phone on jobsite"). The 1.4.205 middle
   placement is gone: it uses the shared .field-ask.job-sub bottom Sheet as is (flush on the bottom edge, rounded top corners,
   560px wide, centered) plus the Sprout Mini polish below. */
/* [Shared] Sprout Mini (Travis Oct 21 2026 10:04 PM "now make it awesome"): the shared bottom Sheet class (.sprout-mini on a
   dialog.field-ask.job-sub), Quick Calc first, the Task Card next. On a computer: flush on the bottom edge like the phone job
   site Sheet, rounded top corners, soft shadow, a grab handle, dimmed backdrop; slides up eased, slides down on Esc, tap
   outside or Close (assets/js/sprout-mini.js). Phones keep their Sheet as is. */
@keyframes sm-up { from { transform: translateY(100%); } to { transform: none; } }
@keyframes sm-down { from { transform: none; } to { transform: translateY(100%); } }
@keyframes sm-dim { from { opacity: 0; } to { opacity: 1; } }
@media (min-width: 801px) {
  dialog[open].sprout-mini { box-shadow: 0 -10px 36px rgba(11, 42, 69, .18), 0 -1px 0 var(--line); padding-top: 18px; }
  dialog[open].sprout-mini::before { content: ""; position: absolute; top: 7px; left: 50%; width: 40px; height: 5px; margin-left: -20px; border-radius: 999px; background: var(--line); }
  dialog.sprout-mini::backdrop { background: rgba(8, 20, 32, .38); }
}
/* Oct 22 2026 (Travis 4:59 AM CT, Route Quick Calc on the iPhone): every Sprout Mini, phone too, slides up and down the
   same way, stays docked at the bottom, centered, and rides on the keyboard edge (--kb from tips.js). */
dialog[open].sprout-mini { position: fixed; inset: auto 0 var(--kb, 0px) 0; margin: 0 auto; transition: none; }
@media (prefers-reduced-motion: no-preference) {
  dialog[open].sprout-mini { animation: sm-up .34s cubic-bezier(.22, .9, .25, 1); }
  dialog[open].sprout-mini::backdrop { animation: sm-dim .3s ease-out; }
  dialog[open].sprout-mini.is-closing { animation: sm-down .22s cubic-bezier(.4, 0, 1, 1) forwards; }
  dialog[open].sprout-mini.is-closing::backdrop { animation: sm-dim .22s ease-in reverse forwards; }
}
.qc-quick .qc-guide { display: flex; align-items: center; gap: 6px; color: var(--ink); font-size: .86rem; font-weight: 600; }
.qc-quick .qc-guide svg { flex: none; color: var(--grass); }
.qc-out:not(.qc-ans) { color: var(--ink); font-weight: 600; }
/* [Shared] Question popup text box (ttPrompt, Tracker 875) */
.field-ask.tt-ask .tt-ask-in { width: 100%; margin: 0 0 8px; }
/* [Shared] Person in a box everywhere (Travis Oct 21 2026 8:50 PM "square that": look exactly like the Top Bar Profile
   picture). Every person picture is the Top Bar tile shape: rounded square (tile radius 10 of 36 = 28%), the photo fills
   the box, initials sit on the tile background. Replaces the round ring outside a tile. */
.pm-av { border: 1px solid var(--line); border-radius: 28%; background: var(--tile-rest); color: var(--ink); overflow: hidden; }
.pm-av.has-photo { border: 0; }
.pm-av .pm-photo, .top .tb-profile .pm-av .pm-photo { border-radius: inherit; }
.field-person b, .tech-dot, .mail-avatar { border-radius: 28%; }

/* [Profile] Profile Part 1 (plans/profile-overhaul.md, Travis Oct 21 2026 10:19-10:24 PM): header with the shared
   rounded-square person ring, At a Glance gauges (shared .sx-gauge), Mine tiles (shared .pn-grid) and one Settings form. */
.pf-hero { display: flex; align-items: center; gap: 14px; }
.pf-hero .pf-face { flex: none; }
.pf-hero .pm-av.av-lg { margin: 0; }
.pf-hero .pf-who { min-width: 0; }
.pf-hero h2 { margin: 0; }
.pf-hero p { margin: 2px 0 0; }
.pf-gauges { justify-content: space-around; }
.pf-gauge { text-decoration: none; color: inherit; border-radius: 12px; padding: 4px; }
/* Shared gauge hover moved to the .sx-gauge rule below (Oct 22 2026) */
.pf-facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 14px; margin: 12px 0; }
.pf-facts dt { color: var(--muted); }
.pf-facts dd { margin: 0; min-width: 0; }
#pf-settings > .card:last-child { margin-bottom: 16px; }
@media (max-width: 600px) {
  .pf-gauges { flex-wrap: wrap; gap: 8px; }
  .pf-gauge { flex: 1 1 40%; }
  .pf-gauge .sx-gauge { margin: 0 auto; width: 76px; height: 76px; }
}
/* [Profile] Quick Settings tiles (Travis 10:29 PM, like a phone Control Center): starred switches, tap to flip, saves at once. */
.pf-quick { margin: 0; }
.pf-quick .pn-item { height: auto; min-height: 0; width: auto; margin: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 12px 6px; font: inherit; font-weight: 700; line-height: 1.2; cursor: pointer; box-shadow: none; }
.pf-quick .pn-item:not(.on) { background: var(--tile-rest); color: var(--muted); border: 1px solid var(--line); }
.pf-qs-st { font-style: normal; font-size: .75rem; font-weight: 600; opacity: .85; }
.pf-sw { justify-content: space-between; align-items: center; gap: 10px; flex-wrap: nowrap; padding: 4px 0; }
.pf-sw .pf-qs { flex: 1 1 auto; text-align: left; margin: 0; }
.pf-sw .pf-qs.on { font-weight: 650; }
.pf-star { flex: none; font-size: 18px; line-height: 1; }
.pf-star.on { color: var(--orange); }

/* [Top Bar] Section picker tap target (Oct 22 2026, Travis 5:17 AM CT: only the tiny arrow responded): the page icon and the
   ▾ open the picker together, each at least 44px tall. */
.top .tb-page-ico.pn-ico-tap { cursor: pointer; min-height: 44px; min-width: 44px; }
.top h1 .pn-switch { min-height: 44px; min-width: 44px; margin-left: -12px; padding-left: 12px; }
/* [Route] Left Menu taps (Oct 22 2026, Travis 5:15 AM CT: "Clicking any link in menu just closes menu and doesn't go anywhere"):
   on Route the shade sat above the menu (79 over 70), so every tap hit the shade and only closed the menu. The menu is on top. */
.field-body.nav-open .side { z-index: 80; }
/* [Shared] Page changes without a flash (Oct 22 2026, Travis 5:20-5:24 AM CT: "If we can't get rid of doing that, is there a way
   to transition it hide it something", "All of site especially live pages shouldn't do this right?", "And no jumping while
   doing it?"): when a full page change can't be avoided, the old page crossfades into the new one (cross-document View
   Transitions, iOS 18+ Safari / WebKit app, Chrome); the page color fills the whole screen so nothing paints white or black
   below short pages; the Top Bar and bottom bar hold still during the fade. */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .16s; animation-timing-function: ease-out; }
html { background: var(--page-bg, var(--paper)); }
body { min-height: 100dvh; }
.content > header.top:only-of-type, .field-app > header.top { view-transition-name: tt-top; }
@media (prefers-reduced-motion: reduce) { ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; } }
/* [Shared] Soft page updates (Oct 22 2026, Travis 5:15-5:52 AM CT): the swapped part keeps the page's column layout. */
.soft-root { display: flex; flex-direction: column; flex: 1 0 auto; min-width: 0; }

/* [Shared] Gauge hover (Travis Oct 21 2026 10:49 PM: "on hover ... just have a card border with it maybe (can change color
   too)"): any tappable gauge (a link or button holding .sx-gauge: Profile, Sprout's Clients, Status, widgets, tank
   calc) gets a card border in the accent color, a small lift and a soft shadow. No layout shift: the border is always
   there, only its color changes, and the lift is a transform. */
:is(a, button):has(> .sx-gauge, > figure > .sx-gauge) { border: 1px solid transparent; border-radius: 12px; transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease; }
@media (hover: hover) {
  :is(a, button):has(> .sx-gauge, > figure > .sx-gauge):hover { border-color: var(--accent, var(--blue)); box-shadow: 0 6px 18px rgba(11, 42, 69, .12); transform: translateY(-2px); }
}
:is(a, button):has(> .sx-gauge, > figure > .sx-gauge):focus-visible { border-color: var(--accent, var(--blue)); }
/* [Tasks] Task number on every row (Oct 22 2026, Travis Oct 21 10:34 PM: replaces the Call / Follow-up chip) */
.tk-num { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--muted); font-size: .82em; }
/* [Base] Tasks today strip is one tap target that opens Today (Oct 22 2026, Travis Oct 21 11:09 PM) */
a.rt-strip.tk-strip { color: inherit; text-decoration: none; cursor: pointer; }
@media (hover: hover) { a.rt-strip.tk-strip:hover { border-color: var(--accent, var(--blue)); } }
/* [Tasks] Task Card (Oct 22 2026, Travis Oct 21 10:01-10:04 PM): the task opens in the shared Sprout Mini (bottom-docked,
   centered, 560px), the list keeps the full width behind it. */
.task-wrap { grid-template-columns: minmax(0, 1fr); }
/* [Tasks] Task Card buttons keep their own size (the shared Sheet makes buttons full width); the action grid fills its cells. */
.task-card .task-card-body button, .task-card .task-card-body a.btn { width: auto; }
.task-card .task-card-body .row:not(.task-panel-top) > button, .task-card .task-card-body .row:not(.task-panel-top) > a.btn { width: 100%; }
.task-card .task-card-body, .task-card .task-card-body textarea, .task-card .task-card-body form > * { flex-shrink: 0; } /* the Sheet is a flex column: nothing inside gets squeezed (the title box kept its full height) */
/* [Tasks] Task Card is ONE scroll (Travis Oct 22 2026 8:19 PM: "Make it ONE scroll for the whole card, with no inner scroll
   box ... the card fits with the Comments box and Comment button reachable, and nothing jumps when typing a comment"). The
   shared .field-ask form box scroll is off here; the Sheet itself scrolls, with its scrollbar space kept (scrollbar-gutter). */
dialog.task-card .task-form { max-height: none; overflow: visible; }
/* [Shared] A toast inside an open modal (toast.js, Travis Oct 22 2026 8:14 PM) stays on top of the modal's own content. */
:is(dialog#task-card, dialog)[open] > .notices[data-dock] { z-index: 60; }
body:has(dialog[open]) :is(dialog#task-card, dialog)[open] > .notices[data-dock] { visibility: visible; } /* page toasts hide under a sheet; the sheet's own do not */
/* [Shared] The DND dot in a Sheet header (Travis Oct 22 2026 8:13 PM): dot size, next to the title. */
dialog .pn-head > button.sx-dot { flex: none; width: .75rem; min-width: 0; height: .75rem; margin: 0 .5rem; }
dialog.task-card .task-card-body form > *, dialog.task-card .task-card-body > * { margin-top: 0; margin-bottom: .5rem; }
dialog.task-card .task-card-body .task-comment { resize: none; min-height: 4.5rem; max-height: 4.5rem; overflow-y: auto; }
/* [Tracker] At a Glance (Oct 22 2026, Travis Oct 21 11:11 PM "know wtf is going on"): Building Now, Up Next, Waiting on You,
   Just Shipped; Linear-style rows (number, title, status, priority, owner), one tap opens the Task Card. */
.tr-gl-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 12px; }
.tr-gl h3 { margin: 0 0 6px; font-size: .95rem; }
.lin-row { display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 4px 8px; border-radius: 10px; color: inherit; text-decoration: none; border: 1px solid transparent; }
.lin-row + .lin-row { border-top-color: var(--line); border-radius: 0; }
.lin-row .lin-t { flex: 1; min-width: 0; }
.lin-row .lin-n { flex: none; width: 22px; height: 22px; border-radius: 50%; background: var(--paper); display: inline-flex; align-items: center; justify-content: center; font-size: .78rem; font-weight: 700; }
.lin-row .lin-who { flex: none; color: var(--muted); font-size: .82rem; }
@media (hover: hover) { .lin-row:hover { background: var(--paper); } }
.tr-card-full { margin-left: auto; margin-right: 8px; width: auto; }

/* Read-first Task Card (Oct 22 2026; Travis 7:05 AM): chips, quick replies, Sprout's Ask line; the rest behind More. */
.tk-read { display: flex; flex-direction: column; gap: 8px; flex-shrink: 0; }
.tk-replies, .tk-ask-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.pick-chip.tk-pick { width: auto; padding: 0; border: 0; background: none; }
.tk-edit > * { width: auto; min-height: 36px; }
.tk-reply, .tk-ask-keep, .tk-ask-undo, .tk-ask-pick { width: auto; min-height: 36px; }
.tk-ask-in { width: 100%; }
.tk-ask-bar:empty { display: none; }
.tk-more { flex-shrink: 0; }
.tk-more > .tk-more-sum { cursor: pointer; min-height: 36px; display: flex; align-items: center; color: var(--muted); }

/* Section picker: icon + ▾ in ONE button (Oct 22 2026, Travis 7:24 AM "Menu arrow not fixed still"). */
.top h1 .pn-switch.pn-has-ico { display: inline-flex; align-items: center; gap: 2px; min-width: 44px; min-height: 44px; padding: 0 8px 0 4px; }
.top h1 .pn-switch.pn-has-ico > .tb-page-ico, .top-title.back-phone h1 .pn-switch.pn-has-ico > .tb-page-ico { display: inline-flex; order: 0; margin: 0; min-width: 0; min-height: 0; width: auto; height: auto; padding: 0; border: 0; background: none; cursor: pointer; }
.top h1 .pn-switch.pn-has-ico > .pn-caret { display: inline; }

/* My Tasks Sheet on Route (Oct 22 2026, Travis 7:05 AM): rows open the shared Task Card. */
.rt-tasks { display: flex; flex-direction: column; flex-shrink: 0; overflow-y: auto; }
.rt-tasks > button.lin-row { width: 100%; background: none; text-align: left; font: inherit; cursor: pointer; }

/* Task 878 Workspace Full Screen (assets/js/workspace.js): the Top Bar and menu hide, the grid keeps its layout, the hidden
   Full Screen row sits on top (a drop spot while editing), a corner avatar shows on hover to get out. */
html.ws-full header.top, html.ws-full aside.side, html.ws-full .phone-tabs { display: none; }
html.ws-full .dw-fsrow { grid-column: 1 / -1; height: var(--ws-gain, 64px); border-radius: 12px; }
html.ws-full .dash-editing .dw-fsrow { border: 2px dashed var(--pal-green); }
html.ws-full .dw-fsrow.rd-over { background: color-mix(in srgb, var(--pal-green) 12%, transparent); }
.ws-corner { position: fixed; top: 8px; right: 8px; z-index: 90; opacity: 0; transition: opacity .2s; }
.ws-corner:hover, .ws-corner:focus-visible { opacity: 1; }
@media (hover: none) { .ws-corner { opacity: .7; } } /* Task 878: phones have no hover: the way out always shows */
/* Full Screen Menu button (Oct 22 2026, Travis 5:31 PM "start it... dont break app and route/base"): one small shared tile at the
   top left brings the menu back over the page; the menu shows as it always does (phones: the normal slide-out). */
.tile.ws-fab { position: fixed; top: calc(env(safe-area-inset-top, 0px) + 8px); left: 8px; z-index: 90; opacity: .55; transition: opacity .2s; }
.ws-fab:hover, .ws-fab:focus-visible, html.ws-side .ws-fab { opacity: 1; }
html.ws-full.ws-side aside.side, html.ws-full body.nav-open aside.side { display: flex; z-index: 80; box-shadow: 0 0 40px rgba(8, 20, 32, .35); }
html.ws-full.ws-side .ws-fab { left: 228px; }
@media (max-width: 800px) { html.ws-full.ws-side .ws-fab { left: auto; right: 8px; top: auto; bottom: calc(env(safe-area-inset-bottom, 0px) + 12px); } }
/* Sections under their page in the left menu (Sprout, Tracker; Oct 22 2026): the shared sub row, one step further in */
.side nav a.sub.nav-sec { padding-left: 34px; }
.ws-menu { position: fixed; z-index: 200; display: block; min-width: 160px; }
.ws-menu > button { width: 100%; min-height: 40px; text-align: left; }

/* Task 878 Profile widget */
.dw-profile { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.dw-profile.is-small { justify-content: center; }
.dw-profile-name { flex: 1; min-width: 0; }
.dw-profile-acts { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; }
.dw-profile-acts > .btn { width: auto; }
.dw-ws-exit { display: none; }
html.ws-full .dw-ws-exit { display: inline-flex; }

/* Task 878 one drag look (row-drag.js live mode): a green dashed spot holds the place, a lifted copy follows the pointer. */
.rd-slot { outline: 2px dashed var(--pal-green); outline-offset: -2px; background: color-mix(in srgb, var(--pal-green) 6%, transparent); }
.rd-slot > * { visibility: hidden; }
.rd-ghost { box-shadow: 0 18px 40px rgba(22, 58, 95, .25); opacity: .95; transition: none; }

/* Section picker = one Top Bar tile (Oct 22 2026 8:49 AM, Travis: "Menu thing not fixed"). Root cause: 1.4.234 moved the
   page icon into the switch but stripped its tile border and background, so phones showed a bare icon, a separate-looking
   ▾ and the grey dot row. Now it is the same 44px .tile as Menu and the Dashboard page icon (same is same), the ▾ is a
   small mark inside the tile's corner, and the whole tile is the tap target. */
.top h1 .pn-switch.pn-has-ico { position: relative; display: inline-flex; align-items: center; justify-content: center; width: var(--tile); height: var(--tile); min-width: var(--tile); min-height: var(--tile); max-width: var(--tile); margin: 0; padding: 0; gap: 0; box-sizing: border-box; border: 1px solid var(--line); border-radius: var(--tile-r); background: var(--tile-rest); color: var(--muted); }
.top h1 .pn-switch.pn-has-ico > .tb-page-ico, .top-title.back-phone h1 .pn-switch.pn-has-ico > .tb-page-ico { display: inline-flex; align-items: center; justify-content: center; width: auto; height: auto; min-width: 0; min-height: 0; margin: 0; padding: 0; border: 0; background: none; box-shadow: none; pointer-events: none; }
.top h1 .pn-switch.pn-has-ico > .tb-page-ico .ico { width: var(--tile-ico); height: var(--tile-ico); }
.top h1 .pn-switch.pn-has-ico > .pn-caret { display: block; position: absolute; right: 3px; bottom: 1px; font-size: 9px; line-height: 1; pointer-events: none; }
.top h1 .pn-switch.pn-has-ico:hover, .top h1 .pn-switch.pn-has-ico:active, .top h1 .pn-switch.pn-has-ico:focus-visible { background: var(--tile-on); border-color: var(--blue); color: #fff; }
.top h1 .pn-switch.pn-has-ico:hover .pn-caret, .top h1 .pn-switch.pn-has-ico:active .pn-caret { color: #fff; }
.pn-dots { display: none !important; }
/* Same size as the Menu tile (Oct 22 2026 9:11 AM, Travis: "You fixed icon so don't break again but not same size"): var(--tile), not 44px. */

/* Task 533 Vitals (includes/vitals.php): the Sprout page Status view and the Vitals Dashboard widget share this look. */
.vt-wrap { --vt-beat: var(--pal-gray); display: grid; gap: 8px; }
.vt-wrap.vt-ok { --vt-beat: var(--pal-green); }
.vt-wrap.vt-warn { --vt-beat: var(--pal-orange); }
.vt-wrap.vt-down { --vt-beat: var(--pal-red); }
.vt-ecg { width: 100%; height: 48px; display: block; }
.vt-ecg path { fill: none; stroke: var(--vt-beat); stroke-width: 2.5; stroke-linejoin: round; stroke-dasharray: 520; stroke-dashoffset: 0; }
@media (prefers-reduced-motion: no-preference) { .vt-ecg path { stroke-dashoffset: 520; animation: vt-beat 1.6s linear infinite; } }
@keyframes vt-beat { to { stroke-dashoffset: -520; } }
/* Oct 22 2026 (plans/sprout-status.md): every vital is its own number card, label / big number / sub-label. */
.vt-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(130px, 100%), 1fr)); gap: 8px; }
.vt-card { display: grid; gap: 2px; min-width: 0; padding: var(--t-pad, 10px 12px); border: 1px solid var(--line); border-radius: var(--pill-radius, 10px); background: var(--card); color: inherit; text-decoration: none; }
.vt-card em { font-style: normal; font-size: .7rem; font-weight: 650; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.vt-card b { font-size: 1.35rem; font-weight: 750; font-variant-numeric: tabular-nums; line-height: 1.2; overflow-wrap: anywhere; }
.vt-card small { font-size: .75rem; color: var(--muted); }
a.vt-card small { color: var(--pal-blue); }
.vt-card.bad b { color: var(--pal-red); }
.vt-card.warn b { color: var(--pal-orange); }
html.tt-calm .vt-ecg path { animation-play-state: paused; }
@media (max-width: 480px) { .vt-cards { grid-template-columns: 1fr 1fr; } }

/* Safety List (Travis Oct 22 2026 12:07 PM): plain list in the shared pull-up Sheet, fades out after Show For. */
.sc-list { margin: 4px 0 8px; padding-left: 20px; display: grid; gap: 6px; }
#sc-list { transition: opacity .4s ease; }
#sc-list.sc-fade { opacity: 0; }

/* Route Sheet (Oct 22 2026, Travis 12:49 PM: "the Done screen's Products view is THE style for every Route slide-up"):
   .route-sheet makes a Route Menu sheet (Products, Equipment, Quick Calc, Safety List) the same white card as .sheet-step,
   under the job header (top = --route-top, set by field.php), flush to the bottom so no blue shows under it. */
dialog.field-ask.job-sub.route-sheet[open] { position: fixed; inset: var(--route-top, 96px) 0 0 0; width: auto; max-width: 560px; height: auto; max-height: none; margin: 0 auto; padding: 16px 16px calc(16px + env(safe-area-inset-bottom)); background: var(--paper); color: var(--ink); border: 0; border-radius: 22px 22px 0 0; box-shadow: none; overflow: auto; }
@media (max-width: 584px) { dialog.field-ask.job-sub.route-sheet[open] { margin: 0 12px; } }
dialog.field-ask.job-sub.route-sheet::backdrop { background: transparent; }
/* Oct 22 2026, Travis 1:58 PM: keep the edges peeking behind a Route slide-up, but the card behind (the active tab) is muted, not the tab color. */
.field-sheet:has(dialog.route-sheet[open]) .job-tabs button.on,
.field-sheet:has(dialog.route-sheet[open]) .job-tabs button { background: rgba(255,255,255,.07); color: rgba(255,255,255,.55); }
.field-sheet:has(dialog.route-sheet[open]) .field-sheet-body { background: color-mix(in srgb, var(--paper) 70%, var(--muted)); }
/* Oct 22 2026, Travis: Route's Add item (picker and How to bill it) opens inside the Route slide-up, same card as Products. */
dialog.ai-sheet.ai-route[open] { position: fixed; inset: var(--route-top, 96px) 0 0 0; width: auto; max-width: 560px; height: auto; max-height: none; margin: 0 auto; background: var(--paper); border-radius: 22px 22px 0 0; box-shadow: none; padding-bottom: env(safe-area-inset-bottom); }
@media (max-width: 584px) { dialog.ai-sheet.ai-route[open] { margin: 0 12px; width: auto; max-width: none; height: auto; max-height: none; border-radius: 22px 22px 0 0; } }
dialog.ai-sheet.ai-route::backdrop { background: transparent; }
/* Oct 22 2026, Travis: Call sheet rows (Call / Text / Email with icons). */
.reach-list .set-row { text-decoration: none; color: var(--ink); gap: 12px; }
.reach-list .reach-ico { flex: none; width: 36px; height: 36px; border-radius: 10px; display: inline-grid; place-items: center; background: var(--grass); color: var(--ink); }
.reach-list .reach-ico svg { width: 18px; height: 18px; }

/* Oct 22 2026, Travis: Route header spacing: status bar to the top row and the top row to the name are tightened to about
   the pill-to-name gap; Start / Drive / Time on Site rows a little tighter so the stats, Equipment and one panel row fit. */
.field-sheet-bar { min-height: 0; padding-top: calc(env(safe-area-inset-top, 0px) + 4px); padding-bottom: 8px; }
.field-body .field-sheet-bar { padding-top: 4px; }
.field-sheet-bar .who { margin-top: 2px; }
.job-tabs { padding-bottom: 6px; }
.field-sheet .job-rows:first-child div, .field-sheet section.job-rows:not(.site-rows):not(.eq-row-card) > div { padding-top: 9px; padding-bottom: 9px; }
/* Oct 22 2026, Travis: the Equipment row (above the Irrigation Controller) */
.eq-row-card .eq-pick { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 0; padding: var(--t-pad, 12px 14px); }
.eq-row-card .eq-pick > span { flex: none; }
.eq-row-card .eq-pick select { margin-left: auto; max-width: 62%; width: auto; border: 0; background: transparent; font-weight: 700; text-align: right; }
/* Oct 22 2026, Travis: Show Jobs on All Services Done */
.eod-jobs { background: var(--grass); color: #fff; border: 0; border-radius: var(--pill-radius, 999px); padding: 8px 14px; font-weight: 700; }
#site-ask .rachio-panel, #site-ask .rc-hero { margin-bottom: 8px; }

/* The one fold card (includes/fold.php, Oct 22 2026): title row folds the body; the arrow turns when open. */
details.fold > summary.fold-head { list-style: none; display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }
details.fold > summary.fold-head::-webkit-details-marker { display: none; }
details.fold > summary.fold-head h2 { margin: 0; font-size: 1.05rem; }
details.fold .fold-arrow { width: 18px; height: 18px; flex: none; color: var(--muted); transition: transform .15s ease; }
details.fold[open] .fold-arrow { transform: rotate(90deg); }
details.fold .fold-n { font-variant-numeric: tabular-nums; font-size: .8rem; font-weight: 600; padding: 1px 8px; border-radius: 999px; background: var(--line); }
details.fold[open] > .fold-body { margin-top: 14px; }
@media (prefers-reduced-motion: reduce) { details.fold .fold-arrow { transition: none; } }
/* The note fold (includes/fold.php note_fold_html, Oct 22 2026): Summary line on top, who said it + exact words folded. */
.note-fold { margin: 0 0 10px; }
.note-fold .note-sum { margin: 0; }
.note-fold details.note-more > summary { cursor: pointer; color: var(--muted); font-size: .85rem; margin-top: 2px; }
.note-fold details.note-more > p { margin: 6px 0 0; padding-left: 10px; border-left: 2px solid var(--line); }

/* Top bar tabs ($topTabs, includes/header.php; Sprout Oct 22 2026): plain text tabs, the open one underlined in green. */
.tb-tabs { display: flex; gap: 2px; align-items: stretch; min-width: 0; margin: 0 auto 0 8px; }
.tb-tabs a { display: flex; align-items: center; padding: 0 12px; min-height: 40px; font-weight: 650; color: var(--muted); text-decoration: none; border-bottom: 3px solid transparent; white-space: nowrap; }
.tb-tabs a.on { color: inherit; border-bottom-color: var(--pal-green); }
.tb-tabs a:focus-visible { outline: 2px solid var(--pal-blue); outline-offset: -2px; }
@media (max-width: 600px) { .tb-tabs { margin-left: 4px; } .tb-tabs a { padding: 0 8px; font-size: .9rem; } }
/* [Shared] Same is same: one Pill, one Button family, one X close (Tracker 880). Travis, Oct 22 2026: "Did we ever fix css so pills
   and everything same? Should have been for everything buttons x etc" / "Let's get it done". Icon buttons were already one
   (.tile + data-tip, 1.4.171). Sizes live in these tokens only; a Style (LMN, SA) or a company's Corners pick changes them
   in one place. Colors keep their meaning (Sandbox red/orange, status colors): only size, padding, corners and type are shared.
   Rules check "Same is same rule" (tools/rules/diff_check.py) flags a new pill/button/X size outside this block. docs/components.md. */
:root {
  --pill-h: 22px; /* pill padding and type: var(--pill-pad, 0 9px) and var(--pill-fs, .75rem), so a Style's own fallbacks stay its own */
  --btn-h: 36px; --btn-pad: 0 16px; --btn-h-sm: 30px; --btn-pad-sm: 0 12px; --btn-fs-sm: .78rem;
  --x-size: 32px;
}
/* Pill: .badge (and .pill) is the one status/priority/count pill. These older pill classes keep their colors and take its size. */
.badge, .pill, .pause-pill, .predict-pill, .sc-pill, .sum-tag, .tc-flag, .sc-demo b, .tag-chip, .itpl-chip {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px; vertical-align: middle;
  min-height: var(--pill-h); padding: var(--pill-pad, 0 9px); font-size: var(--pill-fs, .75rem); line-height: 1.15; font-weight: 650;
  border-radius: var(--pill-radius, 999px); white-space: nowrap; box-sizing: border-box;
}
.badge.name { white-space: normal; }
/* Pills in a list row sit in their own fixed column, the same width on every row, so rows line up (Tracker At a Glance, Tracker 880). */
.pill-col { flex: none; /* rules-ok: the shared pill column */ width: var(--pill-col, 5.4rem); display: flex; justify-content: flex-start; }
.pill-col > .badge { width: 100%; } /* rules-ok: shared pill column fills its cell */
.pill-col:empty { visibility: hidden; } /* rules-ok: shared pill column */
/* X close: one shared close button (toasts, pop-ups, chips, pictures, sheets). Name in aria-label, no tooltip (not an action). */
:is(button, a, span).x-close {
  display: inline-flex; align-items: center; justify-content: center; flex: none; box-sizing: border-box;
  width: var(--x-size); min-width: var(--x-size); height: var(--x-size); min-height: var(--x-size); padding: 0; margin: 0;
  border: 0; border-radius: 50%; background: transparent; color: inherit; box-shadow: none;
  font: inherit; font-size: 1.25rem; font-weight: 500; line-height: 1; text-decoration: none; cursor: pointer;
}
:is(button, a, span).x-close.x-sm { --x-size: 18px; font-size: 1rem; margin-left: 4px; }
@media (hover: hover) { :is(button, a, span).x-close:hover { background: rgba(0, 0, 0, .07); color: inherit; border-color: transparent; } }
.mt-pic .x-close { background: #fff; box-shadow: inset 0 0 0 1px var(--line); }
/* Tracker At a Glance rows (Tracker 880, Travis Oct 22 2026 phone: "Can we line up columns consistent, looks so bad"): number, title,
   status, priority, owner are fixed columns on every row, so an extra High pill never shoves Queued over. */
.tr-glance .lin-row { display: grid; grid-template-columns: 2.9rem minmax(0, 1fr) 5.4rem 4.1rem 3.4rem; gap: 6px; }
.tr-glance .lin-row.has-n { grid-template-columns: 22px 2.9rem minmax(0, 1fr) 5.4rem 4.1rem 3.4rem; }
.tr-glance .lin-row .pill-col { width: auto; } /* rules-ok: grid sets the column */
.tr-glance .lin-row .lin-who { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: right; }
.tr-glance .tk-num { white-space: nowrap; }
@media (max-width: 420px) {
  .tr-glance .lin-row { grid-template-columns: 2.5rem minmax(0, 1fr) 4.6rem 3.4rem 2.9rem; gap: 5px; padding: 4px 4px; }
  .tr-glance .lin-row.has-n { grid-template-columns: 20px 2.5rem minmax(0, 1fr) 4.6rem 3.4rem 2.9rem; }
  .tr-glance .lin-row { --pill-pad: 0 4px; }
}
/* Box Sprout (includes/box_user.php, Oct 22 2026, Travis: "no way to do that internally to tell the difference, hes got
   different ring than you or something"): purple person ring and a purple Box pill, shared .pm-av and .badge. */
.pm-av.av-box { border-color: var(--pal-purple); border-width: 2px; color: var(--pal-purple); --ttm-size: 100%; }
.pm-av.av-box .ttm { width: 100%; height: 100%; }
.badge.box-tag { background: var(--pal-purple); color: #fff; }
/* [Shared] Oct 22 2026, rules check bugs 732 and 734 (Travis: "NO WRAPPING ANYWHERE, ever"; no sideways page): on a narrow tablet (801-960px)
   Area Types and Profit by Month were wider than the screen. Columns share the card and a word ends in "…" only when it truly doesn't fit
   (full text on hover and tap via core.js). Phones keep the phone-sheet cards; from 961px the columns size to their words. */
@media (min-width: 801px) and (max-width: 960px) {
  #areas table.phone-sheet, table.pf-months { table-layout: fixed; width: 100%; }
  #areas table.phone-sheet :is(th, td), table.pf-months :is(th, td) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: none; }
  #areas table.phone-sheet :is(input, select, .unit-field) { width: 100%; min-width: 0; box-sizing: border-box; }
}
/* [Customers and Properties] Oct 22 2026 (Travis: services?id=13 was 46px wider than an 820 tablet): on a tablet the Assigned card is
   narrow, so the Customer name stops sooner (14vw, then "…", full text on hover and tap) and Property, the main column, keeps its room. */
@media (min-width: 801px) and (max-width: 1100px) {
  body:not(.ps):not(.site) main .card table.assigned-table:has(td.t-main) td:first-child:not(.t-main),
  body:not(.ps):not(.site) main .card table.assigned-table:has(td.t-main) td:first-child:not(.t-main) > a:first-child:not(.btn):not(.svc-name):not(.one-line) { max-width: 14vw; }
}
/* Tracker Overview (Travis Oct 22 2026 7:30 PM): four fold cards of the newest work, Service Status table style. */
.tr-ov { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 460px), 1fr)); gap: 12px; align-items: start; }
.tr-ov > .card { margin: 0; min-width: 0; }
.tr-ov-table { width: 100%; table-layout: fixed; }
.tr-ov-table th:nth-child(2), .tr-ov-table td.sx-state { width: 5.5rem; min-width: 0; }
.tr-ov-table th:nth-child(3), .tr-ov-table td.sx-num { width: 7.5rem; }
.tr-ov-table td.sx-name { min-width: 0; max-width: none; }
.tr-ov-table td.sx-name a { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tr-ov-when { display: none; font-style: normal; }
@media (max-width: 1180px) { .tr-ov-when { display: inline; } table.sx-table.tr-ov-table td.sx-name span { display: block; } }
/* [Shared] Quick Calc on shared styles (Travis Oct 22 2026 7:56 PM): examples are shared pills in one row that wraps, the
   Spray Tank / Backpack / Materials picks are shared buttons, the X is the shared X close, and the Sprout Mini fits or scrolls
   with its scrollbar space kept. */
.qc .qa-exs, .qc-quick .qa-exs, .qc-help .qa-exs { display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 6px; }
.qc button.qa-ex.pill, .qc-quick button.qa-ex.pill, .qc-help button.qa-ex.pill { min-height: var(--pill-h); padding: var(--pill-pad, 0 9px); font-size: var(--pill-fs, .75rem); line-height: 1.15; border-radius: var(--pill-radius, 999px); white-space: nowrap; }
.qc .qc-picks .btn { height: var(--btn-h); min-height: var(--btn-h); padding: var(--btn-pad-sm); }
dialog.sprout-mini.qc-pop .pn-head .x-close.sheet-x { width: var(--x-size); min-width: var(--x-size); height: var(--x-size); min-height: var(--x-size); margin: 0 0 0 auto; font-size: 1.25rem; }
dialog[open].sprout-mini { overflow-y: auto; scrollbar-gutter: stable; max-height: calc(var(--vvh, 100dvh) - env(safe-area-inset-top, 0px) - 12px - var(--kb, 0px)); }
/* [Shared] Left menu numbers (Travis Oct 22 2026 7:58 PM): the shared pill, right-aligned on its menu item (assets/js/nav-counts.js). */
.side nav a.nav-sec .nav-sec-l { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side nav a.nav-sec .nav-n { margin-left: auto; flex: none; }
.side nav a.nav-sec .nav-n[hidden] { display: none; }
/* [Shared] Sprout Vitals widget (Oct 22 2026): the 7 shared gauges in one row that shrinks to fit; 2 rows tall wraps them bigger. */
.dw-gauges { flex-wrap: nowrap; justify-content: space-around; gap: 6px; }
.dw-gauges figure { flex: 1 1 0; min-width: 0; }
.dw-gauges .sx-gauge { width: 100%; max-width: 72px; height: auto; margin: 0 auto; }
.dw-gauges figcaption { overflow: hidden; text-overflow: ellipsis; }
.dw[data-h="2"] .dw-gauges { flex-wrap: wrap; row-gap: 10px; }
.dw[data-h="2"] .dw-gauges figure { flex: 0 0 calc(25% - 6px); }
/* Profile Part 2/3 (Oct 22 2026; Travis 9:39 PM "just follow what we did earlier with cards and new rules do it"; 9:41 PM
   phone/Route = the same cards stacked). Green header card, compact card grid, whole card is the link. */
.pf-hero { background: linear-gradient(120deg, color-mix(in srgb, var(--grass) 30%, var(--ink)), color-mix(in srgb, var(--grass) 45%, var(--ink))); color: #fff; border: 0; padding: 18px; }
.pf-hero .muted { color: rgba(255,255,255,.85); }
.pf-hpills { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.pf-hpills .pill { background: rgba(255,255,255,.18); color: #fff; text-decoration: none; }
nav.tabs.pf-sections { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; margin: 0 0 12px; }
nav.tabs.pf-sections a.on { background: color-mix(in srgb, var(--grass) 45%, var(--ink)); border-color: transparent; color: #fff; }
.pf-grid { display: grid; gap: 12px; margin-bottom: 12px; }
.pf-g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.pf-g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.pf-span2 { grid-column: span 2; }
.pf-grid > .card { margin: 0; min-width: 0; }
a.pf-card { display: block; color: inherit; text-decoration: none; border: 1px solid var(--line); transition: border-color .15s; }
.pf-card h3 { margin: 0 0 10px; font-size: .75rem; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.pf-big { font-size: 1.5rem; font-weight: 750; }
.pf-big.pf-ok { color: var(--grass); } .pf-big.pf-warn { color: var(--orange); }
.pf-sub { margin: 4px 0 0; font-size: .82rem; }
.pf-ring .sx-gauges, .pf-ring figure { margin: 0 auto; text-align: center; color: var(--muted); font-size: .8rem; }
.pf-ring .sx-gauge { margin: 0 auto 4px; }
table.pf-list { width: 100%; border-collapse: collapse; }
body:not(.ps):not(.site) main .card table.pf-list tr > td.pf-r { width: 1%; max-width: none; white-space: nowrap; padding-left: 10px; }
table.pf-list td { padding: var(--t-pad, 7px 0); border-bottom: 1px solid var(--paper); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
table.pf-list tr:last-child td { border-bottom: 0; }
table.pf-list a { color: inherit; text-decoration: none; }
.pf-r { text-align: right; white-space: nowrap; width: 1%; padding-left: 10px; }
.pf-qlist { margin: 0; }
.pf-qrow { display: flex; width: 100%; justify-content: space-between; background: none; border: 0; border-bottom: 1px solid var(--paper); padding: 7px 0; font: inherit; color: inherit; cursor: pointer; box-shadow: none; margin: 0; border-radius: 0; }
.pf-qrow:last-child { border-bottom: 0; }
.pf-qrow.on b { color: var(--grass); }
/* Shared gauge hover (Travis Oct 21 2026 10:49 PM "just have a card border with it maybe (can change color too)"):
   a card holding .sx-gauge, or a linked card, gets the accent border on hover. Same is same. */
.card:has(.sx-gauge):hover, a.pf-card:hover, .pf-grid > .card:hover { border-color: var(--accent, var(--grass)); }
@media (max-width: 1100px) { .pf-g4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 800px) { .pf-g4, .pf-g2 { grid-template-columns: minmax(0, 1fr); } .pf-span2 { grid-column: auto; } .pf-hero { padding: 14px; } }
/* 2026-10-22 Travis: "follow what we did earlier with cards" (fix: global inline-block made titles 0-wide) */
body:not(.ps):not(.site) main .card table.pf-list tr > td.t-main { width: 100%; max-width: 0; display: table-cell; }
body:not(.ps):not(.site) main .card table.pf-list:not(.board) tr > td.t-main > a:first-child:not(.btn) { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Money menu (task 916, Oct 22 2026): on PC every money section is its own left-menu item, so the old section row and "Invoices ▾" switcher are gone. Phones keep the switcher. */
@media (min-width: 801px) { nav.tabs.money-tabs { display: none !important; } }
@media (min-width: 801px) { nav.tabs.ticket-tabs { display: none !important; } } /* Tracker 927: on a computer the Tickets views are left-menu items */
/* Shared list bar: the count on the right never shrinks or cuts off ("92 ope…" on Tracker, Oct 22 2026). */
.list-bar .list-count, .lb .list-count, .lb-tail { flex: none; min-width: max-content; overflow: visible; text-overflow: clip; white-space: nowrap; }

/* Shared At A Glance card grid (Oct 22 2026): 1 column on phone, a clean 2x2 on PC, 4 across only on very wide screens; cards in a row are equal height */
.glance-grid { display: grid; grid-template-columns: 1fr; gap: 12px; align-items: stretch; }
@media (min-width: 801px) { .glance-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1800px) { .glance-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.tc-copy { cursor: pointer; } .tc-copy:hover { text-decoration: underline dotted; } /* Task Card header: click Task #N to copy it */
/* Task Card chips (Oct 22 2026): a tap opens a list under the chip; the chip keeps its label and width */
.tk-chips { position: relative; }
.tk-pick-native { position: absolute; overflow: hidden; } .tk-pick-native > input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; }
.tk-menu { position: absolute; z-index: 30; min-width: 200px; max-height: 280px; overflow-y: auto; padding: 4px; background: #fff; border: 1px solid var(--line); border-radius: var(--in-radius, 8px); box-shadow: 0 8px 24px rgba(15, 23, 42, .16); display: flex; flex-direction: column; }
.tk-menu-i { display: block; width: 100%; min-height: 36px; padding: 6px 10px; border: 0; border-radius: 6px; background: none; color: var(--ink); font: inherit; text-align: left; cursor: pointer; }
.tk-menu-i:hover, .tk-menu-i:focus-visible { background: var(--paper); outline: none; } .tk-menu-i.on { font-weight: 650; color: var(--blue); }
/* Profile Part 2 (Oct 22 2026): My Time card head row + Clock History sub-heading. */
.pf-head { justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
.pf-head h2 { margin: 0; }
.pf-links { display: flex; gap: 6px; flex-wrap: wrap; }
.pf-sub-h { font-size: .95rem; margin: 16px 0 8px; }
#pf-time .pf-gauges { margin-top: 10px; }

/* Profile Part 3: wrapper only marks the page as no-tooltip; it adds no box so card spacing stays the same */
.pf-page{display:contents}
/* [Customers] Customers + Properties Pipeline (1.4.341, plans/customers-properties-pipeline.md): stage timeline, next step, opt-outs,
   stage pills as .badge (Margin: red below 15%, green above 30%), losing-money card, Stage History. One scroll, nothing reloads. */
.cpl-card { margin-bottom: 12px; }
.cpl-line { display: flex; gap: 0; margin: 2px 0 10px; overflow: hidden; }
.cpl-dot { position: relative; flex: 1 1 0; min-width: 0; text-align: center; padding-top: 18px; }
.cpl-dot::before { content: ""; position: absolute; top: 6px; left: 0; right: 0; height: 2px; background: var(--line); }
.cpl-dot:first-child::before { left: 50%; }
.cpl-dot:last-child::before { right: 50%; }
.cpl-dot i { position: absolute; top: 0; left: 50%; width: 14px; height: 14px; margin-left: -7px; border-radius: 50%; background: var(--paper, #fff); border: 2px solid var(--line); box-sizing: border-box; }
.cpl-dot b { display: block; font-size: .78rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cpl-dot span { display: block; font-size: .68rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cpl-dot.done i { background: var(--grass); border-color: var(--grass); }
.cpl-dot.done::before { background: var(--grass); }
.cpl-dot.cur i { background: var(--blue, #1E90FF); border-color: var(--blue, #1E90FF); }
.cpl-dot.next i { border-color: var(--blue, #1E90FF); }
.cpl-dot.later b, .cpl-dot.skip b { color: var(--muted); font-weight: 400; }
.cpl-dot.skip i { border-style: dashed; }
.cpl-dot.lost i { background: var(--red); border-color: var(--red); }
.cpl-dot.lost b { color: var(--red); }
.cpl-next { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin: 0 0 8px; }
.cpl-auto { font-size: .85rem; }
.cpl-opt { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 0; }
.cpl-lose { border-left: 4px solid var(--red); }
.cpl-lose .row { margin-top: 8px; }
.cpl-hist summary { cursor: pointer; font-weight: 700; }
.cpl-hist table { width: 100%; margin-top: 8px; }
.cpl-stage-row { flex-wrap: wrap; }
.mg .gauge.good .val { stroke: var(--grass); }
.mg .stat.good b { color: var(--grass); }
.cpl-sheet label { display: block; margin: 10px 0 4px; }
.cpl-sheet select, .cpl-sheet textarea { width: 100%; box-sizing: border-box; }
@media (max-width: 600px) { .cpl-dot b { font-size: .66rem; } .cpl-dot span { display: none; } }
@media (max-width: 1360px) { .list-results .cpl-col, .list-results th.lc-a.num, .list-results td.lc-a.num:has(> .badge, > .muted) { display: none; } } /* Properties list: the money column steps out before Pond/Surface would push it sideways */

/* Tracker 938 Menu widget (includes/widgets.php widget_menu, assets/js/widgets.js dwMenuFill): the left menu inside a card.
   One scroll (the card body), groups fold, wide cards flow into columns, nothing wider than the card on a phone. */
.dw-menu { height: 100%; min-width: 0; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; }
.dw-menu-set { display: none; margin-left: 6px; padding: 2px 8px; font-size: .78rem; font-weight: 400; }
body.dash-editing .dw-menu-set { display: inline-flex; }
.dw-menu-ed { display: grid; gap: 8px; min-width: 0; font-weight: 400; }
.dw-menu-ed label { display: grid; gap: 4px; font-size: .85rem; min-width: 0; }
.dw-menu-ed .dw-me-allw { display: flex; align-items: center; gap: 6px; }
.dw-menu-ed input[type=text], .dw-menu-ed select { width: 100%; min-width: 0; max-width: 100%; }
.dw-mi-list { display: grid; gap: 4px; margin-bottom: 6px; }
.dw-mi { display: flex; align-items: center; gap: 6px; padding: 4px 8px; border: 1px solid var(--line); border-radius: 8px; background: var(--card); cursor: grab; min-width: 0; }
.dw-mi-t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dw-me-acts { display: flex; gap: 8px; justify-content: flex-end; }
.dw-menu-nav { display: block; columns: 1; column-gap: 14px; }
.dw-menu[data-cols="2"] .dw-menu-nav { columns: 2; }
.dw-menu[data-cols="3"] .dw-menu-nav { columns: 3; }
.dw-menu-nav > a, .dw-menu-nav .nav-fold { break-inside: avoid; }
.dw-menu-nav a { display: flex; align-items: center; gap: 8px; min-width: 0; padding: 6px 8px; border-radius: 8px; color: inherit; text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 400; }
.dw-menu-nav a:hover { background: color-mix(in srgb, var(--pal-green) 10%, transparent); }
.dw-menu-nav a.active { background: color-mix(in srgb, var(--pal-green) 16%, transparent); font-weight: 600; }
.dw-menu-nav a svg { flex: none; width: 16px; height: 16px; }
.dw-menu-nav .nav-fold > summary { cursor: pointer; padding: 6px 8px; color: var(--muted); font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; list-style: revert; }
.dw-menu-nav .sub.nav-sec { padding-left: 32px; font-size: .9rem; }
.dw-menu-nav .nav-count, .dw-menu-nav .nav-n { margin-left: auto; }
@media (max-width: 700px) { .dw-menu[data-cols] .dw-menu-nav { columns: 1; } .dw .dw-menu { max-height: 60vh; } }
/* Tracker 926 (Oct 23 2026): Profile inside Route for crew. Same Profile, Route frame: no office side menu, phone layout,
   one scroll, sections wrap (no sideways scroll), card titles normal weight. */
body.pf-in-route .side, body.pf-in-route #nav-shade, body.pf-in-route .office-menu-ico { display: none !important; }
body.pf-in-route .shell { display: block; }
body.pf-in-route main { margin-left: 0; max-width: 720px; margin-inline: auto; }
body.pf-in-route .pf-g4, body.pf-in-route .pf-g2 { grid-template-columns: minmax(0, 1fr); }
body.pf-in-route .pf-span2 { grid-column: auto; }
.pf-card h3, .pf-page .card > h3 { font-weight: 400; }
@media (max-width: 600px) {
  nav.tabs.pf-sections { flex-wrap: wrap; overflow: visible; }
  .pf-page { overflow-x: clip; }
}
/* [Estimates] Oct 23 2026: Needs Attention Customer and History What are each table's main column, so a name or "Changes
   requested" is never cut while other columns have room (same as td.t-main; works before and after the t-main markup). */
@media (min-width: 801px) {
  body:not(.ps):not(.site) main .card table.eg-t tr > td[data-label="Customer"],
  body:not(.ps):not(.site) main .card table.phone-sheet tr > td[data-label="What"]:nth-child(2) { max-width: none; width: 100%; }
  body:not(.ps):not(.site) main .card table.eg-t:not(.board) tr > td[data-label="Customer"] > a:first-child:not(.btn):not(.svc-name):not(.one-line) { max-width: none; }
}

/* Customer + Property header (Travis, Oct 23 2026 "make it pop"): the green header card like Profile's .pf-hero,
   labeled icon action buttons (tooltips), contact pills, then tags + stage line + Next step on a light strip. */
.ch-hero { background: linear-gradient(120deg, color-mix(in srgb, var(--grass) 30%, var(--ink)), color-mix(in srgb, var(--grass) 45%, var(--ink))); color: #fff; border: 0; padding: 18px 18px 0; overflow: hidden; }
.ch-hero .muted { color: rgba(255,255,255,.85); }
.ch-top { display: flex; align-items: center; gap: 14px; min-width: 0; }
.ch-mark { flex: none; width: calc(var(--btn-h) * 1.3); height: calc(var(--btn-h) * 1.3); border-radius: var(--card-radius, 12px); display: grid; place-items: center; background: rgba(255,255,255,.16); border: 2px solid rgba(255,255,255,.45); font-size: 1.2rem; font-weight: 650; letter-spacing: .02em; }
.ch-who { min-width: 0; flex: 1 1 auto; }
.ch-hero h2.ch-name { margin: 0; color: #fff; font-size: 1.35rem; line-height: 1.2; overflow-wrap: anywhere; }
.ch-sub { margin-top: 2px; color: rgba(255,255,255,.88); }
.ch-pills { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.ch-pills .pill { background: rgba(255,255,255,.16); color: #fff; font-weight: 400; text-decoration: none; max-width: 100%; overflow-wrap: anywhere; display: inline-flex; align-items: center; gap: 5px; }
.ch-pills a.pill:hover { background: rgba(255,255,255,.28); }
.ch-acts { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 8px; margin: 14px 0 16px; }
.ch-hero .btn.ch-act { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; height: auto; min-height: calc(var(--btn-h) * 1.6); padding: var(--btn-pad-sm); background: rgba(255,255,255,.12); color: #fff; border: 1px solid rgba(255,255,255,.28); border-radius: 12px; font-size: .8rem; font-weight: 400; white-space: normal; text-align: center; line-height: 1.15; }
.ch-hero .btn.ch-act:hover { background: rgba(255,255,255,.24); }
.ch-hero .btn.ch-act.ch-up { background: var(--grass); color: var(--ink); border-color: var(--grass); }
.ch-foot { background: var(--paper, #fff); color: var(--ink); margin: 0 -18px; padding: 12px 18px 4px; }
.ch-foot:empty { display: none; }
.ch-foot .ch-stage { margin-top: 8px; }
@media (max-width: 800px) {
  .ch-hero { padding: 14px 14px 0; }
  .ch-foot { margin: 0 -14px; padding: 10px 14px 2px; }
  .ch-acts { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
  .ch-mark { font-size: 1rem; }
  .ch-hero h2.ch-name { font-size: 1.2rem; }
}
@media (max-width: 800px) { /* header stage line: two rows on the phone so every stage name reads in full */
  .ch-stage .cpl-line { flex-wrap: wrap; row-gap: 10px; overflow: visible; }
  .ch-stage .cpl-dot { flex: 0 0 20%; }
  .ch-stage .cpl-dot b, .ch-stage .cpl-dot span { overflow: visible; text-overflow: clip; font-size: .7rem; }
}
/* Oct 23 2026 (Travis, Sign-ups Registry at 390 "Formatting"): the Status page's phone grid above (table.sx-table tr = name/chip/bars areas)
   also hit every sx-table that is a phone-sheet (Registry, Automations, Account, Price Import, Product Lookup...), jumbling labels and values
   into two columns. Phone-sheet tables keep the standard one-label-per-line cards. */
@media (max-width: 700px) {
  table.sx-table.phone-sheet tr { display: block; grid-template-areas: none; padding: 10px 12px; border: 1px solid var(--line); border-bottom: 1px solid var(--line); border-radius: 12px; margin: 0 0 8px; background: #fff; }
  table.sx-table.phone-sheet tr:first-child { display: none; }
  table.sx-table.phone-sheet td, table.sx-table.phone-sheet td:first-child, table.sx-table.phone-sheet td:last-child { display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 8px; align-items: center; padding: 4px 0; background: transparent; }
  table.sx-table.phone-sheet td[data-label=""], table.sx-table.phone-sheet td:not([data-label]) { grid-template-columns: minmax(0, 1fr); }
  /* Registry: business name is the card title (normal weight), badges sit together, values wrap instead of "…". */
  table.reg-cards.phone-sheet td.reg-name { font-weight: 400; font-size: 1rem; white-space: normal; overflow: visible; }
  table.reg-cards.phone-sheet td, table.reg-cards.phone-sheet td[data-label]:not([data-label=""]):not(:has(*)) { display: grid; white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
  table.reg-cards.phone-sheet td[data-label]:not([data-label=""]):not(:has(*))::before { width: auto; margin: 0; }
  table.reg-cards .reg-badges { display: flex; flex-wrap: wrap; gap: 6px; }
}
@media (min-width: 701px) { table td.u-name { white-space: nowrap; } } /* Oct 23 2026: Users list name + team stay one line (rules check, 820) */
.ch-pills .pill { white-space: normal; } /* address pill wraps on phones (Tracker 955); size stays the shared Pill */
.ch-hero .ch-foot, .ch-hero .ch-foot .muted { color: var(--muted); }
.ch-hero .ch-foot b, .ch-hero .ch-foot strong { color: var(--ink); }
/* [Top Bar and Menus] Back First (Travis, Oct 23 2026): on any page with a Back button the left side reads Back, page icon, live heart, then Menu and the rest. Route keeps its own order until its redo (.field-app). */
body:not(:has(.field-app)) .top .top-title .back-link { order: -3; }
body:not(:has(.field-app)) .top .top-title .tb-page-ico { order: -2; }
body:not(:has(.field-app)) .top .top-title .tt-heart { order: -1; }
body:not(:has(.field-app)) .top .top-title.has-back .tt-heart { order: 0; }
/* Top Bar order (Oct 23 2026): when the page icon lives inside the name pill (section switcher, page-nav.js), the heart follows the pill so it stays page icon > heart */
body:not(:has(.field-app)) .top .top-title:has(h1 .pn-has-ico > .tb-page-ico) .tt-heart { order: 1; }
body:not(:has(.field-app)) .top:has(> .top-title.has-back) > *, body:not(:has(.field-app)) .top:has(> .top-title.has-back) > .office-menu-ico { order: 2; }
body:not(:has(.field-app)) .top:has(> .top-title.has-back) > .top-title { order: 0; }
body:not(:has(.field-app)) .top:has(> .top-title.has-back) > .office-menu-ico { order: 1; }
@media (max-width: 800px) {
  body:not(:has(.field-app)) .top:has(> .top-title.back-phone) > * { order: 2; }
  body:not(:has(.field-app)) .top:has(> .top-title.back-phone) > .top-title { order: 0; }
  body:not(:has(.field-app)) .top:has(> .top-title.back-phone) > .office-menu-ico { order: 1; }
}
/* [Profile Hub] status line (Clock In, today's stops, Time Off left) and the Light/Dark row (plans/profile-hub.md, Oct 23 2026) */
.hub-status { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 6px 8px; }
.hub-status .badge { text-decoration: none; }
.hub-status .hub-act { background: var(--grass); color: var(--paper); }
.pm-style { margin: 0; }
.pm-style .top-more-item { width: 100%; background: none; border: 0; font: inherit; color: inherit; text-align: left; }
