/*
 * Jumpstart Moving CRM, staff UI.
 *
 * TOKENS FIRST. Every colour, font and brand measure is a custom property declared in
 * tokens.css (loaded before this file). This file holds layout and component rules
 * only, and every colour it paints is `var(--...)`: a literal colour here is a bug,
 * because it is the one place a theme change would miss.
 *
 * RESPONSIVE IS A STANDING REQUIREMENT (up/docs/responsive-design-standard.md):
 * phone, tablet, laptop and desktop, no exceptions. The layout is authored
 * MOBILE-FIRST, so the base rules ARE the phone layout and each breakpoint adds
 * room rather than taking it away. There is no max-width media query in this file.
 *
 * THE BREAKPOINTS, AND WHY THESE NUMBERS
 *   base    phone: top bar with a menu button, the sidebar is a drawer (a dialog).
 *   560px   large phone: card grids gain a second column.
 *   820px   TABLET. Deliberately NOT 768px, which that standard's section 2 names
 *           as a stale device-width assumption. The sidebar becomes an icon rail
 *           and the board shows two full stage columns.
 *  1000px   the full labelled sidebar returns (the approved mockup's rail range
 *           ends at 999px).
 *  1100px   laptop: detail views go two-up, record tables become tables.
 *  1200px   Home's two columns (Needs you beside Recent activity) and a four-slot
 *           status strip.
 *  1500px   desktop: wider stage columns and a cap on the content measure.
 *
 * TOUCH TARGETS. Every control is at least 44px tall. The primary way to move a card
 * on this board is a TAP, and a tap target smaller than a fingertip is how a
 * tap-primary path quietly becomes a drag-only one.
 */

:root {
  --tap: 44px;
  --gap: 12px;

  /* Legacy names the existing views were written against, now pointing at the brand
     tokens so those views restyle through tokens with no internal redesign. */
  --ink: var(--jm-ink);
  --ink-soft: var(--jm-gray);
  --line: var(--jm-hairline);
  --bg: var(--jm-surface);
  --panel: var(--jm-ground);
  --accent: var(--jm-accent-text);
  --accent-soft: var(--jm-accent-soft);
  --warn: var(--jm-warning);
  --danger: var(--jm-danger);
  --danger-soft: var(--jm-danger-soft);
  --radius: var(--jm-radius);
}

*, *::before, *::after { box-sizing: border-box; }

/*
 * THE `hidden` ATTRIBUTE MUST WIN, and this rule is why it does.
 *
 * `hidden` is only a UA default of `display: none`, so ANY author rule setting a
 * display beats it. `.topbar { display: flex }` did exactly that once: the sign-in
 * screen shipped with the topbar and a Sign out button painted over it. The
 * javascript and the markup were both correct; the stylesheet quietly overruled
 * both, and it took a screenshot to see it.
 *
 * `!important` is deliberate: `hidden` means "not relevant", and no layout rule
 * should ever be able to reveal an element the application has declared irrelevant.
 */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--jm-font-body);
  font-size: var(--jm-text-base);
  line-height: 1.4;
  color: var(--jm-ink-soft);
  background: var(--jm-ground);
}

h1, h2, h3, h4 { font-family: var(--jm-font-heading); color: var(--jm-ink); font-weight: 600; margin: 0; }
h1 { font-size: var(--jm-text-xl); line-height: 32px; }
h2 { font-size: var(--jm-text-lg); line-height: 28px; margin: 0 0 8px; }
h3 { font-size: var(--jm-text-base); margin: 0 0 6px; }
p { margin: 0; }

a { color: var(--jm-accent-text); }

svg.i {
  width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor;
  stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round;
}

:focus-visible { outline: 2px solid var(--jm-focus-ring); outline-offset: 2px; }

.skip-link {
  position: absolute; left: 8px; top: -64px; z-index: 60;
  background: var(--jm-ground); padding: 8px 12px;
  border: 1px solid var(--jm-border-control); border-radius: var(--jm-radius);
  font: 600 var(--jm-text-sm)/20px var(--jm-font-ui);
}
.skip-link:focus { top: 8px; }

.muted { color: var(--ink-soft); font-size: var(--jm-text-sm); margin: 4px 0 12px; }

/* ================================================================ app shell
 *
 * Phone (base): the sidebar is an off-canvas drawer opened by the menu button and
 * treated as a modal dialog while open; the top bar carries the menu button, the
 * product name and the current page.
 */

.app { min-height: 100vh; background: var(--jm-ground); }

.sidebar {
  position: fixed; z-index: 30; left: 0; top: 0; bottom: 0;
  width: min(320px, 88vw);
  display: flex; flex-direction: column;
  background: var(--jm-side-ground);
  border-right: 1px solid var(--jm-side-hairline);
  transform: translateX(-100%); visibility: hidden;
  overflow-y: auto;
}
body.nav-open .sidebar { transform: none; visibility: visible; }
.scrim { display: none; }
body.nav-open .scrim { display: block; position: fixed; inset: 0; z-index: 20; background: var(--jm-scrim); }

.side-brand {
  height: var(--header-h-phone); flex: none;
  display: flex; align-items: center; gap: 8px;
  padding: 0 8px 0 20px;
  border-bottom: 1px solid var(--jm-side-hairline);
}
.brand-link { display: inline-flex; align-items: center; min-height: var(--tap); border-radius: var(--jm-radius); text-decoration: none; }
.wordmark { font: 700 20px/24px var(--jm-font-heading); color: var(--jm-side-text); text-transform: uppercase; letter-spacing: 0.02em; }
.wordmark-icon {
  display: none; width: 32px; height: 32px; border-radius: var(--jm-radius);
  background: var(--jm-accent); color: var(--jm-accent-contrast);
  align-items: center; justify-content: center; font: 700 16px/1 var(--jm-font-heading);
}
.nav-close {
  display: inline-grid; place-items: center; margin-left: auto;
  width: var(--tap); height: var(--tap); min-height: var(--tap); padding: 0;
  border: 0; background: transparent; color: var(--jm-side-text);
  border-radius: var(--jm-radius); cursor: pointer;
}
.drawer-title { display: block; font: 600 var(--jm-text-lg)/28px var(--jm-font-heading); color: var(--jm-side-text); padding: 8px 12px 0; margin: 0; }

.side-nav { flex: 1; padding: 8px 12px 16px; }
.side-nav ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.nav-group + .nav-group { margin-top: 16px; }
.nav-label { display: block; font: 600 var(--jm-text-xs)/16px var(--jm-font-ui); color: var(--jm-side-text-muted); padding: 4px 12px 8px; }

.nav-item {
  position: relative; display: flex; align-items: center; gap: 12px; width: 100%;
  min-height: var(--tap); padding: 8px 12px;
  border: 0; border-left: 2px solid transparent; border-radius: var(--jm-radius);
  background: transparent; text-decoration: none; text-align: left; cursor: pointer;
  font: 500 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-side-text);
}
.nav-item svg.i { color: var(--jm-side-text-muted); }
.nav-item:hover { background: var(--jm-side-hairline); }
.nav-item[aria-current="page"] {
  background: var(--jm-side-selected-bg); color: var(--jm-accent);
  font-weight: 600; border-left-color: var(--jm-accent);
}
.nav-item[aria-current="page"] svg.i { color: var(--jm-accent); }
.lbl-short { display: none; }

.nav-foot { border-top: 1px solid var(--jm-side-hairline); padding: 12px; flex: none; display: grid; gap: 4px; }
.account { display: flex; align-items: center; gap: 12px; min-height: 48px; padding: 4px 12px; color: var(--jm-side-text); }
.avatar {
  width: 32px; height: 32px; border-radius: 50%; flex: none;
  display: inline-grid; place-items: center;
  background: var(--jm-side-hairline); border: 1px solid var(--jm-side-hairline); color: var(--jm-side-text-muted);
}
.avatar svg.i { width: 16px; height: 16px; }
.account-name { font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); color: var(--jm-side-text); display: block; }

.app-main { min-width: 0; display: flex; flex-direction: column; min-height: 100vh; }

.topbar {
  position: sticky; top: 0; z-index: 5;
  height: var(--header-h-phone);
  display: flex; align-items: center; gap: 8px;
  padding: 0 var(--gutter-phone) 0 4px;
  padding-left: max(4px, env(safe-area-inset-left));
  background: var(--jm-ground); border-bottom: 1px solid var(--jm-hairline);
}
.menu-btn {
  display: inline-grid; place-items: center;
  width: var(--tap); height: var(--tap); min-height: var(--tap); padding: 0;
  border: 0; background: transparent; color: var(--jm-ink);
  border-radius: var(--jm-radius); cursor: pointer;
}
.menu-btn svg.i { width: 24px; height: 24px; }
.topbar-word { display: block; font: 700 16px/20px var(--jm-font-heading); color: var(--jm-ink); text-transform: uppercase; letter-spacing: 0.02em; white-space: nowrap; }
.crumbs {
  margin-left: auto; min-width: 0;
  display: flex; align-items: center; gap: 8px;
  font: 500 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-gray);
}
.crumbs a { color: var(--jm-gray); text-decoration: none; display: inline-flex; align-items: center; min-height: var(--tap); border-radius: var(--jm-radius); }
.crumbs a:hover { color: var(--jm-accent-text); }
.crumbs [aria-current="page"] { color: var(--jm-ink); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.crumbs svg.i { width: 16px; height: 16px; color: var(--jm-border-control); }
.crumbs .crumb-parent, .crumbs .crumb-sep { display: none; }
.topbar-right { display: none; margin-left: auto; align-items: center; gap: 12px; }

.content {
  flex: 1;
  padding: 24px var(--gutter-phone) 64px;
  padding-left: max(var(--gutter-phone), env(safe-area-inset-left));
  padding-right: max(var(--gutter-phone), env(safe-area-inset-right));
}

/* ================================================================ shared controls */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: var(--jm-control-height); padding: 12px 24px;
  font: 600 var(--jm-text-sm)/20px var(--jm-font-ui);
  border-radius: var(--jm-radius); border: 1px solid transparent;
  text-decoration: none; cursor: pointer; white-space: nowrap;
}
.btn svg.i { width: 16px; height: 16px; }
.btn-primary { background: var(--jm-accent); color: var(--jm-accent-contrast); }
.btn-primary:hover { background: var(--jm-accent-hover); }
.btn-outline { background: var(--jm-ground); color: var(--jm-accent-text); border-color: var(--jm-accent-text); }
.btn-outline:hover { background: var(--jm-accent-soft); }
.btn-text { background: transparent; color: var(--jm-accent-text); padding: 12px 8px; }

.chip {
  display: inline-flex; align-items: center; height: 24px; padding: 0 12px;
  border-radius: var(--jm-radius); white-space: nowrap;
  font: 600 var(--jm-text-xs)/16px var(--jm-font-ui);
  color: var(--jm-gray); background: var(--jm-surface);
}
.chip-accent { color: var(--jm-accent-text); background: var(--jm-accent-soft); }
.chip-warning { color: var(--jm-warning); background: var(--jm-warning-soft); }
.chip-neutral { color: var(--jm-gray); background: var(--jm-ground); box-shadow: inset 0 0 0 1px var(--jm-hairline); }

.field { display: flex; flex-direction: column; gap: 4px; font-size: var(--jm-text-sm); }
.field > span { color: var(--ink-soft); }

input, select, button {
  font: inherit;
  min-height: var(--tap);
  border-radius: var(--radius);
  border: 1px solid var(--jm-border-control);
  padding: 0 10px;
  background: var(--panel);
  color: inherit;
  max-width: 100%;
}
button { cursor: pointer; }
button.primary {
  background: var(--jm-accent); color: var(--jm-accent-contrast); border-color: var(--jm-accent);
  font-family: var(--jm-font-ui); font-weight: 600;
}
button.primary:hover { background: var(--jm-accent-hover); }
button.ghost { background: var(--panel); color: var(--jm-accent-text); border-color: var(--jm-accent-text); font-family: var(--jm-font-ui); font-weight: 600; }
button.ghost:hover { background: var(--jm-accent-soft); }

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: var(--gap);
}

.error { color: var(--danger); background: var(--danger-soft); padding: 10px 12px; border-radius: var(--radius); }
.error.banner { position: sticky; bottom: 0; margin-top: var(--gap); }
.error.home-error { position: static; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 var(--gap); }
.loading { color: var(--ink-soft); }
.empty { color: var(--ink-soft); }

/* ================================================================ sign in */

.view-signin { padding: 16px var(--gutter-phone); }
.signin-card { max-width: 26rem; margin: 32px auto; }
.signin-card label { display: block; margin-top: 12px; font-size: var(--jm-text-sm); color: var(--ink-soft); }
.signin-card input { width: 100%; margin-top: 4px; }
.signin-card button { width: 100%; margin-top: 16px; }

/* ================================================================ views */

.view-head {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--gap); margin-bottom: 8px;
}
.view-actions { display: flex; flex-wrap: wrap; gap: var(--gap); margin-left: auto; }
.crumb { margin: 0 0 12px; }

/* ================================================================ Home (TODO 00094) */

.page-head { display: flex; flex-direction: column; align-items: stretch; gap: 16px; }
.page-head h1 { font-size: var(--jm-text-2xl); line-height: 32px; }
.page-sub { color: var(--jm-gray); margin-top: 8px; max-width: 720px; }

/* TODO 00124: the Home search box and its results. */
.home-head-actions { display: flex; flex-direction: column; align-items: stretch; gap: 12px; }
.home-search-field input { width: 100%; }
.home-search-results { margin-top: 16px; }
#home-search-error { margin: 16px 0 0; }
.search-group + .search-group { margin-top: 16px; }
.search-group-h { font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); color: var(--jm-gray); margin: 0 0 8px; }
.search-list { list-style: none; margin: 0; padding: 0; }
.search-hit {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: var(--tap); padding: 12px 16px; border-bottom: 1px solid var(--jm-row-rule);
  color: inherit; text-decoration: none;
}
.search-hit:hover, .search-hit:focus-visible { background: var(--jm-accent-soft); }
.search-hit-main { min-width: 0; }
.search-hit .need-meta { overflow-wrap: anywhere; }
.search-hit .tag { flex: none; }
.search-more { color: var(--jm-gray); font-size: var(--jm-text-sm); margin: 8px 0 0; }
@media (min-width: 820px) {
  .home-head-actions { flex-direction: row; align-items: flex-end; }
  .home-search-field { width: 320px; }
}

/* TODO 00159: the board search box. Full width on a phone row, fixed beside the
 * source filter from 820px up. cites: home-search-bar */
.board-search-field { flex: 1 1 220px; min-width: 0; }
.board-search-field input { width: 100%; }
@media (min-width: 820px) {
  .board-search-field { flex: 0 0 280px; }
}

.strip { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 24px; }
.tile { display: grid; grid-template-rows: subgrid; grid-row: span 3; row-gap: 0; border-top: 1px solid var(--jm-hairline); padding-top: 16px; min-width: 0; }
.tile-label { font: 500 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink-soft); }
.tile-value { font: 600 var(--jm-text-lg)/28px var(--jm-font-heading); color: var(--jm-ink); margin-top: 8px; min-height: 28px; }
.tile-ctx { font-size: var(--jm-text-xs); line-height: 16px; color: var(--jm-gray); margin-top: 4px; }

.home-cols { display: grid; grid-template-columns: minmax(0, 1fr); gap: 40px; margin-top: 40px; }
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.section-head h2 { font-size: var(--jm-text-lg); line-height: 28px; margin: 0; }
.section-meta { font-size: var(--jm-text-xs); line-height: 16px; color: var(--jm-gray); }

.need-list { background: var(--jm-surface); border-radius: var(--jm-radius-panel); border-top: 1px solid var(--jm-row-rule); }
.need-row {
  display: grid; grid-template-columns: 20px minmax(0, 1fr); align-items: start;
  gap: 16px; min-height: 64px; padding: 12px 16px;
  border-bottom: 1px solid var(--jm-row-rule);
}
.need-icon { display: inline-grid; place-items: center; color: var(--jm-gray); margin-top: 2px; }
.need-title { font: 600 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink); display: block; }
.need-meta { font: 400 var(--jm-text-sm)/19.6px var(--jm-font-body); color: var(--jm-gray); display: block; margin-top: 4px; }
.need-end { grid-column: 2; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: flex-start; }
.need-empty { padding: 20px 16px; color: var(--jm-gray); border-bottom: 1px solid var(--jm-row-rule); }

.feed { list-style: none; margin: 0; padding: 0; }
.feed li {
  display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; gap: 12px;
  padding: 12px 0; border-top: 1px solid var(--jm-hairline); align-items: center;
}
.feed li:first-child { border-top: 0; padding-top: 4px; }
/* The empty line spans the whole row, not the 32px avatar column (TODO 00101). */
.feed li.feed-empty { display: block; }
.feed .avatar { background: var(--jm-ink); border-color: var(--jm-ink); color: var(--jm-ground); }
.feed-text { color: var(--jm-ink-soft); min-width: 0; }
.feed-text b { font-weight: 600; color: var(--jm-ink); font-family: var(--jm-font-ui); }
.feed-text a { color: inherit; text-decoration: none; }
.feed-text a:hover b { color: var(--jm-accent-text); }
.feed-time { font-size: var(--jm-text-xs); line-height: 16px; color: var(--jm-gray); white-space: nowrap; }
.feed-empty { color: var(--jm-gray); }

/* ================================================================ board */

/*
 * Phone: the board is ONE column at a time, stacked, because a horizontal strip of
 * eight columns on a 360px screen is a scroll nobody finds.
 */
.board { display: flex; flex-direction: column; gap: var(--gap); }

.stage {
  background: var(--jm-surface);
  border-top: 1px solid var(--jm-row-rule);
  display: flex; flex-direction: column;
  min-width: 0;
}

.stage-head {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  font: 600 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink);
  min-height: var(--tap);
}
.stage-count {
  margin-left: auto; font-weight: 600; font-size: var(--jm-text-xs);
  color: var(--jm-gray); background: var(--jm-ground);
  border-radius: var(--jm-radius); padding: 2px 8px;
  box-shadow: inset 0 0 0 1px var(--jm-hairline);
}
.stage[data-won="true"] .stage-head { color: var(--jm-success); }
.stage[data-terminal="true"][data-won="false"] .stage-head { color: var(--warn); }

.stage-cards {
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px; min-height: 48px;
}
/* The drop affordance. Drag is an ENHANCEMENT: this only ever appears under a
   pointer drag, and nothing about moving a card depends on it. */
.stage-cards[data-dropping="true"] { background: var(--accent-soft); outline: 2px dashed var(--jm-accent); }

.lead-card {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px;
  background: var(--panel);
  display: flex; flex-direction: column; gap: 6px;
}
.lead-card .who { font: 600 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink); word-break: break-word; }
.lead-card .where { font-size: var(--jm-text-sm); color: var(--ink-soft); word-break: break-word; }
.lead-card .meta { font-size: var(--jm-text-xs); color: var(--ink-soft); }
.lead-card .row { display: flex; flex-wrap: wrap; gap: 6px; }
.lead-card button, .lead-card a.btn {
  min-height: var(--tap); display: inline-flex; align-items: center;
  padding: 0 12px; font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); text-decoration: none;
  border: 1px solid var(--jm-accent-text); border-radius: var(--radius);
  background: var(--panel); color: var(--jm-accent-text);
}
.lead-card button.move { background: var(--jm-accent); border-color: var(--jm-accent); color: var(--jm-accent-contrast); }
/* A closed (terminal) lead reads as settled without fading its text: the card drops to
   the column's own surface with a dashed control border. No opacity, so every text
   pair keeps its full token contrast (s159 A15: 0.85 opacity took gray to about 4.1). */
.lead-card[data-terminal="true"] { background: var(--jm-surface); border: 1px dashed var(--jm-border-control); }

.tag {
  display: inline-block; font-size: var(--jm-text-xs); padding: 2px 8px;
  border-radius: var(--jm-radius); background: var(--jm-surface); color: var(--ink-soft);
  border: 1px solid var(--line);
}
/* Plain flag styling for the inventory review card (TODO 00080). */
.tag.warn { background: var(--jm-warning-soft); color: var(--warn); border-color: var(--warn); }

/* ================================================================ sheet */

.sheet-backdrop { position: fixed; inset: 0; background: var(--jm-scrim); z-index: 40; }

/*
 * Phone: a bottom sheet, reachable by thumb. Tablet and up: a centred dialog.
 * Either way it is the same markup and the same taps.
 */
.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  background: var(--panel);
  border-top-left-radius: 12px; border-top-right-radius: 12px;
  padding: 16px;
  padding-bottom: max(16px, env(safe-area-inset-bottom));
  max-height: 85vh; overflow-y: auto;
  box-shadow: 0 -8px 30px var(--jm-sheet-shadow);
}
.move-options { display: flex; flex-direction: column; gap: 8px; margin: 12px 0; }
.move-options button {
  width: 100%; text-align: left; min-height: var(--tap);
  background: var(--accent-soft); border-color: var(--jm-accent-text); color: var(--jm-accent-text);
  font-weight: 600;
}
.sheet .field { margin-bottom: 12px; }
.sheet #move-cancel { width: 100%; }

/* Jobs: Listing | Calendar, crew filter, job preview (TODO 00191.c, rulings s262).
 * Mobile first: on a phone each calendar day shows a count; from 820px it shows up
 * to three jobs. The preview is the shared .sheet: bottom sheet, then centred. */
.jobs-tools { display: flex; flex-direction: column; align-items: stretch; gap: 12px; margin: 0 0 8px; }
.jobs-tools[hidden] { display: none; }
.jobs-seg { display: inline-flex; align-self: flex-start; border: 1px solid var(--jm-accent-text); border-radius: var(--jm-radius); overflow: hidden; }
.jobs-seg button { min-height: var(--tap); min-width: 5.5rem; padding: 0 16px; border: 0; border-radius: 0; background: var(--panel); color: var(--jm-accent-text); font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); cursor: pointer; }
.jobs-seg button + button { border-left: 1px solid var(--jm-accent-text); }
.jobs-seg button:hover { background: var(--jm-accent-soft); }
.jobs-seg button[aria-pressed="true"] { background: var(--jm-accent); color: var(--jm-accent-contrast); }
.jobs-seg button:focus-visible { outline: 3px solid var(--jm-ink); outline-offset: -3px; }
.jobs-crew { margin: 0; }
.jobs-crew select { width: 100%; min-height: var(--tap); }
#jobs-body .row-item[data-job], #jobs-day .row-item[data-job] { cursor: pointer; }
#jobs-body .row-item[data-job]:hover, #jobs-day .row-item[data-job]:hover { border-color: var(--jm-accent-text); }
.jp-open-preview { min-height: 24px; padding: 0; margin-left: 16px; border: 0; background: none; color: var(--jm-accent-text); font: inherit; text-decoration: underline; cursor: pointer; }
.jp-open-preview:focus-visible { outline: 3px solid var(--jm-ink); outline-offset: 2px; }

.cal-chip[data-status="scheduled"], .cal-legend .sw[data-status="scheduled"] { --st: var(--jm-accent); --st-soft: var(--jm-accent-soft); }
.cal-chip[data-status="in_progress"], .cal-legend .sw[data-status="in_progress"] { --st: var(--jm-warning); --st-soft: var(--jm-warning-soft); }
.cal-chip[data-status="completed"], .cal-legend .sw[data-status="completed"] { --st: var(--jm-success); --st-soft: var(--jm-success-soft); }
.cal { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; background: var(--panel); }
.cal-head, .cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.cal-head div { padding: 6px 0; text-align: center; font: 600 var(--jm-text-xs)/16px var(--jm-font-ui); color: var(--ink-soft); text-transform: uppercase; background: var(--jm-surface); border-bottom: 1px solid var(--line); }
.cal-cell { min-width: 0; padding: 2px; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); display: flex; flex-direction: column; gap: 3px; }
.cal-cell:nth-child(7n) { border-right: 0; }
.cal-out { min-height: 56px; background: var(--jm-surface); }
.cal-day { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; width: 100%; min-height: 52px; padding: 4px 0; border: 1px solid transparent; border-radius: var(--radius); background: none; color: var(--jm-ink); font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); cursor: pointer; }
.cal-day:hover { background: var(--jm-accent-soft); }
.cal-day[aria-pressed="true"] { border-color: var(--jm-accent-text); background: var(--jm-accent-soft); }
.cal-day:focus-visible { outline: 3px solid var(--jm-ink); outline-offset: -2px; }
.cal-count { display: inline-block; min-width: 22px; padding: 0 5px; border-radius: 999px; background: var(--jm-accent); color: var(--jm-accent-contrast); font-size: var(--jm-text-xs); line-height: 18px; text-align: center; }
.cal-chips, .cal-more, .cal-legend { display: none; }
.cal-chips { list-style: none; margin: 0; padding: 0; flex-direction: column; gap: 3px; }
.cal-chip { display: block; cursor: pointer; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; padding: 3px 6px; border-left: 4px solid var(--st); border-radius: 4px; background: var(--st-soft); color: var(--jm-ink); font-size: var(--jm-text-xs); line-height: 16px; text-decoration: none; }
.cal-chip:hover { text-decoration: underline; }
.cal-chip:focus-visible { outline: 3px solid var(--jm-ink); outline-offset: 1px; }
.cal-chip .t { font-weight: 600; }
.cal-more { align-self: flex-start; padding: 2px 6px; border: 0; background: none; color: var(--jm-accent-text); font: 600 var(--jm-text-xs)/16px var(--jm-font-ui); text-decoration: underline; cursor: pointer; }
.cal-legend { list-style: none; flex-wrap: wrap; gap: 4px 16px; margin: 10px 0 0; padding: 0; font-size: var(--jm-text-sm); color: var(--ink-soft); }
.cal-legend li { display: inline-flex; align-items: center; gap: 6px; }
.cal-legend .sw { width: 14px; height: 14px; border-radius: 3px; background: var(--st-soft); border-left: 4px solid var(--st); }
.cal-hint { font-size: var(--jm-text-sm); margin: 8px 0; }
#jobs-day { margin-top: 20px; }
#jobs-day .list-head { flex-wrap: wrap; gap: 8px 12px; }
#jobs-day h2 { margin: 0; font-size: var(--jm-text-lg); scroll-margin-top: 88px; }

.jp-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin: 0 0 12px; }
.jp-head h2 { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.jp-head button { flex: 0 0 auto; }
.job-preview-sheet .kv { margin: 0 0 16px; }
.jp-note { margin: 0; }
.jp-note + .jp-note { margin-top: 8px; }
.jp-note small { display: block; color: var(--ink-soft); }
.job-preview-sheet .jp-open { display: flex; justify-content: center; width: 100%; }

@media (min-width: 820px) {
  .jobs-tools { flex-direction: row; flex-wrap: wrap; align-items: flex-end; gap: 12px 16px; }
  .jobs-crew { min-width: 12rem; }
  .cal-head div { padding: 6px 8px; text-align: left; }
  .cal-cell { min-height: 8.5rem; padding: 4px; }
  .cal-out { min-height: 8.5rem; }
  .cal-day { flex-direction: row; justify-content: space-between; min-height: 28px; padding: 2px 6px; }
  .cal-count { display: none; }
  .cal-chips { display: flex; }
  .cal-more { display: inline-block; }
  .cal-legend { display: flex; }
  .sheet.job-preview-sheet { width: min(34rem, calc(100vw - 3rem)); }
}

/* ================================================================ records */

/*
 * A record table on a phone is a horizontal scroll or a lie. These are stacked
 * definition rows; each cell carries its own label, so the same markup serves both.
 */
.rows { display: flex; flex-direction: column; gap: 8px; }
.row-item {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--panel); padding: 10px;
}
.row-item dl { display: grid; grid-template-columns: minmax(6.5rem, auto) 1fr; gap: 4px 10px; margin: 0; }
.row-item dt { color: var(--ink-soft); font-size: var(--jm-text-sm); }
.row-item dd { margin: 0; word-break: break-word; color: var(--jm-ink); }

.kv { display: grid; grid-template-columns: minmax(7rem, auto) 1fr; gap: 6px 12px; margin: 0; }
.kv dt { color: var(--ink-soft); font-size: var(--jm-text-sm); }
.kv dd { margin: 0; word-break: break-word; color: var(--jm-ink); }
/* TODO 00128: the one long label ("Truck (customer's guess)") wraps inside the
 * column's own 7rem floor instead of widening the label column for every row,
 * which crushed the values in the three-column lead view at >= 1100px. */
.kv dt.kv-wrap { max-width: 7rem; }

/* C5a (TODO 00077.d): lead-detail inventory-photo thumbnails. */
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; }
.photo-thumb {
  width: 100%; aspect-ratio: 1 / 1; object-fit: cover;
  border-radius: var(--radius); border: 1px solid var(--line); background: var(--panel);
}

/* Inventory review (TODO 00080): mobile-first, single column. */
.inventory-line { display: flex; flex-direction: column; gap: 8px; }
.inventory-line-main { display: flex; flex-direction: column; gap: 8px; }
.inventory-line .inventory-thumb { width: 72px; height: 72px; flex: none; }
.inventory-line-body .row { margin-top: 6px; gap: 6px; }
.inventory-line-controls { display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; }
.inventory-qty-field { flex: 1 1 6rem; max-width: 8rem; }
.inventory-qty { width: 100%; }
.inventory-line .inventory-remove,
.inventory-line .inventory-add-to-list { min-height: var(--tap); }

.totals { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap); }
.total { border-top: 1px solid var(--jm-hairline); padding: 10px 0 0; min-width: 0; }
.total .n { font: 600 var(--jm-text-lg)/28px var(--jm-font-heading); color: var(--jm-ink); display: block; }
.total .l { font-size: var(--jm-text-xs); color: var(--ink-soft); }

.detail-cols { display: flex; flex-direction: column; gap: var(--gap); }

/* TODO 00190.c: notes in the lead record's Event history card (approved mockup
 * deliverables/dashboard-design/00189-customer-record, noteRow and eventHistoryCard).
 * One column at every width; existing tokens only; nothing here is wider than its card. */
.lr-note-form { display: flex; flex-direction: column; gap: 8px; margin: 0 0 12px; }
.lr-note-form textarea { font: inherit; width: 100%; box-sizing: border-box; min-height: calc(var(--tap) * 2); padding: 8px 10px; border: 1px solid var(--jm-border-control); border-radius: var(--radius); background: var(--panel); color: inherit; resize: vertical; }
.lr-note-form select { width: 100%; min-height: var(--tap); }
.lr-note-actions { margin: 0; flex-wrap: wrap; align-items: center; }
.lr-note-actions button { min-height: var(--tap); }
.lr-note-actions button:disabled { background: var(--jm-surface); color: var(--jm-text-disabled); border-color: var(--jm-border-control); cursor: not-allowed; }
.lr-note-error { margin: 0; }
.lr-note-error:empty { display: none; }
.lr-note-list { margin: 0 0 16px; }
.lr-note-row .lr-note-text { white-space: pre-wrap; overflow-wrap: anywhere; }

/* TODO 00189.c: the lead record's Current job, Jobs, Event history fold and History
 * (mockup deliverables/dashboard-design/00189-customer-record). One column on a
 * phone; nothing here is wider than its card. */
.lr-current.lr-accent { border: 2px solid var(--jm-accent); background: var(--jm-accent-soft); }
.lr-current-label { margin: 0 0 4px; font-family: var(--jm-font-ui); font-weight: 600; font-size: var(--jm-text-sm); text-transform: uppercase; letter-spacing: .04em; color: var(--jm-ink-soft); }
.lr-current.lr-accent .lr-current-label { color: var(--jm-accent-text); }
.lr-current h2 { font-size: var(--jm-text-xl); display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.lr-current h2 a, .lr-past h3 a { color: var(--jm-accent-text); display: inline-flex; align-items: center; min-height: var(--tap); }
.lr-current .kv { margin-bottom: 12px; }
.lr-items-head { margin-top: 4px; }
.lr-items { list-style: none; margin: 0 0 8px; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(12rem, 100%), 1fr)); gap: 6px 16px; }
.lr-items li { padding: 6px 0; border-bottom: 1px solid var(--jm-row-rule); word-break: break-word; }
.lr-open { display: inline-flex; align-items: center; min-height: var(--tap); }
.tag.lr-todo { background: var(--jm-accent); color: var(--jm-accent-contrast); border-color: var(--jm-accent); font-weight: 600; }
.lr-jobs { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.lr-job-row { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; min-height: var(--tap); padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); color: var(--jm-ink); text-decoration: none; }
.lr-job-row:hover { border-color: var(--jm-accent-text); }
.lr-job-date { font-weight: 600; color: var(--jm-accent-text); text-decoration: underline; }
.lr-job-count { margin-left: auto; color: var(--ink-soft); font-size: var(--jm-text-sm); }
.lr-job-row.lr-job-own { border-color: var(--jm-accent); background: var(--jm-accent-soft); }
.lr-cancelled, .lr-cancelled dd, .lr-cancelled .lr-job-date, .lr-cancelled .lr-job-count, .lr-cancelled a, .lr-current.lr-cancelled h2 a, .lr-past.lr-cancelled h3 a { color: var(--jm-gray); }
.lr-job-row.lr-cancelled { background: var(--jm-surface); }
.lr-moves-head { margin-top: 4px; }
.lr-fold { min-height: var(--tap); }
.lr-history .row-item + .row-item { margin-top: 8px; }

/* ================================================================ Performance (TODO 00095)
 * Built from the Home tile vocabulary: hairline-topped blocks on white, the figure in
 * the display face, context in gray. Mobile first: one column, the by-source table
 * reads as one labelled block per source until 820px gives it room to be a table. */

.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* Inside a Soon label the hidden suffix stays inline, so the accessible name reads
 * "Messages, not available yet" with no inserted space (TODO 00101). Still unseen. */
.is-soon .lbl .vh { position: static; display: inline; width: auto; height: auto; clip: auto; clip-path: inset(50%); font-size: 0; }

.tile-link { color: inherit; text-decoration: none; border-radius: var(--jm-radius); }
.tile-link:hover .tile-label { color: var(--jm-accent-text); }
.tile-value.tile-value-quiet { font: 400 var(--jm-text-sm)/20px var(--jm-font-body); color: var(--jm-gray); }
/* TODO 00187: the Leads to quote tile opens the board with New and Contacted marked. */
.stage.stage-to-quote { border-top: 3px solid var(--jm-accent-text); background: var(--jm-accent-soft); }

.perf-denied { margin-top: 24px; padding: 20px 16px; background: var(--jm-surface); color: var(--jm-ink-soft); border-top: 1px solid var(--jm-row-rule); }

.kpi-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; margin-top: 24px; }
.kpi-card { border-top: 1px solid var(--jm-hairline); padding-top: 16px; min-width: 0; }
.kpi-label { font: 500 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink-soft); margin: 0; }
.kpi-figure { font: 600 var(--jm-text-xl)/32px var(--jm-font-heading); color: var(--jm-ink); margin-top: 8px; }
.kpi-figure-quiet { font: 400 var(--jm-text-sm)/20px var(--jm-font-body); color: var(--jm-gray); }
.kpi-figure .chip { font-family: var(--jm-font-ui); }
.kpi-detail { font-size: var(--jm-text-sm); line-height: 20px; color: var(--jm-ink-soft); margin-top: 4px; }

.perf-sources { margin-top: 40px; }
.kpi-table { width: 100%; border-collapse: collapse; background: var(--jm-surface); border-top: 1px solid var(--jm-row-rule); }
.kpi-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.kpi-table tr { display: block; padding: 12px 16px; border-bottom: 1px solid var(--jm-row-rule); }
.kpi-table tfoot tr { background: var(--jm-ground); }
.kpi-table th[scope="row"] { display: block; text-align: left; font-weight: 400; margin-bottom: 4px; }
.kpi-table td { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; color: var(--jm-ink); }
.kpi-table td::before { content: attr(data-label); color: var(--jm-gray); font-size: var(--jm-text-sm); }
.kpi-source { display: block; font: 600 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink); }
.kpi-source-kind { display: block; font-size: var(--jm-text-xs); line-height: 16px; color: var(--jm-gray); text-transform: capitalize; }
.kpi-note { font-size: var(--jm-text-sm); line-height: 20px; color: var(--jm-gray); margin-top: 12px; }

/* Reviews (TODO 00096): the v1 quotes list vocabulary (list, list-head, qrow).
 * Phone: each row stacks name, facts, then the chip and the Review button. 820px:
 * name over a line of facts, the chip and button at the right. 1100px: one aligned
 * row per lead (fixed-width end column, so a chip never shifts the columns). */

.reviews-body { margin-top: 24px; }
.list { background: var(--jm-surface); border-radius: var(--jm-radius-panel); }
.list-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 16px; background: var(--jm-ground);
  border-top: 1px solid var(--jm-row-rule); border-bottom: 1px solid var(--jm-row-rule);
}
.list-head h2 { font-size: var(--jm-text-base); line-height: 20px; margin: 0; }
.qrow {
  display: grid; grid-template-columns: minmax(0, 1fr); row-gap: 4px;
  min-height: 64px; padding: 12px 16px; border-bottom: 1px solid var(--jm-row-rule);
}
.qrow-name { font: 600 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink); overflow-wrap: anywhere; }
.qrow-meta { font: 400 var(--jm-text-sm)/19.6px var(--jm-font-body); color: var(--jm-gray); }
.qrow-end { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 8px; }
.review-facts { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.qrow-end .btn { min-height: var(--tap); }
.reviews-showing { font-size: var(--jm-text-sm); line-height: 20px; color: var(--jm-gray); margin-top: 12px; }
/* Opened from Reviews, the lead view scrolls to its inventory card: land it below
   the sticky topbar, not under it. */
#inventory-card { scroll-margin-top: calc(var(--header-h-phone) + 16px); }

/* Quotes (TODO 00097): the same list vocabulary, one link per job. Phone: name and
 * total on one line, move date and version under them. 820px: one aligned row of
 * name, move date, total, version. The detail reuses card and kv; only the stored
 * line breakdown and the version list are new. */

.quotes-body { margin-top: 24px; }
.segmented {
  display: flex; gap: 4px; padding: 4px; margin-top: 24px;
  background: var(--jm-surface); border-radius: var(--jm-radius);
}
.segmented button {
  flex: 1 1 0; min-width: 0; min-height: var(--tap); padding: 0 8px;
  border: 0; border-radius: var(--jm-radius); background: transparent;
  font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); color: var(--jm-gray);
}
.segmented button[aria-pressed="true"] { background: var(--jm-ground); color: var(--jm-ink); box-shadow: inset 0 0 0 1px var(--jm-hairline); }
.seg-count { font-weight: 400; }
a.qrow { text-decoration: none; color: inherit; }
a.qrow:hover { background: var(--jm-ground); }
.qrow.quote-row { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name total" "meta version"; column-gap: 16px; align-items: center; }
.quote-row .qrow-name { grid-area: name; }
.quote-row .qrow-meta { grid-area: meta; }
.qrow-total { grid-area: total; font: 600 var(--jm-text-base)/20px var(--jm-font-heading); color: var(--jm-ink); text-align: right; white-space: nowrap; }
.qrow-version { grid-area: version; font: 500 var(--jm-text-sm)/20px var(--jm-font-ui); color: var(--jm-gray); text-align: right; }

.quote-lines, .quote-versions { border-top: 1px solid var(--jm-row-rule); }
.quote-line { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; padding: 12px 0; border-bottom: 1px solid var(--jm-row-rule); }
.quote-line-main { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.quote-line-label { font: 600 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink); }
.quote-line-note { font-size: var(--jm-text-sm); line-height: 20px; color: var(--jm-ink-soft); overflow-wrap: anywhere; }
.quote-line-amount { font: 600 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink); white-space: nowrap; }
.quote-sum .quote-line-label { font-weight: 400; }
.quote-total { border-bottom: 0; }
.quote-total .quote-line-label, .quote-total .quote-line-amount { font-weight: 700; font-size: var(--jm-text-lg); line-height: 24px; }
.quote-lines .empty { padding: 12px 0; border-bottom: 1px solid var(--jm-row-rule); margin: 0; }
.quote-version {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 12px;
  min-height: var(--tap); padding: 8px 0; border-bottom: 1px solid var(--jm-row-rule);
  text-decoration: none; color: inherit;
}
.quote-version:hover { background: var(--jm-ground); }
.quote-version[aria-current="page"] { box-shadow: inset 3px 0 0 var(--jm-accent); padding-left: 12px; }
.quote-version-end { display: flex; align-items: center; gap: 12px; }

/* Book job (TODO 00106): the lead header slot and its sheet, and the job's quote
 * card. Phone: the sheet's two buttons stack full width. 820px: side by side. */

.book-slot { display: contents; }
a.button-link {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); padding: 0 14px;
  border: 1px solid var(--jm-accent-text); border-radius: var(--radius);
  background: var(--panel); color: var(--jm-accent-text);
  font-family: var(--jm-font-ui); font-weight: 600; text-decoration: none;
}
a.button-link:hover { background: var(--jm-accent-soft); }
a.button-link:focus-visible { outline: 2px solid var(--jm-focus-ring); outline-offset: 2px; }
.book-facts { margin: 0 0 12px; }
.book-quote-total, .job-quote-total { font-weight: 600; }
.book-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.book-actions button { width: 100%; }
#book-sheet input { width: 100%; }
#book-sheet .error { margin-top: 12px; }
#book-sheet #book-date-error { margin: -4px 0 12px; }
#book-sheet button.primary:disabled { background: var(--jm-surface); color: var(--jm-text-disabled); border-color: var(--jm-border-control); cursor: not-allowed; }

@media (min-width: 820px) {
  .book-actions { flex-direction: row; }
  .book-actions button { width: auto; min-width: 8rem; }
}

/* Lead quote (TODO 00102): the quote card in the lead view. Reuses the stored
 * breakdown and version-row vocabulary above. Phone: the form fields stack, one
 * per row. 820px: the three number fields and the truck box sit two to a row.
 * Skeleton rows are plain and static, never animated. */

.quote-current { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; margin-bottom: 8px; }
.quote-accepted { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 0 0 12px; }
.quote-earlier { margin: 20px 0 8px; }
.quote-actions { margin: 16px 0 0; }
.quote-confirm { margin-top: 16px; padding: 12px; border: 1px solid var(--jm-border-control); border-radius: var(--jm-radius); background: var(--jm-ground); }
.quote-confirm p { font: 600 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink); }
.quote-confirm .quote-actions { margin-top: 12px; }
.quote-form { margin-top: 16px; }
.quote-fields { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.quote-fields input { width: 100%; }
.field-hint { font-size: var(--jm-text-sm); line-height: 18px; color: var(--ink-soft); }
.quote-legacy-drive { grid-column: 1 / -1; margin: 0; }
.quote-truck { display: flex; align-items: center; gap: 8px; min-height: var(--tap); font-size: var(--jm-text-sm); color: var(--jm-ink); cursor: pointer; }
.quote-truck input { width: 20px; height: 20px; min-height: 0; padding: 0; margin: 0; accent-color: var(--jm-accent-text); }
#quote-card .error { margin-top: 12px; }
#quote-card h2:focus { outline: none; }
#quote-card h2:focus-visible { outline: 2px solid var(--jm-focus-ring); outline-offset: 2px; }

.quote-skeleton { display: grid; gap: 12px; padding: 4px 0; }
.quote-skel-row { display: block; height: 20px; border-radius: var(--jm-radius); background: var(--jm-surface); border: 1px solid var(--jm-hairline); }
.quote-skel-row:last-child { width: 60%; }

@media (min-width: 820px) {
  .quote-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
}

/* Settings (TODO 00098): the v1 settings vocabulary, Items only (rulings s163).
 * Phone: each item row is its name over its option count, Edit at the right.
 * 820px: one aligned row of name, count and Edit. Group heads are shown in title
 * case by app.js, so no text-transform here. The sheets reuse .sheet. */

.settings-section { margin-top: 24px; }
.summary { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.summary h2 { font-size: var(--jm-text-xl); line-height: 32px; margin: 0; }
.room-head {
  padding: 12px 16px; background: var(--jm-ground);
  border-top: 1px solid var(--jm-row-rule); border-bottom: 1px solid var(--jm-row-rule);
  font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); color: var(--jm-ink-soft); letter-spacing: 0.02em;
}
.room-head:first-child { border-top: 0; }
.item-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name end" "meta end";
  align-items: center; column-gap: 16px; row-gap: 4px;
  min-height: 64px; padding: 12px 16px; border-bottom: 1px solid var(--jm-row-rule);
}
.item-row-name { grid-area: name; font: 600 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink); overflow-wrap: anywhere; }
.item-row-variants { grid-area: meta; font: 400 var(--jm-text-sm)/19.6px var(--jm-font-body); color: var(--jm-gray); }
.item-row-end { grid-area: end; display: flex; justify-content: flex-end; }
.item-row-end .btn { min-height: var(--tap); }
.item-row.is-retired .item-row-name { color: var(--jm-gray); font-weight: 400; }
/* An item with no option count is one grid row: no empty second row, no gap (TODO 00101). */
.item-row-variants:empty { display: none; }
.item-row:has(> .item-row-variants:empty) { grid-template-areas: "name end"; row-gap: 0; }
.foot-nav ul { list-style: none; margin: 0; padding: 0; }

.catalog-sheet h3 { margin: 20px 0 8px; }
.catalog-sheet .field input, .catalog-sheet .field select { width: 100%; }
.catalog-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.catalog-options { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }
.catalog-option { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.catalog-option input { flex: 1 1 10rem; min-width: 0; }
.catalog-option-label { flex: 1 1 10rem; min-width: 0; overflow-wrap: anywhere; }
.catalog-option.is-retired .catalog-option-label { color: var(--jm-gray); }
.catalog-option-new { margin-bottom: 12px; }
.catalog-retire { margin-top: 20px; padding-top: 12px; border-top: 1px solid var(--jm-row-rule); }
.catalog-confirm { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.catalog-confirm-text { font-weight: 600; color: var(--jm-ink); }
button.danger { background: var(--jm-danger); color: var(--jm-ground); border-color: var(--jm-danger); font-family: var(--jm-font-ui); font-weight: 600; }
.catalog-sheet .error { margin: 0 0 12px; }
.catalog-close { width: 100%; }

/* Settings subnav and Lead sources (TODO 00099, rulings s164 R7, R8).
 * Phone and tablet: the two subnav entries sit in one row above the section,
 * ruled off below. 1100px: the subnav becomes a left column beside the section.
 * A source row is its name over its type, with the Active chip and Edit (or the
 * Built in chip) at the right; 820px lines name, type and the end up in columns. */

.settings { display: grid; grid-template-columns: minmax(0, 1fr); gap: 24px; margin-top: 24px; }
.settings-body { min-width: 0; }
.settings-body .settings-section, .settings-body .perf-denied { margin-top: 0; }
.source-kv { margin-bottom: 16px; }
.subnav { border-bottom: 1px solid var(--jm-hairline); }
.subnav ul { list-style: none; margin: 0; padding: 0 0 12px; display: flex; flex-wrap: wrap; gap: 4px; }
.subnav .nav-item { width: auto; white-space: nowrap; color: var(--jm-ink-soft); }
.subnav .nav-item svg.i { color: var(--jm-ink-soft); }
.subnav .nav-item:hover { background: var(--jm-surface); }
.subnav .nav-item[aria-current="page"] {
  background: var(--jm-accent-soft); color: var(--jm-accent-text);
  font-weight: 600; border-left-color: var(--jm-accent-text);
}
.subnav .nav-item[aria-current="page"] svg.i { color: var(--jm-accent-text); }
.chip-success { color: var(--jm-success); background: var(--jm-success-soft); }
.source-row .item-row-end { align-items: center; gap: 8px; flex-wrap: wrap; }
.source-row.is-locked .item-row-end { min-height: var(--tap); }
/* A fixed-width control slot, so the Active chip sits at one x whether the row
 * ends in Edit or in the Built in chip (TODO 00101). */
.source-row .item-row-end > :last-child { flex: 0 0 4.5rem; justify-content: center; text-align: center; }

@media (min-width: 820px) {
  .item-row.source-row { grid-template-columns: minmax(0, 1fr) 8rem 12rem; }
  .source-row .item-row-variants { text-align: left; }
  .source-row .item-row-end { flex-wrap: nowrap; }
}

@media (min-width: 1100px) {
  .settings { grid-template-columns: 14rem minmax(0, 1fr); gap: 40px; margin-top: 32px; align-items: start; }
  .subnav { border-bottom: 0; position: sticky; top: calc(var(--header-h) + 32px); }
  .subnav ul { display: grid; padding: 0; }
  .subnav .nav-item { width: 100%; }
  /* The global Loading line sits in the body column, not under the subnav (TODO 00101). */
  main:has(> #view-settings:not([hidden])) > #loading { margin-left: calc(14rem + 40px); }
}

/* Settings > Pricing (TODO 00139.d, rulings s199 D7): the Items / Lead sources row
 * vocabulary, no new visual language. Phone: zip and town over county and tier over
 * the two rates, the Edited chip and Edit at the right. 820px: one aligned row of
 * place, area, rates and the end. The search box is the Home search field's shape. */

.pricing-search-field { margin-bottom: 16px; }
.pricing-search-field input { width: 100%; }
.item-row.pricing-row { grid-template-areas: "name end" "meta end" "rates end"; }
.pricing-area { grid-area: meta; font: 400 var(--jm-text-sm)/19.6px var(--jm-font-body); color: var(--jm-gray); }
.pricing-rates { grid-area: rates; display: flex; flex-wrap: wrap; gap: 2px 16px; font: 400 var(--jm-text-sm)/19.6px var(--jm-font-body); color: var(--jm-ink); }
.pricing-rate-k { color: var(--jm-gray); }
.pricing-half { color: var(--jm-gray); }
.pricing-row .item-row-end { align-items: center; gap: 8px; flex-wrap: wrap; }
.quote-area { margin: 0 0 12px; }
.quote-area-note { display: block; }

@media (min-width: 820px) {
  .pricing-search-field { width: 320px; }
  .item-row.pricing-row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 14rem 8.5rem;
    grid-template-areas: "name meta rates end";
  }
  .pricing-rates { flex-direction: column; gap: 0; }
  .pricing-row .item-row-end { flex-wrap: nowrap; }
}

/* Soon placeholders (TODO 00100, rulings s165 R2 to R4; client-dashboard-SOP section 4).
 * A Soon row is a span, not a link: no hover fill, a not-allowed cursor, greyed text
 * that still clears 4.5:1, and a one-word bordered badge. Never opacity. The Home
 * preview cards are dashed, plain and static: the skeleton rows never animate.
 * Mobile first; 820px is the icon rail (the badge drops its box there), 1000px the
 * full sidebar again (the shell's own breakpoint), 1100px three cards in a row. */

.is-soon { cursor: not-allowed; }
.nav-item.is-soon { cursor: not-allowed; color: var(--jm-side-disabled); font-weight: 500; }
.nav-item.is-soon:hover { background: transparent; }
.nav-item.is-soon svg.i { color: var(--jm-side-disabled); }
.soon {
  margin-left: auto; flex: none;
  font: 600 var(--jm-text-xs)/16px var(--jm-font-ui); color: var(--jm-side-disabled);
  background: var(--jm-side-ground); border: 1px solid var(--jm-side-hairline); border-radius: var(--jm-radius);
  padding: 0 8px;
}
.subnav .nav-item.is-soon { color: var(--jm-gray); }
.subnav .nav-item.is-soon:hover { background: transparent; }
.subnav .nav-item.is-soon svg.i { color: var(--jm-text-disabled); }
.subnav .soon, .preview .soon { color: var(--jm-gray); background: var(--jm-ground); border-color: var(--jm-hairline); }

.home-more { margin-top: 40px; }
.previews { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
.preview { border: 1px dashed var(--jm-border-control); border-radius: var(--jm-radius-panel); background: var(--jm-ground); padding: 20px; min-width: 0; }
.preview-head { display: flex; align-items: center; gap: 8px; }
.preview-head svg.i { color: var(--jm-text-disabled); }
.preview-title { font: 600 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-gray); margin: 0; }
.preview-copy { color: var(--jm-gray); margin: 8px 0 0; }
.preview-tag {
  display: inline-block; margin-top: 16px; padding: 4px 8px; border-radius: var(--jm-radius);
  font: 600 10px/16px var(--jm-font-ui); letter-spacing: 1px; text-transform: uppercase;
  color: var(--jm-gray); background: var(--jm-surface);
}
.sk-rows { margin-top: 16px; display: grid; gap: 12px; }
.sk-row { display: grid; grid-template-columns: minmax(0, 1fr) 48px; gap: 12px; align-items: center; }
.sk-row.num { grid-template-columns: 48px minmax(0, 1fr) 48px; }
.sk-row.day { grid-template-columns: 48px minmax(0, 1fr); }
.sk { height: 8px; border-radius: var(--jm-radius); background: var(--jm-surface); }
.sk.tall { height: 12px; }
.sk.gap { margin-top: 8px; }
.sk.w40 { width: 40%; }
.sk.w60 { width: 60%; }
.sk.w80 { width: 80%; }
.sk-pill { height: 16px; border-radius: var(--jm-radius); background: var(--jm-surface); }

@media (min-width: 820px) {
  .home-more { margin-top: 48px; }
  .sidebar .soon { margin: 0; padding: 0; border: 0; background: transparent; font-weight: 500; }
}

@media (min-width: 1000px) {
  .sidebar .soon {
    margin-left: auto; padding: 0 8px; font-weight: 600;
    background: var(--jm-side-ground); border: 1px solid var(--jm-side-hairline);
  }
}

@media (min-width: 1100px) {
  .previews { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .preview { padding: 24px; }
  .preview-copy { min-height: 44px; }
}

/* Job ticket (TODO 00103): the job's linked numbers card and its add sheet.
 * Phone: the add action and the sheet's two buttons are full width, stacked.
 * 820px: they sit at their own width, side by side. */

#job-refs-title:focus { outline: none; }
#job-refs-title:focus-visible { outline: 2px solid var(--jm-focus-ring); outline-offset: 2px; }
.job-ref-value { overflow-wrap: anywhere; }
.job-ref-actions { margin-top: 12px; }
.job-ref-actions button { width: 100%; min-height: var(--tap); }
.job-ticket-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.job-ticket-actions button { width: 100%; min-height: var(--tap); }
#job-ticket-sheet input { width: 100%; }
#job-ticket-sheet .error { margin-top: 12px; }
.job-ticket-readback {
  margin: 4px 0 16px; padding: 12px;
  border: 1px solid var(--jm-border-control); border-radius: var(--jm-radius);
  background: var(--jm-ground); color: var(--jm-ink);
  font: 600 var(--jm-text-xl)/1.3 var(--jm-font-ui);
  letter-spacing: 0.04em; overflow-wrap: anywhere;
}
#job-ticket-sheet button.primary:disabled { background: var(--jm-surface); color: var(--jm-text-disabled); border-color: var(--jm-border-control); cursor: not-allowed; }
#job-ticket-sheet button.ghost:disabled { color: var(--jm-text-disabled); border-color: var(--jm-border-control); cursor: not-allowed; }
/* TODO 00107: the change read-back names the old number above the new one. */
.job-ticket-old-line { margin: 4px 0 12px; color: var(--jm-ink-soft); overflow-wrap: anywhere; }
.job-ticket-old { font-weight: 600; color: var(--jm-ink); text-decoration: line-through; }
.job-ticket-new-label { margin: 0; color: var(--jm-ink-soft); }

@media (min-width: 820px) {
  .job-ref-actions button { width: auto; }
  .job-ticket-actions { flex-direction: row; }
  .job-ticket-actions button { width: auto; min-width: 8rem; }
}

/* ================================================================ 560px */

@media (min-width: 560px) {
  .totals { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; }
  .inventory-line-main { flex-direction: row; align-items: flex-start; }
}

/* ================================================================ 820px: TABLET
 *
 * Deliberately 820, not 768. The sidebar becomes a persistent icon rail beside the
 * content; the drawer, the scrim and the menu button go away.
 */

@media (min-width: 820px) {
  /* The sidebar column is painted on .app itself, so it runs the full height of a
     long page rather than stopping where the sticky sidebar box ends. */
  .app {
    --shell-side-w: var(--rail-w);
    display: grid; grid-template-columns: var(--shell-side-w) minmax(0, 1fr);
    background: linear-gradient(to right,
      var(--jm-side-ground) calc(var(--shell-side-w) - 1px),
      var(--jm-side-hairline) calc(var(--shell-side-w) - 1px) var(--shell-side-w),
      var(--jm-ground) var(--shell-side-w));
  }
  .sidebar {
    position: sticky; top: 0; height: 100vh; width: auto;
    transform: none; visibility: visible; z-index: auto;
  }
  body.nav-open .scrim { display: none; }
  .side-brand { height: var(--header-h); justify-content: center; padding: 0; }
  .wordmark { display: none; }
  .wordmark-icon { display: flex; }
  .nav-close, .drawer-title { display: none; }
  .side-nav { padding: 8px; }
  .nav-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .nav-group + .nav-group { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--jm-side-hairline); }
  .sidebar .nav-item {
    flex-direction: column; justify-content: center; gap: 4px;
    min-height: 64px; padding: 8px 4px; text-align: center;
    font-size: var(--jm-text-xs); line-height: 16px;
  }
  .sidebar .lbl { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .sidebar .lbl-short { display: block; }
  .nav-foot { padding: 8px; }
  .account { justify-content: center; padding: 4px; }
  .account-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

  .topbar { height: var(--header-h); padding: 0 var(--gutter-tablet); gap: 12px; }
  .menu-btn, .topbar-word { display: none; }
  .crumbs { margin-left: 0; }
  .crumbs .crumb-parent, .crumbs .crumb-sep { display: inline-flex; }
  .topbar-right { display: flex; }
  .content { padding: 32px var(--gutter-tablet) 64px; }

  .page-head { flex-direction: row; align-items: flex-end; justify-content: space-between; flex-wrap: wrap; }
  .strip { gap: 24px; margin-top: 32px; }
  .tile-value { font-size: var(--jm-text-xl); line-height: 32px; }
  .home-cols { margin-top: 48px; }
  .need-row { grid-template-columns: 20px minmax(0, 1fr) auto; align-items: center; padding: 12px 24px; }
  .need-icon { margin-top: 0; }
  .need-end { grid-column: auto; justify-content: flex-end; flex-wrap: nowrap; }
  .list-head { padding: 12px 24px; }
  .qrow {
    grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name end" "facts end";
    align-items: center; column-gap: 16px; padding: 12px 24px;
  }
  .qrow-name { grid-area: name; }
  .review-facts { grid-area: facts; flex-direction: row; flex-wrap: wrap; column-gap: 24px; }
  .qrow-end { grid-area: end; margin-top: 0; justify-content: flex-end; flex-wrap: nowrap; }
  #inventory-card { scroll-margin-top: calc(var(--header-h) + 16px); }
  .qrow.quote-row {
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) 7rem 4rem;
    grid-template-areas: "name meta total version";
  }
  .need-empty { padding: 20px 24px; }
  .room-head { padding: 12px 24px; }
  .item-row {
    grid-template-columns: minmax(0, 1fr) 10rem 6rem; grid-template-areas: "name meta end";
    padding: 8px 24px;
  }
  .item-row:has(> .item-row-variants:empty) { grid-template-areas: "name meta end"; }
  .item-row-variants { text-align: right; }

  /* The board becomes a horizontally scrolling strip of fixed-width columns.
     TODO 00185: on the board view the page ends at the bottom of the window. The
     main column is one window tall, the board takes what is left under the heading,
     every column runs the full board height and each card list scrolls on its own.
     The 24rem floor keeps a very short window from squeezing the board to a sliver;
     there the content area scrolls instead. Phone (under 820) is untouched: stacked
     columns inside a scrolling page. cites: pipeline-columns-full-height */
  .app-main:has(> .content > .view-board:not([hidden])) { height: 100dvh; min-height: 0; }
  .content:has(> .view-board:not([hidden])) {
    display: flex; flex-direction: column;
    min-height: 0; overflow-y: auto; padding-bottom: 16px;
  }
  .view-board { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  /* Flex items do not collapse margins: keep the heading-to-summary gap at 8px. */
  .view-board > #board-summary { margin-top: 0; }
  .board {
    flex-direction: row; overflow-x: auto;
    gap: var(--gap); padding-bottom: 8px;
    scroll-snap-type: x proximity;
    flex: 1 1 0; min-height: 24rem;
  }
  .stage { flex: 0 0 19rem; scroll-snap-align: start; }
  .stage-cards { flex: 1 1 auto; overflow-y: auto; }

  .sheet {
    left: 50%; right: auto; bottom: auto; top: 50%;
    transform: translate(-50%, -50%);
    width: min(30rem, calc(100vw - 3rem));
    border-radius: 12px;
  }

  .totals { grid-template-columns: repeat(4, minmax(0, 1fr)); }

  /* The by-source split has room to be a real table: numbers right-aligned. */
  .kpi-table thead { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; }
  .kpi-table tr { display: table-row; padding: 0; }
  .kpi-table th, .kpi-table td { display: table-cell; padding: 12px 16px; border-bottom: 1px solid var(--jm-row-rule); vertical-align: top; }
  .kpi-table thead th { background: var(--jm-ground); font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); color: var(--jm-ink-soft); text-align: right; }
  .kpi-table thead th:first-child { text-align: left; }
  .kpi-table th[scope="row"] { display: table-cell; margin: 0; }
  .kpi-table td { text-align: right; white-space: nowrap; }
  .kpi-table td::before { content: none; }
}

/* ================================================================ 1000px: full sidebar */

@media (min-width: 1000px) {
  .app { --shell-side-w: var(--sidebar-w); }
  .side-brand { justify-content: flex-start; padding: 0 20px; }
  .wordmark { display: inline; }
  .wordmark-icon { display: none; }
  .side-nav { padding: 16px 12px; }
  .nav-label { position: static; width: auto; height: auto; overflow: visible; clip: auto; }
  .nav-group + .nav-group { margin-top: 16px; padding-top: 0; border-top: 0; }
  .sidebar .nav-item {
    flex-direction: row; justify-content: flex-start; gap: 12px;
    min-height: var(--nav-h); padding: 8px 12px; text-align: left;
    font-size: var(--jm-text-base); line-height: 20px;
  }
  .sidebar .lbl { position: static; width: auto; height: auto; overflow: visible; clip: auto; }
  .sidebar .lbl-short { display: none; }
  .nav-foot { padding: 12px; }
  .account { justify-content: flex-start; padding: 4px 12px; }
  .account-text { position: static; width: auto; height: auto; overflow: visible; clip: auto; }

  .topbar { padding: 0 var(--gutter); }
  .content { padding: 32px var(--gutter) 64px; }
}

/* ================================================================ 1100px: laptop */

@media (min-width: 1100px) {
  .detail-cols { flex-direction: row; align-items: flex-start; }
  .detail-cols > * { flex: 1 1 0; min-width: 0; }
  .stage { flex: 0 0 20rem; }

  /* A record table has room to be a table again. */
  .rows.as-table { display: table; width: 100%; border-collapse: collapse; }
  .totals { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .qrow { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) 15rem; grid-template-areas: "name facts end"; }
  .review-facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: 16px; }
}

/* ================================================================ 1200px: Home two-up */

@media (min-width: 1200px) {
  .strip { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .kpi-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .home-cols { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 32px; align-items: start; }
}

/* ================================================================ 1500px: desktop */

@media (min-width: 1500px) {
  .content { max-width: 118rem; }
  .stage { flex: 0 0 21rem; }
}

/* ================================================================ preferences */

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}

@media (forced-colors: active) {
  .nav-item[aria-current="page"] { outline: 2px solid Highlight; }
  /* TODO 00100: a Soon row reads as unavailable in forced colours too. */
  .is-soon, .is-soon * { color: GrayText !important; }
  .soon { border-color: GrayText; }
}

/* TODO 00170.e.2 + F7: the booking confirmation email and emails that need a look
   (mockups deliverables/dashboard-design/00170e-booking-email and 00170f7-unconfirmed-and-held,
   approved, DECISIONS s227b 00170e2-and-f7-mockups-approved). Placed before the 00170.d
   block so it sits in no test's slice (GO-113). Tokens only, no breakpoints. */
.chip-danger { color: var(--jm-danger); background: var(--jm-danger-soft); }
.bk-email { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 12px 0 0; padding: 10px 12px; border-radius: var(--jm-radius); background: var(--jm-surface); box-shadow: inset 0 0 0 1px var(--jm-hairline); }
.bk-email p { margin: 0; flex: 1 1 16rem; min-width: 0; color: var(--jm-ink); overflow-wrap: anywhere; }
.bk-email .chip .i { width: 16px; height: 16px; margin-right: 4px; vertical-align: -3px; }
.bk-email a { flex: 1 1 100%; display: inline-flex; align-items: center; min-height: var(--tap); color: var(--jm-accent-text); font-weight: 600; }
.bk-email.is-sent { background: var(--jm-success-soft); box-shadow: none; }
.bk-email:focus-visible { outline: 2px solid var(--jm-focus-ring); outline-offset: 2px; }
.bk-more { margin: 8px 0 0; }
.bk-more summary { display: inline-flex; align-items: center; min-height: var(--tap); cursor: pointer; color: var(--jm-accent-text); font-weight: 600; }
.bk-more summary:focus-visible { outline: 2px solid var(--jm-focus-ring); outline-offset: 2px; border-radius: 6px; }
.bk-more[open] .booking-message { margin-top: 4px; }
.confirm-settings select { min-height: var(--tap); width: 100%; }
.confirm-settings .error { margin: 12px 0 0; }
.confirm-warn { margin: 12px 0 0; padding: 10px 12px; border-radius: var(--jm-radius); color: var(--jm-warning); background: var(--jm-warning-soft); }
.confirm-row-note { margin-left: 6px; }
.fu-steps li.is-unconfirmed .fu-when, .fu-steps li.is-waiting .fu-when { color: var(--jm-warning); font-weight: 600; }
.fu-steps li.is-refused .fu-when { color: var(--jm-danger); font-weight: 600; }
.fu-steps li.is-refused .fu-name, .fu-steps li.is-unconfirmed .fu-name { color: var(--jm-ink-soft); }
.fu-note { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 12px 0 0; padding: 10px 12px; border-radius: var(--jm-radius); background: var(--jm-surface); box-shadow: inset 0 0 0 1px var(--jm-hairline); }
.fu-note p { margin: 0; flex: 1 1 16rem; min-width: 0; color: var(--jm-ink); overflow-wrap: anywhere; }
.fu-note .fu-self { flex: 1 1 100%; display: inline-flex; align-items: center; justify-content: flex-start; min-height: var(--tap); padding: 0; color: var(--jm-accent-text); font-weight: 600; text-align: left; }
.fu-name-form { margin: 12px 0 0; padding: 12px; border-radius: var(--jm-radius); background: var(--jm-warning-soft); display: grid; gap: 10px; }
.fu-name-form > p { margin: 0; color: var(--jm-ink); }
.fu-name-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 12px; }
.fu-name-row .field { flex: 1 1 12rem; min-width: 0; margin: 0; }
.fu-name-row .field input { width: 100%; }
.fu-name-row .primary { flex: none; }
.fu-card .fu-name-form .error { margin: 0; }
.bubble-wrap.is-unconfirmed .bubble { box-shadow: inset 0 0 0 2px var(--jm-warning); background-image: none; }
.bubble-wrap.is-refused .bubble { opacity: .7; }
.bubble-meta .st-unconfirmed { color: var(--jm-warning); font-weight: 600; }
.bubble-meta .st-refused { color: var(--jm-danger); font-weight: 600; }
.send-unconfirmed { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 8px 0 0; padding: 10px 12px; border-radius: var(--jm-radius); background: var(--jm-warning-soft); }
.send-unconfirmed p { margin: 0; flex: 1 1 16rem; min-width: 0; color: var(--jm-ink); overflow-wrap: anywhere; }

/* TODO 00170.d: follow-up emails (mockup deliverables/dashboard-design/00170d-follow-ups,
   approved, DECISIONS s223 00170d-mockup-approved). The lead's card with its switch, and
   the Follow-ups tab and postal address in Settings > Messages. Tokens only, no breakpoints. */
.fu-toggle { display: inline-flex; align-items: center; gap: 10px; min-height: var(--tap); min-width: var(--tap); padding: 0 4px; border: 0; background: none; color: var(--jm-ink); font: 600 var(--jm-text-base)/20px var(--jm-font-ui); cursor: pointer; }
.fu-track { position: relative; flex: none; width: 48px; height: 28px; border-radius: 14px; background: var(--jm-border-control); transition: background .15s; }
.fu-track::after { content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: var(--jm-ground); box-shadow: 0 1px 2px var(--jm-sheet-shadow); transition: transform .15s; }
.fu-toggle[aria-checked="true"] .fu-track { background: var(--jm-accent); }
.fu-toggle[aria-checked="true"] .fu-track::after { transform: translateX(20px); }
.fu-toggle[aria-disabled="true"] { cursor: not-allowed; color: var(--jm-gray); }
.fu-toggle[aria-disabled="true"] .fu-track { background: var(--jm-hairline); }
.fu-toggle[aria-busy="true"] { cursor: progress; }
.fu-toggle:focus-visible { outline: 2px solid var(--jm-accent); outline-offset: 2px; border-radius: 8px; }
.fu-card .card-head { align-items: center; }
.fu-card .card-head h2 { margin-bottom: 0; }
.fu-state { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 8px 0 0; }
.fu-state p { margin: 0; color: var(--jm-ink); }
.fu-stops { margin: 8px 0 0; font-size: var(--jm-text-sm); color: var(--jm-ink-soft); }
.fu-card .error { margin: 12px 0 0; display: grid; gap: 4px; }
.fu-card .error a { color: inherit; font-weight: 600; justify-self: start; min-height: var(--tap); display: inline-flex; align-items: center; }
.fu-card .fu-link { display: inline-flex; align-items: center; min-height: var(--tap); }
.fu-steps { list-style: none; margin: 12px 0 0; padding: 0; border-top: 1px solid var(--jm-hairline); }
.fu-steps li { display: grid; grid-template-columns: 1.75rem minmax(0, 1fr) auto; gap: 2px 8px; align-items: baseline; padding: 10px 0; border-bottom: 1px solid var(--jm-row-rule, var(--jm-hairline)); }
.fu-n { font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); color: var(--jm-gray); }
.fu-name { color: var(--jm-ink); overflow-wrap: anywhere; }
.fu-when { font-size: var(--jm-text-sm); color: var(--jm-ink-soft); text-align: right; }
.fu-steps li.is-done .fu-name { color: var(--jm-ink-soft); }
.fu-steps li.is-next .fu-name { font-weight: 600; }
.fu-steps li.is-skipped .fu-name, .fu-steps li.is-skipped .fu-when { color: var(--jm-gray); }
#settings-messages #templates-channels { max-width: 30rem; }
#templates-channels button { white-space: nowrap; }
#settings-messages[data-channel="followups"] .sms-only,
#settings-messages[data-channel="followups"] .email-only,
#settings-messages[data-channel="followups"] #templates-list,
#settings-messages[data-channel="followups"] #template-form,
#settings-messages[data-channel="followups"] #templates-error,
#settings-messages[data-channel="followups"] #templates-status { display: none; }
#settings-messages:not([data-channel="followups"]) .followups-only { display: none; }
.fu-row .item-row-name { display: flex; gap: 8px; }
.fu-row .fu-n { flex: none; }
.fu-row .item-row-end { flex-wrap: wrap; gap: 0 4px; }
.fu-icon { min-width: var(--tap); padding: 0; display: inline-flex; align-items: center; justify-content: center; }
.fu-icon .i { width: 18px; height: 18px; }
.fu-icon[disabled] { opacity: .35; }
.fu-days { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.fu-form .fu-days input { width: 5.5rem; flex: none; }
.fu-days span { color: var(--jm-ink); font-size: var(--jm-text-base); }
.fu-form select { width: 100%; }
.fu-form .template-fields { display: grid; gap: 12px; max-width: 30rem; }
#fu-settings .home-error { margin: 0 0 12px; display: grid; gap: 8px; justify-items: start; }
#fu-settings .home-error span { margin: 0; }
.postal-settings .deposit-fields { grid-template-columns: minmax(0, 1fr); }
.postal-input { width: 100%; }

/* TODO 00170.c: the record's Messages card, texts and emails together (mockup
   deliverables/dashboard-design/00170c-record-messages, approved, DECISIONS s221).
   Placed here, before the 00170.b block, so it sits in no test's slice (GO-113). */
.ch-label { display: inline-flex; align-items: center; gap: 4px; margin-right: 6px; font: 600 var(--jm-text-xs)/16px var(--jm-font-ui); color: var(--jm-ink-soft); }
.ch-label .i, .ch-chip .i { width: 14px; height: 14px; }
.ch-chip { display: inline-flex; align-items: center; gap: 4px; }
.bubble.is-email { background: var(--jm-surface); border: 1px solid var(--jm-hairline); border-radius: 12px; display: grid; gap: 6px; white-space: normal; }
.bubble-wrap.out .bubble.is-email { background: var(--jm-accent-soft); border-color: transparent; border-radius: 12px 12px 4px 12px; }
.bubble-subj { font: 600 var(--jm-text-base)/1.35 var(--jm-font-ui); color: var(--jm-ink); overflow-wrap: anywhere; }
.bubble-email-body { white-space: pre-wrap; }
.bubble-email-body.is-folded { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.bubble-wrap .show-all { align-self: flex-end; min-height: var(--tap); padding: 0 4px; }
.bubble-wrap.is-blocked .bubble { opacity: .7; }
.bubble-wrap.out .bubble-meta { text-align: right; }
.channel-seg { margin: 0; }
.channel-seg button { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.channel-seg button .i { width: 18px; height: 18px; }
.compose-off { display: grid; gap: 12px; }
.compose-to { margin: -4px 0 0; font-size: var(--jm-text-sm); color: var(--jm-ink-soft); overflow-wrap: anywhere; }
.compose input[type="text"] { width: 100%; }
.compose textarea.email-body { min-height: calc(var(--tap) * 5); }
.compose input[aria-invalid="true"] { border-color: var(--jm-danger); }
.pv-footer { margin: 0; padding: 10px 12px; border: 1px dashed var(--jm-hairline); border-radius: var(--radius); font-size: var(--jm-text-sm); color: var(--jm-ink-soft); display: grid; gap: 4px; overflow-wrap: anywhere; }
.pv-footer-h { font: 600 var(--jm-text-xs)/16px var(--jm-font-ui); color: var(--jm-gray); }
.pv-footer p { margin: 0; }
.pv-link { color: var(--jm-accent-text); text-decoration: underline; }
.compose-ok { margin: 0; font-size: var(--jm-text-sm); color: var(--jm-ink); font-weight: 600; }

/* TODO 00170.b: Settings > Messages, the email templates (mockup approved, DECISIONS
   s220). The Texts / Emails switch is the live segmented control; the panel shows
   the side named by its data-channel. The email preview is the inbox view. */
.channel-switch { margin: 12px 0; max-width: 22rem; }
#settings-messages[data-channel="sms"] .email-only { display: none; }
#settings-messages[data-channel="email"] .sms-only { display: none; }
.email-subj { color: var(--jm-ink); font-weight: 600; }
.email-subj::after { content: "  "; white-space: pre; }
.email-card {
  max-width: 34rem; border: 1px solid var(--jm-hairline); border-radius: var(--jm-radius);
  background: var(--jm-ground); overflow: hidden;
}
.email-card-subject {
  padding: 10px 14px; background: var(--jm-surface); border-bottom: 1px solid var(--jm-hairline);
  font: 600 var(--jm-text-base)/1.4 var(--jm-font-body); color: var(--jm-ink); overflow-wrap: anywhere;
}
.email-card-k { font-weight: 400; color: var(--jm-ink-soft); font-size: var(--jm-text-sm); margin-right: 6px; }
.email-card-body {
  padding: 12px 14px; color: var(--jm-ink); font: 400 var(--jm-text-base)/1.45 var(--jm-font-body);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.email-card-body:empty::before { content: "Your message shows here."; color: var(--jm-gray); }
.email-card-foot {
  margin: 0 14px; padding: 10px 0 12px; border-top: 1px solid var(--jm-hairline);
  display: grid; gap: 4px; font-size: var(--jm-text-sm); line-height: 1.45; color: var(--jm-ink-soft);
}
.email-card-foot .fake-link { color: var(--jm-accent-text); text-decoration: underline; }
.email-card .ph-bad { color: var(--jm-danger); background: var(--jm-danger-soft); border-radius: 2px; padding: 0 2px; }
#template-email-subject:empty::before { content: "Your subject shows here."; color: var(--jm-gray); font-weight: 400; }

/* TODO 00169.d: the Messages page, one conversation, and the Texts card on a lead or
   a job (mockup deliverables/dashboard-design/00169d-messages-page, approved). */
.msgs-list { margin-top: 16px; border-top: 1px solid var(--jm-row-rule); }
a.msg-row {
  display: grid; grid-template-columns: 12px minmax(0, 1fr) auto;
  grid-template-areas: "dot name time" ". meta meta";
  column-gap: 8px; row-gap: 4px; align-items: center;
  min-height: 64px; padding: 12px 16px; border-bottom: 1px solid var(--jm-row-rule);
  text-decoration: none; color: inherit;
}
a.msg-row:hover { background: var(--jm-ground); }
.msg-dot { grid-area: dot; width: 8px; height: 8px; border-radius: 50%; }
.msg-row.is-unread .msg-dot { background: var(--jm-accent); }
.msg-name { grid-area: name; font: 400 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink); overflow-wrap: anywhere; }
.msg-row.is-unread .msg-name { font-weight: 600; }
.msg-time { grid-area: time; font-size: var(--jm-text-xs); line-height: 16px; color: var(--jm-gray); white-space: nowrap; }
.msg-row.is-unread .msg-time { color: var(--jm-ink); font-weight: 600; }
.msg-meta { grid-area: meta; display: flex; align-items: center; gap: 8px; min-width: 0; }
.msg-meta .chip { flex: none; }
.msg-snippet { font: 400 var(--jm-text-sm)/19.6px var(--jm-font-body); color: var(--jm-gray); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-row.is-unread .msg-snippet { color: var(--jm-ink-soft); }
.convo { display: flex; flex-direction: column; gap: 8px; }
.convo-day { align-self: center; margin: 8px 0 4px; font-size: var(--jm-text-xs); line-height: 16px; color: var(--jm-gray); }
.bubble-wrap { display: flex; flex-direction: column; gap: 4px; max-width: min(34rem, 85%); }
.bubble-wrap.in { align-self: flex-start; }
.bubble-wrap.out { align-self: flex-end; align-items: flex-end; }
.bubble {
  padding: 10px 14px; border-radius: 16px 16px 16px 4px; overflow-wrap: anywhere;
  font: 400 var(--jm-text-base)/1.45 var(--jm-font-body); white-space: pre-wrap;
  background: var(--jm-surface); color: var(--jm-ink); border: 1px solid var(--jm-hairline);
}
.bubble-wrap.out .bubble { border-radius: 16px 16px 4px 16px; background: var(--jm-accent-soft); border-color: transparent; }
.bubble-meta { font-size: var(--jm-text-xs); line-height: 16px; color: var(--jm-gray); }
.convo-event { align-self: stretch; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; margin: 0; padding: 8px 0; border-top: 1px solid var(--jm-hairline); border-bottom: 1px solid var(--jm-hairline); font-size: var(--jm-text-sm); color: var(--jm-ink-soft); text-align: center; }
.compose { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--jm-row-rule); display: grid; gap: 12px; }
.compose:empty { display: none; }
.compose-state { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.compose-state p { margin: 0; font-size: var(--jm-text-sm); color: var(--jm-ink-soft); }
.compose-h { font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); color: var(--jm-ink); }
.tpl-buttons { display: flex; flex-wrap: wrap; gap: 8px; }
.tpl-buttons .btn { min-height: var(--tap); padding: 0 14px; }
.tpl-buttons .btn[aria-pressed="true"] { background: var(--jm-accent-soft); box-shadow: inset 0 0 0 1px var(--jm-accent-text); }
.compose textarea {
  font: inherit; width: 100%; min-height: calc(var(--tap) * 3); padding: 10px;
  border: 1px solid var(--jm-border-control); border-radius: var(--radius);
  background: var(--jm-ground); color: var(--jm-ink); resize: vertical; line-height: 1.45;
}
.compose .field-hint, .compose .error { margin: 0; }
.compose-note { margin: 0; font-size: var(--jm-text-sm); color: var(--jm-ink-soft); }
.compose-actions, .name-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.compose-actions button, .name-actions button { flex: 1 1 100%; min-height: var(--tap); }
.sent-receipt { margin: 0; padding: 10px 12px; border-radius: var(--radius); background: var(--jm-success-soft); color: var(--jm-success); font-size: var(--jm-text-sm); }
.texts-card { scroll-margin-top: calc(var(--header-h-phone) + 16px); }
.texts-to { margin: -4px 0 12px; font-size: var(--jm-text-sm); color: var(--jm-ink-soft); }
.card-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 12px; }
.card-head h2 { margin-bottom: 8px; }
.card-head .btn-text { min-height: var(--tap); padding: 0 4px; }
.texts-none p { margin: 0 0 8px; color: var(--jm-ink-soft); }
.thread-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 16px; }
#thread-body .view-actions a.btn { min-height: var(--tap); display: inline-flex; align-items: center; }
.link-card fieldset { border: 0; margin: 0; padding: 0; display: grid; gap: 8px; }
.link-card legend { padding: 0; margin-bottom: 8px; font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); color: var(--jm-ink); }
.link-search input { width: 100%; }
.link-option { display: grid; grid-template-columns: 24px minmax(0, 1fr); gap: 12px; align-items: center; min-height: 56px; padding: 8px 12px; border: 1px solid var(--jm-border-control); border-radius: var(--radius); background: var(--panel); cursor: pointer; }
.link-option:has(input:checked) { border-color: var(--jm-accent-text); background: var(--jm-accent-soft); }
.link-option input { width: 20px; height: 20px; min-height: 0; margin: 0; accent-color: var(--jm-accent); }
.link-option-name { display: block; font: 600 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink); }
.link-option-meta { display: block; font-size: var(--jm-text-sm); color: var(--jm-gray); overflow-wrap: anywhere; }
.link-card .compose-actions { margin-top: 12px; }
#link-error { margin: 12px 0 0; }
.name-sheet h2 { margin: 0 0 4px; }
.name-sheet input { width: 100%; }
@media (min-width: 600px) {
  .compose-actions button, .name-actions button { flex: 0 0 auto; padding: 0 16px; }
}
@media (min-width: 820px) {
  a.msg-row { grid-template-columns: 12px minmax(0, 14rem) minmax(0, 1fr) 6rem; grid-template-areas: "dot name meta time"; column-gap: 16px; }
  .msg-time { text-align: right; }
  .texts-card { scroll-margin-top: calc(var(--header-h) + 16px); }
}

/* TODO 00169.c: Settings > Messages, the text templates (mockup approved, DECISIONS
   s216b). The form and rows reuse the Discounts classes; these are the additions. */
.templates-seen { margin: 0; }
.templates-state { color: var(--jm-ink); font-weight: 600; }
#templates-list { margin-top: 12px; }
#templates-error, #templates-load-error { margin-top: 12px; }
.template-form { margin-top: 16px; }
.template-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
.template-fields { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; align-content: start; }
.template-fields input { width: 100%; }
/* s217 MINOR 2: a field focused after an error clears the sticky top bar. */
.template-fields input, .template-fields textarea { scroll-margin-top: calc(var(--header-h-phone) + 16px); }
.template-fields textarea {
  font: inherit; width: 100%; min-height: calc(var(--tap) * 3); padding: 10px;
  border: 1px solid var(--jm-border-control); border-radius: var(--radius);
  background: var(--jm-ground); color: var(--jm-ink); resize: vertical; line-height: 1.45;
}
.template-form [aria-invalid="true"] { border-color: var(--jm-danger); box-shadow: inset 0 0 0 1px var(--jm-danger); }
.ph-insert { display: grid; gap: 6px; }
.ph-insert-h { font-size: var(--jm-text-sm); color: var(--jm-ink-soft); }
.ph-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.ph-chip { min-height: var(--tap); padding: 0 14px; }
.template-count { margin: 0; }
.template-count.is-over { color: var(--jm-danger); }
.template-preview { display: grid; gap: 6px; align-content: start; }
.msg-bubble {
  max-width: 34rem; padding: 12px 14px; border-radius: 16px 16px 16px 4px;
  background: var(--jm-surface); border: 1px solid var(--jm-hairline);
  color: var(--jm-ink); font: 400 var(--jm-text-base)/1.45 var(--jm-font-body);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.msg-bubble:empty::before { content: "Your message shows here."; color: var(--jm-gray); }
.msg-bubble .ph-bad { color: var(--jm-danger); background: var(--jm-danger-soft); border-radius: 2px; padding: 0 2px; }
.template-actions { margin-left: 0; }
.template-toggle { margin-left: auto; }
.item-row.message-row .item-row-variants { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.message-row .item-row-end { display: flex; flex-wrap: wrap; gap: 4px; justify-content: flex-end; align-items: center; }
@media (min-width: 820px) {
  .item-row.message-row { grid-template-columns: minmax(0, 12rem) minmax(0, 1fr) 12rem; }
  .item-row.message-row .item-row-variants { text-align: left; -webkit-line-clamp: 1; }
  .message-row .item-row-end { flex-wrap: nowrap; }
  .template-fields input, .template-fields textarea { scroll-margin-top: calc(var(--header-h) + 16px); }
}
@media (min-width: 1000px) {
  .template-grid { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 24px; }
}

/* ================================================================ Today's moves (TODO 00122)
   Additive only. Reuses the need-row look; the first column carries the start time
   instead of an icon. Phone: time, then name and route, then chip and Open. */

.home-today { margin-top: 40px; }
.today-list { list-style: none; margin: 0; padding: 0; }
.today-list:empty { border-top: 0; }
.need-row.today-row { grid-template-columns: minmax(0, 1fr); gap: 8px; }
.today-row .need-end { grid-column: 1; }
.today-time { font: 600 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink); font-variant-numeric: tabular-nums; }
.today-main { min-width: 0; }
/* TODO 00143: below 820px the name and route wrap, so a long origin never hides the
   destination on a phone (a title tooltip does not work on touch). */
.today-main .need-title,
.today-main .need-meta { overflow-wrap: anywhere; }
.today-list .need-empty { list-style: none; }

@media (min-width: 820px) {
  .home-today { margin-top: 48px; }
  .need-row.today-row { grid-template-columns: 7rem minmax(0, 1fr) auto; align-items: center; gap: 16px; }
  .today-row .need-end { grid-column: auto; }
  .today-main .need-title,
  .today-main .need-meta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* Job start time (TODO 00141): the Change time action in the job's card, its sheet,
 * and the Book sheet's start time error. Phone: buttons full width, stacked.
 * 820px: they sit at their own width, side by side. */

#book-sheet #book-time-error { margin: -4px 0 12px; }
.job-time-actions { margin-top: 12px; }
.job-time-actions button { width: 100%; min-height: var(--tap); }
.job-time-day { margin: 0 0 12px; color: var(--jm-ink); font-weight: 600; }
.job-time-sheet-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.job-time-sheet-actions button { width: 100%; min-height: var(--tap); }
#job-time-sheet input { width: 100%; min-height: var(--tap); }
#job-time-sheet .error { margin-top: 12px; }
#job-time-sheet button.primary:disabled { background: var(--jm-surface); color: var(--jm-text-disabled); border-color: var(--jm-border-control); cursor: not-allowed; }
#job-time-sheet button.ghost:disabled { color: var(--jm-text-disabled); border-color: var(--jm-border-control); cursor: not-allowed; }

@media (min-width: 820px) {
  .job-time-actions button { width: auto; }
  .job-time-sheet-actions { flex-direction: row; }
  .job-time-sheet-actions button { width: auto; min-width: 8rem; }
}

/* TODO 00189.d: Settings > People and the names on notes and moves (approved mockup
   deliverables/dashboard-design/00189-people-and-names, round 2; CEO rulings s265 R3, R5).
   People rows reuse .list/.item-row, the sheets reuse .sheet/.name-sheet. Tokens only;
   every button is at least one tap target tall. */
.people-summary .primary { min-height: var(--tap); padding: 0 16px; }
.people-hint { margin: -4px 0 12px; }
.people-list { list-style: none; margin: 0; padding: 0; }
.people-list .item-row { grid-template-columns: minmax(0, 1fr); grid-template-areas: "name" "meta" "end" "details"; row-gap: 8px; }
.people-list .item-row:last-child { border-bottom: 0; }
.people-list .item-row-variants { text-align: left; }
.people-chips { display: inline-flex; flex-wrap: wrap; gap: 6px; vertical-align: middle; }
.people-since { display: inline-block; margin-left: 4px; }
.people-lock .i { width: 14px; height: 14px; margin-right: 4px; fill: none; stroke: currentColor; stroke-width: 2; }
.people-actions { justify-content: flex-start; flex-wrap: wrap; gap: 8px; align-items: center; }
.people-actions button { min-height: var(--tap); padding: 0 14px; }
.people-always { display: inline-flex; align-items: center; min-height: var(--tap); }
.people-row.is-off .item-row-name { color: var(--jm-gray); font-weight: 400; }
.people-details { grid-area: details; margin-top: 4px; padding: 12px; border-radius: var(--jm-radius); background: var(--jm-ground); border: 1px solid var(--jm-hairline); }
.people-details .kv { margin: 0 0 8px; }
.people-details dd { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; }
.people-code { font: 600 var(--jm-text-sm)/20px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--jm-ink); overflow-wrap: anywhere; min-width: 0; }
.people-copy { min-height: var(--tap); min-width: var(--tap); padding: 0 12px; }
.people-newsecret { min-height: var(--tap); padding: 0 14px; }
.people-once { margin: 4px 0 0; padding: 8px 10px; border-radius: var(--jm-radius); background: var(--jm-warning-soft); color: var(--jm-warning); font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); }
#people-error { margin: 0 0 12px; }
.hist-line { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin: 0; font: 400 var(--jm-text-base)/22px var(--jm-font-body); color: var(--jm-ink); }
.hist-who { font: 600 var(--jm-text-base)/22px var(--jm-font-ui); color: var(--jm-ink); }
.hist-text { margin: 4px 0 0; color: var(--jm-ink); overflow-wrap: anywhere; }
.hist-when { margin: 4px 0 0; font-size: var(--jm-text-sm); color: var(--jm-gray); }
.hist-tag { height: 24px; text-decoration: none; }
a.hist-tag { min-height: 24px; }
@media (min-width: 820px) {
  .people-list .item-row { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name end" "meta end" "details details"; padding: 12px 24px 12px 16px; }
  .people-actions { justify-content: flex-end; }
}

/* TODO 00206: navigation links (approved mockup deliverables/dashboard-design/00206-nav-links).
   R1 the Performance period select; R2 a by-source name is a link, with its lead count, and
   the board's window note; R3 the Waiting on the customer section; R4 the job Quote card
   pointer. Mobile first: every control is a full tap target and wraps at 390. */
.perf-period-field { min-width: 0; }
.perf-period-field select { width: 100%; min-height: var(--tap); }
a.kpi-source { color: var(--jm-accent-text); text-decoration: underline; text-underline-offset: 2px; overflow-wrap: anywhere; }
a.kpi-source:hover { text-decoration-thickness: 2px; }
a.kpi-source:focus-visible { outline: 2px solid var(--jm-focus-ring); outline-offset: 2px; }
.kpi-source-count { display: block; font-size: var(--jm-text-xs); line-height: 16px; color: var(--jm-gray); }
.board-window { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 0 0 12px; }
.board-window .btn { min-height: var(--tap); }
.quotes-waiting { margin-bottom: 24px; }
.job-quote-pointer { margin: 0 0 12px; }
@media (min-width: 820px) {
  .perf-period-field { flex: 0 0 240px; }
}

/* ======================================================= add a lead (TODO 00123)
 * The + in the leftmost board column head, and the sheet holding the phone-in
 * form. Phone: the sheet fills the screen. Tablet and up: a large modal. */
.stage-add {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--tap); height: var(--tap); min-height: var(--tap); padding: 0;
  margin: -10px 0;
  border-radius: var(--jm-radius);
  background: var(--accent-soft); color: var(--jm-accent-text);
  border: 1px solid var(--jm-accent-text);
}
.stage-add:focus-visible { outline: 2px solid var(--jm-focus-ring); outline-offset: 2px; }
.stage-add svg { display: block; }
/* TODO 00148: busy while its token is fetched (disabled + aria-busy). */
.stage-add[aria-busy="true"] { opacity: 0.55; cursor: progress; }

.sheet.add-lead-sheet {
  top: 0; bottom: 0; left: 0; right: 0;
  max-height: none; height: 100%;
  border-radius: 0;
  display: flex; flex-direction: column; gap: 8px;
  padding: 8px 16px max(8px, env(safe-area-inset-bottom));
  overflow: hidden;
}
.sheet.add-lead-sheet[hidden] { display: none; }
.add-lead-head { display: flex; align-items: center; gap: 12px; }
.add-lead-head h2 { margin: 0; flex: 1 1 auto; min-width: 0; }
.add-lead-head button { min-height: var(--tap); }
.add-lead-frame {
  flex: 1 1 auto; width: 100%; min-height: 0;
  border: 1px solid var(--line); border-radius: var(--jm-radius);
  background: var(--jm-ground);
}
@media (min-width: 820px) {
  .sheet.add-lead-sheet {
    top: 50%; bottom: auto; left: 50%; right: auto;
    transform: translate(-50%, -50%);
    width: min(48rem, calc(100vw - 3rem));
    height: min(90vh, 60rem);
    border-radius: 12px;
    padding: 16px;
  }
}

/* TODO 00186.e: Settings > Pipeline, the board order (approved mockup deliverables/
   dashboard-design/00186e-pipeline-reorder, with s269a: both ends pinned). Reuses the
   Settings .list and .item-row vocabulary; only the position number, the arrow buttons,
   the pinned chip, the saved line and the preview strip are new. Phone first; 820px puts
   the chip on the name row. */
.pipeline-hint { margin: -4px 0 12px; }
.pipeline-readonly { margin: 0 0 12px; }
.pipeline-list { list-style: none; margin: 0; padding: 0; }
.pipeline-list .item-row { grid-template-columns: 2rem minmax(0, 1fr) auto; grid-template-areas: "pos name end" "pos meta end"; }
.pipeline-list .item-row:has(> .item-row-variants:empty) { grid-template-areas: "pos name end"; }
.pipeline-list .item-row:last-child { border-bottom: 0; }
.pipe-pos { grid-area: pos; font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); color: var(--jm-gray); text-align: center; }
.pipe-arrows { display: flex; gap: 8px; }
.pipe-arrow { width: var(--tap); height: var(--tap); min-height: var(--tap); padding: 0; display: inline-flex; align-items: center; justify-content: center; color: var(--jm-accent-text); border-color: var(--jm-accent-text); background: var(--jm-ground); }
.pipe-arrow:hover:not(:disabled) { background: var(--jm-accent-soft); }
.pipe-arrow svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.pipe-arrow:disabled { color: var(--jm-text-disabled); border-color: var(--jm-hairline); background: var(--jm-surface); cursor: not-allowed; }
.pipe-lock .i { width: 14px; height: 14px; margin-right: 4px; fill: none; stroke: currentColor; stroke-width: 2; }
.pipeline-list .item-row.is-moved { background: var(--jm-accent-soft); transition: background 0.6s ease; }
.pipeline-list .item-row.is-dragging { opacity: 0.5; }
.pipeline-list .item-row.drop-before { box-shadow: inset 0 3px 0 var(--jm-accent-text); }
.pipeline-actions { margin-top: 16px; display: flex; gap: 8px; flex-wrap: wrap; }
.pipeline-actions button { min-height: var(--tap); }
.pipeline-actions[hidden], .pipeline-saved[hidden] { display: none; }
.pipeline-saved { display: flex; align-items: center; gap: 8px; margin: 16px 0 0; font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); color: var(--jm-success); }
.pipeline-saved .i { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2.5; }
.pipeline-preview-h { margin: 32px 0 8px; font-size: var(--jm-text-base); color: var(--jm-ink-soft); }
.pipeline-preview { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.pipeline-preview li { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: var(--jm-radius); border: 1px solid var(--jm-hairline); border-top: 3px solid var(--jm-accent-text); background: var(--jm-ground); font: 600 var(--jm-text-sm)/20px var(--jm-font-ui); color: var(--jm-ink); }
.pipeline-preview li[data-terminal="true"] { border-top-color: var(--jm-gray); color: var(--jm-ink-soft); }
.pipeline-preview .n { font-weight: 400; color: var(--jm-gray); }
@media (min-width: 820px) {
  .pipeline-list .item-row, .pipeline-list .item-row:has(> .item-row-variants:empty) { grid-template-columns: 2rem minmax(0, 1fr) auto auto; grid-template-areas: "pos name meta end"; padding: 8px 24px 8px 12px; }
  .pipeline-list .item-row-variants { text-align: left; }
}

/* TODO 00165: Settings > Pricing, the discounts, and the discount on the quote form.
   Phone: one field a row, the add button under the heading. 820px: the form's three
   fields share a row. The reason line sits under the discount in the breakdown. */
.discounts-settings { margin-top: 32px; padding-top: 20px; border-top: 1px solid var(--jm-hairline); }
.discounts-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px; }
.discounts-head h3 { margin: 0; }
.discounts-head h3:focus { outline: none; }
.discount-form { margin: 16px 0 0; padding: 12px; border: 1px solid var(--jm-border-control); border-radius: var(--jm-radius); background: var(--jm-ground); }
.discount-form h4 { margin: 0 0 12px; }
.discount-fields { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.discount-fields input, .discount-fields select { width: 100%; }
#discounts-list { margin-top: 12px; }
.discount-row .item-row-end { display: flex; flex-wrap: wrap; gap: 4px; justify-content: flex-end; }
#discounts-error, #discounts-load-error { margin-top: 12px; }
.quote-discount select, .quote-discount-reason input { width: 100%; }
.quote-discount-reason { grid-column: 1 / -1; }
.quote-discount-why { color: var(--jm-gray); }
@media (min-width: 820px) {
  .discount-fields { grid-template-columns: 2fr 1fr 1fr; }
  .item-row.discount-row { grid-template-columns: minmax(0, 1fr) 8rem 12rem; }
  .discount-row .item-row-variants { text-align: left; }
  .discount-row .item-row-end { flex-wrap: nowrap; }
}

/* ================================================================ Settings > Pricing, rate rules (TODO 00163) */

/* TODO 00163: Settings > Pricing, the rate rules. Same vocabulary as the deposit
 * form; it opens the panel, so no rule above it. Phone: one field a row. 820px: two
 * to a row. 1280px: three (at 1024 a two-line label pushed one input out of line). */
.rates-settings { margin-top: 8px; }
.rates-settings h3 { margin: 0 0 12px; }
.rates-settings h3:focus { outline: none; }
.rates-fields { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.rates-fields input { width: 100%; }
.rates-fields input:disabled { background: var(--jm-surface); color: var(--jm-gray); }
.rates-fields .field-hint { margin: 4px 0 0; }
#rates-error, #rates-load-error { margin-top: 12px; }
.pricing-zip-h { margin: 32px 0 12px; padding-top: 20px; border-top: 1px solid var(--jm-hairline); }
@media (min-width: 820px) {
  .rates-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1280px) {
  .rates-fields { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ================================================================ Settings > Calendar (TODO 00126.b) */
.calendar-panel .calendar-kv { padding: 12px 0; border-top: 1px solid var(--jm-hairline); border-bottom: 1px solid var(--jm-hairline); }
.calendar-panel .calendar-kv dd .chip { vertical-align: middle; }
.calendar-actions { margin: 16px 0 0; }
.calendar-actions button { flex: 1 1 100%; }
.calendar-actions button:disabled { background: var(--jm-surface); color: var(--jm-text-disabled); border-color: var(--jm-border-control); cursor: not-allowed; }
.calendar-panel .error { margin-top: 12px; }
p.calendar-notice { margin: 0 0 16px; }
/* TODO 00161.a3: Settings > Connections, the QuickBooks panel (approved mockup
   deliverables/dashboard-design/00161-quickbooks-connections, CEO rulings s292). The
   Calendar panel's kv and actions above, plus a company line. Phone first: the buttons
   are full width until 820px, as Calendar's are; its two wide rules share the 820px
   query below. The subnav entry whose only child is hidden takes no slot (the link
   until QuickBooks answers, or the Soon entry after). */
.subnav li:has(> .nav-item[hidden]) { display: none; }
.qb-panel { padding: 16px; border: 1px solid var(--jm-hairline); border-radius: var(--jm-radius); background: var(--jm-ground); }
.qb-title { margin: 0 0 12px; font-size: var(--jm-text-lg); }
.qb-company { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 12px; }
.qb-company-name { font: 700 var(--jm-text-xl)/1.2 var(--jm-font-heading); color: var(--jm-ink); overflow-wrap: anywhere; margin-right: 4px; }
.qb-panel .calendar-kv { padding: 12px 0; border-top: 1px solid var(--jm-hairline); border-bottom: 1px solid var(--jm-hairline); }
.qb-panel .error, .qb-panel .booking-status { margin-top: 12px; }
.qb-note { margin: 12px 0 0; color: var(--jm-ink-soft); }
.qb-actions { gap: 8px; }
.qb-actions .btn-text { min-height: var(--tap); }
.qb-danger { color: var(--jm-danger); }
.qb-danger:hover { background: var(--jm-danger-soft); }
.qb-danger-solid { color: var(--jm-danger) !important; border-color: var(--jm-danger) !important; }
.qb-danger-solid:hover { background: var(--jm-danger-soft) !important; }
@media (min-width: 820px) {
  .calendar-actions button { flex: 0 0 auto; }
  /* TODO 00161.a3: Disconnect sits at the far end; the confirm's buttons size to fit. */
  .qb-actions .qb-danger { margin-left: auto; }
  .booking-actions.qb-actions button { flex: 0 0 auto; }
}

/* ================================================================ customer booking and deposit (TODO 00131.c, .d) */

/* TODO 00131.c: the customer booking block inside the quote card. Phone: one column,
 * buttons full width so each is a whole-finger target. 820px: the date and time sit
 * side by side and the buttons size to their text. */
.booking-block { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--jm-hairline); }
.booking-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-bottom: 12px; }
.booking-head h3 { margin: 0; }
.booking-head h3:focus { outline: none; }
.booking-head h3:focus-visible { outline: 2px solid var(--jm-focus-ring); outline-offset: 2px; }
.booking-facts { margin-bottom: 4px; }
.booking-actions { margin: 16px 0 0; }
.booking-actions button { flex: 1 1 100%; }
.booking-confirm { margin-top: 16px; padding: 12px; border: 1px solid var(--jm-border-control); border-radius: var(--jm-radius); background: var(--jm-ground); }
.booking-confirm p { font: 600 var(--jm-text-base)/20px var(--jm-font-ui); color: var(--jm-ink); margin: 0 0 12px; }
.booking-confirm p.field-error { font: inherit; }
.booking-fields { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.booking-fields input { width: 100%; }
.booking-status { color: var(--jm-success); font-weight: 600; margin: 8px 0 0; }
.booking-manual, .booking-message { margin-top: 12px; }
.booking-manual input { width: 100%; }
.booking-message textarea {
  font: inherit; width: 100%; min-height: calc(var(--tap) * 2); padding: 10px;
  border: 1px solid var(--jm-border-control); border-radius: var(--radius);
  background: var(--jm-surface); color: var(--jm-ink); resize: vertical;
}
#booking-block .field-hint { margin: 8px 0 0; }
/* s202 fix m3: the new-link warning sits in the button row, directly under the copy
 * button it belongs to (the row's 12px gap less 6px). 820px: the buttons share one
 * row, so the warning takes the line below them. */
#booking-block .booking-actions .booking-link-warning { flex: 1 1 100%; margin: -6px 0 0; }
#booking-block .error { margin-top: 12px; }
.field-error { color: var(--danger); font-size: var(--jm-text-sm); line-height: 18px; margin: 4px 0 0; }

/* TODO 00131.d: Settings > Pricing, deposit and booking. Phone: one field a row.
 * 820px: two to a row, the contact line full width. */
.deposit-settings { margin-top: 32px; padding-top: 20px; border-top: 1px solid var(--jm-hairline); }
.deposit-settings h3 { margin: 0 0 12px; }
.deposit-settings h3:focus { outline: none; }
.deposit-fields { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.deposit-fields input, .deposit-fields select { width: 100%; }
.deposit-fields input:disabled, .deposit-fields select:disabled { background: var(--jm-surface); color: var(--jm-gray); }
.deposit-seen { margin: 16px 0 0; padding: 10px 12px; background: var(--jm-surface); border-radius: var(--radius); color: var(--jm-ink-soft); font-size: var(--jm-text-sm); }
.deposit-actions { margin: 16px 0 0; align-items: center; }
.deposit-actions button { flex: 1 1 100%; }
.deposit-actions .booking-status { margin: 0; }
#deposit-error, #deposit-load-error { margin-top: 12px; }


@media (min-width: 820px) {
  .booking-actions button, .deposit-actions button { flex: 0 0 auto; }
  #booking-block .booking-actions .booking-link-warning { order: 1; margin: -4px 0 0; }
  .booking-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .deposit-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .deposit-contact { grid-column: 1 / -1; }
}

/* TODO 00166: the recommended crew on the lead view and the quote card, and the
   plain warning when a quote's movers are below it (shown, never refused). */
.crew-actions { margin-top: 12px; }
.crew-sheet .field select, .lead-source-sheet .field select { width: 100%; }
.quote-crew { margin: 0 0 12px; }
.crew-below { display: block; color: var(--warn); font-weight: 600; }

/* TODO 00168: drive legs worked out from the addresses. The truck pickup field and
   the tools row span the form; each leg shows its route miles under it. */
.quote-truck-pickup, .quote-drive-tools { grid-column: 1 / -1; }
.quote-drive-tools { display: grid; gap: 4px; justify-items: start; }
.quote-drive-tools p { margin: 0; }
.quote-drive-status:empty { display: none; }
.drive-leg-note { display: block; color: var(--jm-ink); }
.quote-drive { margin: 0 0 12px; }
.quote-drive-credit { display: block; font-size: var(--jm-text-sm); color: var(--ink-soft); }
