/* ═══════════════════════════════════════════════════════════════════════
   DECKHAND · web design system — "BLUEPRINT" (owner-picked direction A, 2026-06-09)
   Drafting-table aesthetic: graph-paper parchment canvas · ink sidebar with a
   safety-orange datum edge · technical mono annotations · square corners ·
   hard offset shadows. Saira display+UI / Spline Sans Mono labels.
   Self-contained (no Tailwind). Loaded app-wide via the asset manifest
   (office shell, auth screens, plain pages). The variable NAMES are the
   stable contract every view consumes — the Blueprint retheme lands through
   their VALUES (--brass now carries the safety-orange accent).
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  /* Surfaces — drafting paper */
  --bg: #efebe0; --surface: #f8f5ec; --surface-lo: #f1ede0; --surface-hi: #fcfaf3;
  /* Ink sidebar */
  --nav-bg: #16202b; --nav-mid: #1e2a38; --nav-border: #2a3744;
  --nav-text: #aeb6c0; --nav-text-hi: #ece8dc; --nav-active: rgba(216,84,42,0.15);
  /* Borders — pencil rules */
  --border: #c9c2b0; --border-lo: #dcd6c6;
  /* Text — ink. --text-3 darkened from #8a8576 (3.1:1 on paper — failed WCAG AA) to clear 4.5:1 on every
     surface incl. --surface-hi while staying a muted warm taupe (a11y pass 2026-06-14). */
  --text-1: #16202b; --text-2: #3c4654; --text-3: #6b6657;
  /* Safety-orange accent (the historical --brass names are the app-wide contract). --brass-cta is the
     filled-button fill: minimally darker so WHITE label text clears 4.5:1 (4.02→4.68) without shifting the
     signature accent used for borders/icons/pills. */
  --brass: #d8542a; --brass-hi: #e4683f; --brass-lo: #b23f1c; --brass-cta: #c94a22;
  --brass-soft: rgba(216,84,42,0.10); --brass-pill: rgba(216,84,42,0.14);
  /* Lifecycle stage palette (the six office columns) — blueprint blues + site green */
  --s-lead: #6b7686; --s-qualified: #22456b; --s-quoting: #2e6fa3;
  --s-sold: #2e7d52; --s-completed: #266b47; --s-closed: #4a5560;
  /* Channel */
  --chan-lowes: #22456b; --chan-native: #a4632a;
  /* Semantic. --success darkened from #2e7d52 (4.2:1 — just under AA) to 4.5:1 on paper; it's used as
     `.money.pos` TEXT, not only as a status dot (a11y pass 2026-06-14). */
  --danger: #c2362b; --warning: #c7791b; --success: #2c764d;
  /* Designer intersection-snap badge — pink, distinct from the brass accent (iPad SnapPipeline parity). */
  --designer-snap-cross: #c81d67;
  /* Type */
  --font-display: "Saira", system-ui, sans-serif;
  --font-ui: "Saira", system-ui, -apple-system, sans-serif;
  --font-mono: "Spline Sans Mono", "SFMono-Regular", monospace;
  /* Geometry — square, technical */
  --sidebar-w: 248px; --r-sm: 2px; --r-md: 3px; --r-lg: 4px; --r-pill: 3px;
  --shadow-card: 0 0 0 rgba(0,0,0,0);
  --shadow-lift: 4px 4px 0 rgba(22,32,43,0.10);
  /* Shared inline-control height — so controls sharing a row (a status pill next to action buttons,
     a button next to a select, a composer's send next to its channel picker) align to one baseline. */
  --control-h: 34px;
}

* { box-sizing: border-box; }

body.office {
  margin: 0;
  background: var(--bg);
  /* Drafting-paper grid — faint blueprint-blue graph lines under everything. */
  background-image:
    linear-gradient(rgba(34,69,107,0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(34,69,107,0.05) 1px, transparent 1px);
  background-size: 26px 26px;
  color: var(--text-1);
  font-family: var(--font-ui);
  font-size: 13.5px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.ico { width: 18px; height: 18px; stroke: currentColor; fill: none;
  stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; flex: none; }

/* ── Shell ─────────────────────────────────────────────────────────────── */
.office-shell { display: grid; grid-template-columns: var(--sidebar-w) 1fr; min-height: 100vh; }

/* ── Sidebar ───────────────────────────────────────────────────────────── */
.office-side {
  background: linear-gradient(180deg, var(--nav-bg) 0%, #111923 100%);
  color: var(--nav-text); display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
  /* The drafting datum edge — a safety-orange rule separating ink from paper. */
  border-right: 2px solid var(--brass);
}
.office-side::-webkit-scrollbar { width: 7px; }
.office-side::-webkit-scrollbar-thumb { background: var(--nav-border); border-radius: 4px; }

.office-logo { display: flex; align-items: center; gap: 11px; padding: 20px 18px 16px; }
.office-logo-tile {
  width: 38px; height: 38px; border-radius: var(--r-sm); flex: none;
  display: grid; place-items: center; color: var(--brass);
  background: transparent; border: 1.5px solid var(--brass);
}
.office-logo-tile .ico { width: 21px; height: 21px; stroke-width: 2; }
.office-logo b { color: #fff; font-family: var(--font-display); font-weight: 700;
  font-size: 18px; letter-spacing: -0.01em; line-height: 1; }
.office-logo small { color: var(--nav-text); font-family: var(--font-mono);
  font-size: 8.5px; letter-spacing: 0.16em; }

.office-nav { padding: 6px 12px 16px; display: flex; flex-direction: column; gap: 1px; flex: 1; }
.office-nav-label { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.16em;
  text-transform: uppercase; color: #5d7793; padding: 14px 10px 5px; }
.office-navitem {
  display: flex; align-items: center; gap: 11px; padding: 8px 10px;
  border-radius: var(--r-sm); color: var(--nav-text); text-decoration: none;
  font-size: 13px; font-weight: 500; border-left: 2px solid transparent;
  transition: background .12s, color .12s;
}
.office-navitem .ico { width: 16.5px; height: 16.5px; opacity: .85; }
a.office-navitem:hover { background: var(--nav-mid); color: var(--nav-text-hi); }
.office-navitem.active {
  background: var(--nav-active); color: #fff; font-weight: 600;
  border-left-color: var(--brass-hi);
}
.office-navitem.active .ico { color: var(--brass-hi); opacity: 1; }
.office-navitem.is-static { cursor: default; opacity: .72; }

.office-navfoot { padding: 14px 18px; border-top: 1px solid var(--nav-border);
  display: flex; align-items: center; gap: 10px; color: var(--nav-text); font-size: 12.5px; }

/* ── Main / topbar ─────────────────────────────────────────────────────── */
.office-main { display: flex; flex-direction: column; min-width: 0; }
.office-topbar {
  position: sticky; top: 0; z-index: 5;
  display: flex; align-items: center; gap: 16px;
  padding: 15px 28px; background: rgba(239,235,224,0.9);
  backdrop-filter: saturate(140%) blur(8px);
  border-bottom: 1px solid var(--border);
}
.office-toptitle { font-family: var(--font-display); font-weight: 700; font-size: 23px;
  line-height: 1.1; letter-spacing: -0.01em; color: var(--text-1); margin: 0; } /* now an <h1> — reset UA margin */
/* Skip-to-content link: visually hidden until keyboard focus, then pinned top-left (a11y 2026-06-14). */
.skip-link { position: absolute; left: 8px; top: -48px; z-index: 1000; padding: 9px 14px; border-radius: var(--r-sm);
  background: var(--nav-bg); color: var(--nav-text-hi); font-family: var(--font-ui); font-weight: 600; font-size: 13px;
  text-decoration: none; transition: top .12s; }
.skip-link:focus { top: 8px; outline: 2px solid var(--brass); outline-offset: 2px; }
.office-topsub { font-size: 12px; color: var(--text-2); margin-top: 2px; }
.office-topspacer { flex: 1; }
.office-search {
  display: flex; align-items: center; gap: 8px; width: 230px;
  padding: 7px 12px; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-pill); color: var(--text-3); font-size: 12.5px;
}
.office-search .ico { width: 15px; height: 15px; flex: none; }
.office-search:focus-within { border-color: var(--brass); }
.office-search-input { border: none; background: transparent; outline: none; width: 100%;
  font-family: var(--font-ui); font-size: 12.5px; color: var(--text-1); padding: 0; }
.office-search-input::placeholder { color: var(--text-3); }
.search-results { display: flex; flex-direction: column; gap: 16px; max-width: 760px; }

/* ── Status badge (reusable — compliance/active/etc.) ──────────────────── */
.badge { display: inline-flex; align-items: center; gap: 5px; padding: 2px 9px; border-radius: var(--r-pill);
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.02em; text-transform: capitalize;
  white-space: nowrap; /* a pill must never wrap to two lines (e.g. "Manual Procurement", F013) */
  border: 1px solid var(--border); color: var(--text-2); background: var(--surface-hi); }
.badge.ok   { color: #15803d; border-color: rgba(21,128,61,0.45);  background: rgba(22,163,74,0.14); }
.badge.warn { color: #a16207; border-color: rgba(245,158,11,0.50); background: rgba(245,158,11,0.17); }
.badge.bad  { color: #b91c1c; border-color: rgba(220,38,38,0.45);  background: rgba(220,38,38,0.12); }
.badge.muted { color: var(--text-3); }
.settings-stack { display: flex; flex-direction: column; gap: 24px; }

/* ── Dashboard (wf-office) ─────────────────────────────────────────────── */
.kpi-row { display: grid; grid-template-columns: repeat(5, 1fr); gap: 14px; margin-bottom: 20px; }
@media (max-width: 1100px) { .kpi-row { grid-template-columns: repeat(2, 1fr); } }
.kpi { display: flex; flex-direction: column; gap: 3px; padding: 16px 18px; text-decoration: none;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-card); }
.kpi:hover { box-shadow: var(--shadow-lift); }
.kpi-val { font-family: var(--font-display); font-weight: 700; font-size: 28px; color: var(--text-1); line-height: 1; }
.kpi-val.block { color: var(--danger); }
.kpi-label { font-size: 12.5px; color: var(--text-2); margin-top: 4px; }
.kpi-trend { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.04em; color: var(--text-3); }
.kpi-trend.block { color: var(--danger); }

.dash-twocol { display: grid; grid-template-columns: 1.4fr 1fr; gap: 18px; align-items: start; }
@media (max-width: 900px) { .dash-twocol { grid-template-columns: 1fr; } }
.attn-row { display: flex; align-items: center; gap: 11px; padding: 11px 2px; text-decoration: none;
  border-bottom: 1px solid var(--border-lo); }
.attn-row:last-child { border-bottom: none; }
.attn-row:hover .attn-ttl { color: var(--brass-lo); }
.attn-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.attn-dot.block { background: var(--danger); }
.attn-dot.wait { background: var(--warning); }
.attn-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.attn-ttl { font-size: 13px; font-weight: 500; color: var(--text-1); }
.attn-meta { font-size: 11.5px; color: var(--text-3); }
.chan-bar { display: flex; height: 26px; border-radius: 7px; overflow: hidden; border: 1px solid var(--border); margin-bottom: 14px; }
.chan-seg { display: grid; place-items: center; font-family: var(--font-mono); font-size: 10px; color: #fff;
  min-width: 0; overflow: hidden; white-space: nowrap; padding: 0 4px; }
.chan-seg.lowes { background: var(--chan-lowes); }
.chan-seg.native { background: var(--chan-native); }
.report-summary { display: grid; grid-template-columns: repeat(2, minmax(0, 280px)); gap: 14px; margin-bottom: 20px; }
.report-summary .kpi-val .badge { font-size: 13px; padding: 4px 12px; }
.office-user { display: flex; align-items: center; gap: 9px; }
.office-avatar { width: 30px; height: 30px; border-radius: 50%; flex: none;
  display: grid; place-items: center; color: #fff; font-weight: 600; font-size: 12px;
  background: linear-gradient(150deg, #2a4a6e, #16304f); }
.office-username { font-size: 12.5px; color: var(--text-2); }
.office-signout-form { margin: 0; line-height: 0; }
.office-signout { display: grid; place-items: center; width: 30px; height: 30px; padding: 0;
  background: transparent; border: 1px solid transparent; border-radius: var(--r-sm);
  color: var(--text-3); cursor: pointer; transition: background .12s, color .12s, border-color .12s; }
.office-signout:hover { background: var(--surface); border-color: var(--border); color: var(--brass-lo); }
.office-signout .ico { width: 16px; height: 16px; }

.office-content { padding: 24px 28px 48px; }

@media (max-width: 760px) {
  .office-shell {
    display: block;
    min-width: 0;
  }

  .office-side {
    position: sticky;
    top: 0;
    z-index: 8;
    height: auto;
    overflow: visible;
    border-right: 0;
    border-bottom: 1px solid var(--nav-border);
  }

  .office-logo {
    padding: 12px 14px 8px;
  }

  .office-logo-tile {
    width: 32px;
    height: 32px;
  }

  .office-logo b {
    font-size: 16px;
  }

  .office-nav {
    flex: none;
    flex-direction: row;
    gap: 6px;
    overflow-x: auto;
    padding: 8px 12px 12px;
    scrollbar-width: thin;
  }

  .office-nav-label,
  .office-navfoot {
    display: none;
  }

  .office-navitem {
    flex: 0 0 auto;
    white-space: nowrap;
    padding: 7px 10px;
  }

  .office-main {
    min-width: 0;
  }

  .office-topbar {
    position: static;
    flex-wrap: wrap;
    gap: 10px;
    padding: 13px 14px;
  }

  .office-toptitle {
    font-size: 21px;
    overflow-wrap: anywhere;
  }

  .office-topspacer {
    display: none;
  }

  .office-search {
    order: 3;
    width: 100%;
  }

  .office-user {
    margin-left: auto;
  }

  .office-username {
    max-width: 9rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .office-content {
    padding: 16px 14px 32px;
  }
}

/* ── Buttons / pills / eyebrow ─────────────────────────────────────────── */
.btn { display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  padding: 8px 14px; border-radius: var(--r-sm); font-size: 12.5px; font-weight: 600;
  font-family: var(--font-ui); border: 1px solid var(--border); background: var(--surface);
  color: var(--text-1); text-decoration: none; transition: background .12s, border-color .12s, transform .06s; }
.btn .ico { width: 15px; height: 15px; }
.btn:hover { background: var(--surface-hi); }
.btn:active { transform: translateY(1px); }
.btn.prim { background: var(--brass-cta);
  border-color: var(--brass-lo); color: #fff; font-weight: 700;
  box-shadow: 3px 3px 0 rgba(22,32,43,0.12); } /* drafting offset shadow */
.btn.prim:hover { filter: brightness(1.05); }
.btn.prim:active { transform: translate(1px,1px); box-shadow: 2px 2px 0 rgba(22,32,43,0.12); }
.btn.ghost { background: transparent; }
.btn.sm { padding: 5px 10px; font-size: 11.5px; }

.eyebrow { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-3); }

.pill { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px;
  border-radius: var(--r-pill); border: 1px solid var(--border); background: var(--surface);
  font-size: 11.5px; font-weight: 500; color: var(--text-2); cursor: pointer; }
.pill.on { background: var(--brass-pill); border-color: var(--brass); color: var(--brass-lo); font-weight: 600; }

/* ── Channel badge ─────────────────────────────────────────────────────── */
.chan { display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px;
  border-radius: var(--r-pill); border: 1px solid; font-family: var(--font-mono);
  font-size: 9.5px; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; }
.chan .ico { width: 10px; height: 10px; stroke-width: 2; }
.chan.lowes  { color: var(--chan-lowes);  border-color: var(--chan-lowes);  background: rgba(47,95,160,0.08); }
.chan.native { color: var(--chan-native); border-color: var(--chan-native); background: rgba(154,118,54,0.10); }

/* ── Stage dot ─────────────────────────────────────────────────────────── */
.stage-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; display: inline-block; }
.s-lead{background:var(--s-lead)} .s-qualified{background:var(--s-qualified)}
.s-quoting{background:var(--s-quoting)} .s-sold{background:var(--s-sold)}
.s-completed{background:var(--s-completed)} .s-closed{background:var(--s-closed)}

/* ── Pipeline board ────────────────────────────────────────────────────── */
.pipeline-toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 18px; }
.pipeline-board { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(232px, 1fr);
  gap: 16px; overflow-x: auto; padding-bottom: 8px; align-items: start; }
.pipeline-col { display: flex; flex-direction: column; gap: 10px; }
.pipeline-col-head { display: flex; align-items: center; gap: 8px; padding: 2px 4px 4px; }
.pipeline-col-head b { font-size: 13px; color: var(--text-1); font-weight: 600; }
.pipeline-count { margin-left: auto; font-family: var(--font-mono); font-size: 11px;
  color: var(--text-2); background: var(--surface-hi); border: 1px solid var(--border-lo);
  border-radius: var(--r-pill); padding: 1px 8px; }
.pipeline-cards { display: flex; flex-direction: column; gap: 10px; }

.project-card { display: flex; flex-direction: column; gap: 7px; padding: 12px 13px;
  background: var(--surface); border: 1px solid var(--border-lo); border-left: 4px solid var(--c, var(--s-lead));
  border-radius: var(--r-md); box-shadow: var(--shadow-card); text-decoration: none; color: inherit;
  transition: transform .1s, box-shadow .1s, border-color .1s; }
.project-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift); }
.card-top { display: flex; align-items: center; justify-content: space-between; }
.card-age { font-family: var(--font-mono); font-size: 10px; color: var(--text-3); }
.card-name { font-size: 14px; font-weight: 600; color: var(--text-1); }
.card-name .muted { color: var(--text-3); font-weight: 400; }
.card-mid { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.card-trades { font-size: 12px; color: var(--text-2); }
.card-val { font-family: var(--font-mono); font-size: 12px; font-weight: 500; color: var(--text-1); }
.card-note { font-size: 11.5px; color: var(--text-3); border-top: 1px solid var(--border-lo); padding-top: 6px; }
.col-empty { font-size: 11.5px; color: var(--text-3); text-align: center; padding: 14px 0;
  border: 1px dashed var(--border); border-radius: var(--r-md); }

.state-region {
  min-width: 0;
  width: 100%;
}
.state-region.is-empty,
.state-region.is-loading,
.state-region.is-error {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: clamp(14px, 3vw, 28px);
  border: 1px dashed var(--border);
  border-radius: var(--r-md);
  color: var(--text-3);
  font-size: clamp(11.5px, 1.5vw, 12.5px);
  line-height: 1.4;
  overflow-wrap: anywhere;
  text-align: center;
}
.state-region.is-error { color: var(--danger); }
.state-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.state-region.is-loading .state-dot {
  animation: statePulse 1.2s ease-in-out infinite;
}
@keyframes statePulse {
  0%, 100% { opacity: .35; transform: scale(.82); }
  50% { opacity: 1; transform: scale(1); }
}

/* ── Project detail ────────────────────────────────────────────────────── */
.proj-head { display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 22px; }
.proj-code { font-family: var(--font-mono); font-size: 12px; font-weight: 500; color: var(--brass-lo);
  background: var(--brass-soft); border: 1px solid var(--brass-pill); border-radius: var(--r-sm); padding: 4px 9px; }
.proj-name { font-family: var(--font-display); font-weight: 700; font-size: 26px; line-height: 1.1;
  letter-spacing: -0.01em; color: var(--text-1); }
.proj-name .muted { color: var(--text-3); font-weight: 400; font-size: 18px; }
.proj-meta { display: flex; align-items: center; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
.proj-stage { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-mono);
  font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-2); }

.detail-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 18px; align-items: start; }
@media (max-width: 900px) { .detail-grid { grid-template-columns: minmax(0, 1fr); } }
/* minmax(0,…) keeps a panel with wide content (forms with min-width fields) from blowing the grid
   out past the viewport — it shrinks to the column and its content wraps/scrolls instead. */
.panel { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-card); padding: 18px; }
.panel-title { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-3); margin-bottom: 14px; }
.panel + .panel { margin-top: 18px; }
.payload-block { font-family: var(--font-mono); font-size: 11.5px; line-height: 1.55; color: var(--text-1);
  background: var(--surface-lo); border: 1px solid var(--border-lo); border-radius: var(--r-md);
  padding: 12px 14px; margin: 0; max-height: 460px; overflow: auto; white-space: pre-wrap; word-break: break-word; }

.job-list { display: flex; flex-direction: column; gap: 10px; }
.job-item { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 14px; background: var(--surface-lo); border: 1px solid var(--border-lo);
  border-left: 4px solid var(--c, var(--s-sold)); border-radius: var(--r-md); }
.job-item--c-lead { --c: var(--s-lead); } .job-item--c-qualified { --c: var(--s-qualified); }
.job-item--c-quoting { --c: var(--s-quoting); } .job-item--c-sold { --c: var(--s-sold); }
.job-item--c-completed { --c: var(--s-completed); } .job-item--c-closed { --c: var(--s-closed); }
/* Phone width: the engagement/job row wraps its right-side cluster (value · badges · stage pill)
   below the identity instead of overflowing the row. */
@media (max-width: 560px) { .job-item { flex-wrap: wrap; } }
/* A long unbreakable token in inline <code> (e.g. the data-deletion page) wraps instead of overflowing. */
code { overflow-wrap: anywhere; }
.job-trade { font-family: var(--font-display); font-weight: 600; font-size: 16px; color: var(--text-1); }
.job-status { font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-2); }
.job-empty { font-size: 12.5px; color: var(--text-3); }

.meta-row { display: flex; align-items: center; justify-content: space-between; padding: 9px 0;
  border-bottom: 1px solid var(--border-lo); font-size: 12.5px; }
.meta-row:last-child { border-bottom: none; }
.meta-row .k { color: var(--text-3); font-family: var(--font-mono); font-size: 10.5px;
  letter-spacing: 0.08em; text-transform: uppercase; }
.meta-row .v { color: var(--text-1); font-weight: 500; }

.backlink { display: inline-flex; align-items: center; gap: 6px; font-size: 12px;
  color: var(--text-2); text-decoration: none; margin-bottom: 14px; }
.backlink:hover { color: var(--brass-lo); }
.backlink .ico { width: 15px; height: 15px; }

/* ════════════════════════════════════════════════════════════════════════
   DETAIL PAGE SYSTEM (redesign Phase 1) — the canonical components every
   detail/list view composes from. Replaces the bolted-on `.panel` + inline
   `style="margin/gap/flex"` rot. Two-column work + sticky aside, sectioned
   bodies with consistent rhythm, a lifecycle spine, quiet empty states.
   ════════════════════════════════════════════════════════════════════════ */

/* Two-column detail: primary work column + sticky facts/actions aside. */
.detail { display: grid; grid-template-columns: 1.7fr 1fr; gap: 20px; align-items: start; }
@media (max-width: 1000px) { .detail { grid-template-columns: 1fr; } }
.detail-main, .detail-aside { display: flex; flex-direction: column; gap: 22px; min-width: 0; }
.detail-aside { position: sticky; top: 82px; }
/* The right rail recedes — lighter cards than the main column, so the eye leads with the content and
   treats the rail as a quiet glance. The brass Next-step card keeps its emphasis. */
.detail-aside .section:not(.nextstep) { background: var(--surface-lo); border-color: var(--border-lo); }
@media (max-width: 1000px) { .detail-aside { position: static; } }

/* Section — the canonical surface with built-in vertical rhythm (no inline margins). */
.section { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-card); padding: 18px; }
.section.flush { padding: 0; overflow: hidden; }       /* for a section wrapping a full-bleed table */
.section-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.section-head .section-title { margin: 0; }
.section-head .actions { margin-left: auto; }
.section-title { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-3); margin: 0 0 14px; }
.section-title .count { color: var(--text-2); }
.section-note { font-size: 12px; color: var(--text-2); line-height: 1.5; margin: 0 0 14px; }

/* Empty state — a quiet one-liner, never a tall dead box. */
.empty { font-size: 12.5px; color: var(--text-3); padding: 6px 0; }
.empty.center { text-align: center; padding: 16px 0; }

/* Key/value facts grid (generalizes .meta-row). */
.kv { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; padding: 8px 0;
  border-bottom: 1px solid var(--border-lo); font-size: 12.5px; }
.kv:last-child { border-bottom: none; }
.kv > .k { color: var(--text-3); font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.07em;
  text-transform: uppercase; flex: none; }
.kv > .v { color: var(--text-1); font-weight: 500; text-align: right; }
.kv > .v.strong { font-family: var(--font-display); font-size: 15px; font-weight: 700; }

/* Action group — replaces every inline display:flex;gap;flex-wrap on button rows. */
.actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.actions.end { justify-content: flex-end; }
.actions.stack { flex-direction: column; align-items: stretch; }
.actions form { margin: 0; display: inline-flex; }
.actions.stack form, .actions.stack form .btn, .actions.stack > .btn { width: 100%; justify-content: center; }

/* Inline write-form: label/input/button on one baseline (gate, booking, money forms).
   Children size to content by default; add `.grow` to the free-text field that should expand. */
.inline-form { display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; margin: 0; }
.inline-form .field { margin: 0; }
.inline-form .input, .inline-form select.input { width: auto; flex: 0 1 auto; min-width: 0;
  padding: 8px 10px; font-size: 12.5px; }
.inline-form .input.grow { flex: 1 1 11rem; }
/* A field WRAPPER that should expand (its label sits above a grow input — e.g. the takeover composer). */
.inline-form .field.grow { flex: 1 1 16rem; }

/* Money / number treatment — mono, tabular, right-aligned wherever figures appear. */
.num, .money { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.money.pos { color: var(--success); } .money.neg { color: var(--danger); }

/* Toolbar + spacing utilities — replace inline margin/flex nudges in view bodies. */
.toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 18px; }
.subhead { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-3); margin: 16px 0 8px; }
.subhead:first-child { margin-top: 0; }
/* Payment-history disclosure — the summary IS a subhead with a caret, keeping the cleared-events
   table (the secondary view) one click away under the primary payment ladder. */
.pay-history > summary { cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: 6px; width: fit-content; }
.pay-history > summary::-webkit-details-marker { display: none; }
.pay-history > summary::after { content: "▾"; font-size: 9px; opacity: 0.55; }
.pay-history[open] > summary { margin-bottom: 6px; }
.pay-history[open] > summary::after { content: "▴"; }
.pay-history > summary:hover { color: var(--text-2); }
/* Drop the native number spinner on the inline refund field so it reads as a clean amount input. */
.pay-history input[type="number"].input { appearance: textfield; -moz-appearance: textfield; }
.pay-history input[type="number"].input::-webkit-outer-spin-button,
.pay-history input[type="number"].input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
/* Danger disclosure — a destructive section (cancel / rescind) folded shut so it doesn't sit open
   under the daily controls. The whole header is the click target; the body holds the full form. */
details.danger-disc { padding: 0; }
.danger-disc__summary { cursor: pointer; list-style: none; display: flex; align-items: center;
  gap: 10px; padding: 16px 18px; }
.danger-disc__summary::-webkit-details-marker { display: none; }
.danger-disc__summary::after { content: "▾"; font-size: 10px; color: var(--text-3); margin-left: 4px; }
.danger-disc[open] .danger-disc__summary { border-bottom: 1px solid var(--border); }
.danger-disc[open] .danger-disc__summary::after { content: "▴"; }
.danger-disc__summary .section-title { margin: 0; }
.danger-disc__summary:hover .section-title { color: var(--danger); }
.danger-disc__hint { font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.02em;
  color: var(--text-3); margin-left: auto; }
.danger-disc__body { padding: 16px 18px; }
.mt-xl { margin-top: 26px; } .mt-lg { margin-top: 18px; } .mb-lg { margin-bottom: 18px; }
.mt-md { margin-top: 12px; } .mb-md { margin-bottom: 12px; }
.w-xs { max-width: 5rem; } .w-sm { max-width: 7rem; } .w-md { max-width: 11rem; } .w-lg { max-width: 15rem; }
.field.row { flex-direction: row; gap: 16px; flex-wrap: wrap; align-items: center; }
.svg-defs { position: absolute; width: 0; height: 0; }

/* Lifecycle stepper — the status spine that makes a detail page read like a CRM. */
.lifecycle { display: flex; align-items: flex-start; padding: 4px 4px 2px; }
.life-step { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 7px;
  position: relative; text-align: center; }
.life-step::before { content: ""; position: absolute; top: 5px; right: 50%; width: 100%; height: 2px;
  background: var(--border); z-index: 0; }
.life-step:first-child::before { display: none; }
.life-step.done::before, .life-step.now::before { background: var(--s-qualified); }
/* Blueprint: stage markers are surveyor's diamonds, not dots. */
.life-dot { width: 10px; height: 10px; border-radius: 1px; transform: rotate(45deg);
  background: var(--surface); border: 2px solid var(--border); z-index: 1; }
.life-step.done .life-dot { background: var(--s-qualified); border-color: var(--s-qualified); }
.life-step.now .life-dot { background: var(--brass); border-color: var(--brass); box-shadow: 0 0 0 4px var(--brass-soft); }
.life-step.dead .life-dot { background: var(--danger); border-color: var(--danger); }
.life-step.dead::before { background: var(--danger); opacity: 0.4; }
.life-label { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--text-3); }
.life-step.done .life-label { color: var(--text-2); }
.life-step.now .life-label { color: var(--text-1); font-weight: 600; }
.life-step.dead .life-label { color: var(--danger); font-weight: 600; }

/* Compact checklist (gates/inspections/811 in the aside) — status + label + inline action. */
.check-row { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--border-lo); }
.check-row:last-child { border-bottom: none; }
.check-ico { width: 18px; height: 18px; border-radius: 50%; flex: none; display: grid; place-items: center;
  font-family: var(--font-mono); font-size: 11px; background: var(--surface-hi); color: var(--text-3); border: 1px solid var(--border); }
.check-row.ok .check-ico { background: rgba(22,163,74,0.10); color: var(--success); border-color: rgba(22,163,74,0.3); }
.check-row.wait .check-ico { background: rgba(245,158,11,0.10); color: #a16207; border-color: rgba(245,158,11,0.3); }
.check-body { flex: 1; min-width: 0; }
.check-title { font-size: 12.5px; color: var(--text-1); font-weight: 500; }
.check-sub { font-size: 11px; color: var(--text-3); font-family: var(--font-mono); }

/* ── Form controls (shared: auth now, office write-surfaces later) ──────── */
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 15px; }
.field-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-3); }
.input {
  width: 100%; padding: 10px 12px; font-family: var(--font-ui); font-size: 13.5px;
  color: var(--text-1); background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-sm); transition: border-color .12s, box-shadow .12s;
}
.input::placeholder { color: var(--text-3); }
.input:focus { outline: none; border-color: var(--brass);
  box-shadow: 0 0 0 3px var(--brass-soft); }
/* Visible keyboard focus for buttons + disclosure summaries (WCAG 2.4.7) — inputs already had it; the
   action buttons (.btn, .todo-act) and the Block/Reopen <summary> disclosures did not. */
.btn:focus-visible, .todo-act:focus-visible, summary:focus-visible {
  outline: 2px solid var(--brass); outline-offset: 2px; border-radius: 2px; }
/* The locked owner-gated setting VALUE is read-mostly info — readable body text, not the 9px kind-chip. */
.set-edit--locked .set-locked-val { font-family: var(--font-mono); font-size: 13px; color: var(--text-1); }
.input.is-invalid { border-color: var(--danger); }
.input.code { font-family: var(--font-mono); font-size: 12px; line-height: 1.55; }
/* Two-column form body (cancel/edit forms) — collapses on narrow widths. */
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
@media (max-width: 640px) { .form-grid { grid-template-columns: 1fr; } }
.checkrow { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-2); }
.checkrow input { accent-color: var(--brass); width: 15px; height: 15px; }

/* ── Flash / alert ─────────────────────────────────────────────────────── */
.flash { display: flex; align-items: center; gap: 9px; padding: 10px 13px; margin-bottom: 16px;
  border: 1px solid; border-radius: var(--r-sm); font-size: 12.5px; line-height: 1.4; }
.flash .ico { width: 15px; height: 15px; flex: none; }
.flash-notice  { color: #15603a; background: rgba(22,163,74,0.08);  border-color: rgba(22,163,74,0.35); }
.flash-alert   { color: #a3231f; background: rgba(220,38,38,0.07);  border-color: rgba(220,38,38,0.34); }

/* ── Auth screens (login / password reset / unlock / confirm) ──────────── */
body.auth { margin: 0; min-height: 100vh; display: grid; place-items: center; padding: 32px 20px;
  background: radial-gradient(120% 90% at 50% -10%, #f7f2e9 0%, var(--bg) 60%);
  color: var(--text-1); font-family: var(--font-ui); -webkit-font-smoothing: antialiased; }
.auth-card { width: 100%; max-width: 392px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-lift); padding: 30px 30px 26px; }
.auth-brand { display: flex; flex-direction: column; align-items: center; gap: 11px;
  text-align: center; padding-bottom: 18px; margin-bottom: 20px;
  border-bottom: 1px solid var(--border-lo); }
.auth-brand .office-logo-tile { width: 46px; height: 46px; }
.auth-brand .office-logo-tile .ico { width: 25px; height: 25px; }
.auth-wordmark b { font-family: var(--font-display); font-weight: 700; font-size: 21px;
  letter-spacing: -0.01em; color: var(--text-1); line-height: 1; }
.auth-wordmark small { display: block; margin-top: 4px; font-family: var(--font-mono);
  font-size: 8.5px; letter-spacing: 0.18em; color: var(--text-3); }
.auth-title { font-family: var(--font-display); font-weight: 700; font-size: 19px;
  color: var(--text-1); margin: 0 0 3px; }
.auth-sub { font-size: 12.5px; color: var(--text-2); margin: 0 0 20px; }
.auth-card .btn.prim { width: 100%; justify-content: center; padding: 10px 14px; font-size: 13px; margin-top: 4px; }
.auth-links { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border-lo);
  display: flex; flex-direction: column; gap: 8px; text-align: center; }
.auth-links a { font-size: 12px; color: var(--text-2); text-decoration: none; }
.auth-links a:hover { color: var(--brass-lo); }
.auth-errors { margin: 0 0 16px; padding: 11px 13px; list-style: none;
  background: rgba(220,38,38,0.06); border: 1px solid rgba(220,38,38,0.30);
  border-radius: var(--r-sm); color: #a3231f; font-size: 12.5px; }
.auth-errors li { margin-left: 2px; }

/* ── To-do queue (wf-tasks A · triage inbox) ───────────────────────────── */
.todo-layout { display: grid; grid-template-columns: 188px 1fr; gap: 22px; align-items: start; }
.todo-rail { display: flex; flex-direction: column; gap: 2px; position: sticky; top: 18px; }
.todo-rail .eyebrow { margin: 2px 0 6px; }
.todo-filt { display: flex; align-items: center; gap: 7px; padding: 7px 11px; border-radius: var(--r-sm);
  font-size: 12.5px; color: var(--text-2); text-decoration: none; cursor: pointer; }
.todo-filt:hover { background: var(--surface-hi); color: var(--text-1); }
.todo-filt.on { background: var(--brass-pill); color: var(--brass-lo); font-weight: 600; }
.todo-count { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-3);
  background: var(--surface-hi); border-radius: var(--r-pill); padding: 1px 7px; }
.todo-filt.on .todo-count { background: rgba(216,84,42,0.20); color: var(--brass-lo); }

.todo-list { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.todo-bucket { display: flex; flex-direction: column; gap: 7px; }
.todo-buckethead { display: flex; align-items: center; gap: 8px; padding: 0 2px 2px; }
.todo-buckethead b { font-size: 12px; color: var(--text-1); font-weight: 600; }
.todo-buckethead .todo-count { margin-left: 2px; }

.todo-task { display: flex; align-items: center; gap: 12px; padding: 11px 14px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
  box-shadow: var(--shadow-card); }
.todo-task.high { border-left: 3px solid var(--danger); }
/* Urgent (C-6 IME mapping) — heavier than high: full danger edge + tinted row (audit G12). */
.todo-task.urgent { border-left: 4px solid var(--danger); background: rgba(194,54,43,0.05); }
.todo-checkform { display: flex; flex: none; }
.todo-check { width: 18px; height: 18px; border: 1.5px solid var(--border); border-radius: 5px; flex: none;
  display: grid; place-items: center; padding: 0; background: none; color: transparent; }
.todo-check .ico { width: 12px; height: 12px; }
button.todo-check { cursor: pointer; transition: border-color .12s, color .12s, background .12s; }
button.todo-check:hover { border-color: var(--brass); color: var(--brass); background: var(--surface-hi); }
.todo-check.blocked { border-style: dashed; opacity: .55; }
.todo-body { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.todo-title { font-size: 13px; font-weight: 500; color: var(--text-1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.todo-meta { display: flex; align-items: center; gap: 8px; font-size: 11.5px; }
.todo-meta .muted { color: var(--text-3); }
.todo-typetag { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.02em;
  color: var(--text-2); background: var(--surface-hi); border-radius: var(--r-sm); padding: 1px 6px; }
.todo-src { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.04em; text-transform: uppercase;
  padding: 2px 7px; border-radius: var(--r-pill); border: 1px solid var(--border); color: var(--text-3); flex: none; }
.todo-src.auto { color: var(--brass-lo); border-color: var(--brass); background: var(--brass-soft); }
.todo-due { font-family: var(--font-mono); font-size: 11px; color: var(--text-2); flex: none; min-width: 52px; text-align: right; }
.todo-due.today { color: var(--brass-lo); font-weight: 600; }
.todo-due.over { color: var(--danger); font-weight: 600; }
.todo-avatar { display: grid; place-items: center; width: 28px; height: 28px; flex: none;
  border-radius: 50%; font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  background: var(--surface-hi); color: var(--text-2); border: 1px solid var(--border); }
.todo-avatar.owner { background: var(--brass-pill); color: var(--brass-lo); border-color: var(--brass); }
.todo-caught { display: flex; align-items: center; gap: 9px; padding: 26px; justify-content: center;
  color: var(--text-3); font-size: 13px; }
.todo-caught .ico { width: 17px; height: 17px; color: var(--brass); }

@media (max-width: 640px) {
  .todo-layout {
    grid-template-columns: minmax(0, 1fr);
    gap: 14px;
  }

  .todo-rail {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 6px;
  }

  .todo-rail .eyebrow {
    flex: 0 0 100%;
    margin-bottom: 2px;
  }

  .todo-filt {
    flex: 1 1 7rem;
    justify-content: center;
    min-width: 0;
  }

  .todo-task {
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 8px 10px;
    padding: 12px;
  }

  .todo-checkform,
  .todo-check.blocked {
    order: 1;
    margin-top: 2px;
  }

  .todo-body {
    order: 2;
    flex: 1 1 calc(100% - 34px);
  }

  .todo-title {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: anywhere;
  }

  .todo-meta {
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 4px 6px;
  }

  .todo-src {
    order: 3;
    margin-left: 28px;
  }

  .todo-due,
  .todo-avatar {
    order: 3;
  }

  .todo-due {
    min-width: 0;
    text-align: left;
  }

  .todo-acts {
    order: 4;
    flex: 1 0 calc(100% - 28px);
    flex-wrap: wrap;
    margin-left: 28px;
  }
}

/* ── Data table (reusable list surface — Customers, later Jobs/Subs/…) ──── */
.data-table { width: 100%; border-collapse: separate; border-spacing: 0;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-card); overflow: hidden; }
.data-table thead th { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-3); text-align: left; font-weight: 500;
  padding: 11px 16px; background: var(--surface-lo); border-bottom: 1px solid var(--border); }
.data-table th.num, .data-table td.num { text-align: right; }
.data-table tbody td { padding: 12px 16px; font-size: 13px; color: var(--text-2);
  border-bottom: 1px solid var(--border-lo); vertical-align: middle; }
.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover { background: var(--surface-hi); }
.cust-name { font-size: 13.5px; font-weight: 600; color: var(--text-1); text-decoration: none; }
.cust-name:hover { color: var(--brass-lo); }
.cust-sub { font-size: 11.5px; color: var(--text-3); margin-left: 6px; }
.cust-contact { font-family: var(--font-mono); font-size: 12px; color: var(--text-2); }
/* Small/narrow screens: a wide table scrolls inside its own box instead of forcing the WHOLE page to
   scroll sideways (which shifts the layout). display:block makes the table a scroll container while the
   inner rows keep their natural width; reverts to a normal full-width table above the breakpoint. */
@media (max-width: 1000px) {
  .data-table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/* .job-item is rendered as a link on the customer detail (a div on the project detail) */
a.job-item { text-decoration: none; color: inherit; }
a.job-item:hover { background: var(--surface-hi); }

/* Settings sub-navigation — config panes nested under Settings (wf-admin). */
/* The tab strip scrolls horizontally on narrow screens instead of overflowing the page. */
.set-tabs { display: flex; gap: 6px; margin: 0 0 18px; border-bottom: 1px solid var(--border-lo); overflow-x: auto; }
.set-tab { font-size: 12.5px; text-decoration: none; color: var(--text-2); padding: 8px 14px;
  border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; flex: none; }
.set-tab:hover { color: var(--brass-lo); }
.set-tab.on { color: var(--text-1); font-weight: 600; border-bottom-color: var(--brass); }
.set-desc { font-size: 12.5px; color: var(--text-2); line-height: 1.55; max-width: 760px; margin: 0 0 18px; }
.tpl-head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.tpl-head .panel-title { margin: 0; }

/* Project sub-navigation — nested sections drilled into from the job detail. */
.proj-tabs { display: flex; gap: 6px; margin: 16px 0 2px; }
.proj-tab { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; text-decoration: none;
  color: var(--text-2); border: 1px solid var(--border); border-radius: var(--r-md); padding: 6px 12px;
  background: var(--surface); }
.proj-tab:hover { border-color: var(--brass); color: var(--brass-lo); }
.proj-tab .ico { width: 15px; height: 15px; }

/* ── Notifications inbox (wf-server3) + shared queue rows ─────────────── */
.notif-row { display: flex; align-items: flex-start; gap: 11px; padding: 13px 4px;
  border-bottom: 1px solid var(--border-lo); }
.notif-row:last-child { border-bottom: none; }
.notif-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--border); margin-top: 5px; flex: none; }
.notif-row.unread .notif-dot { background: var(--brass); }
.notif-body { flex: 1; min-width: 0; }
.notif-title { font-size: 13.5px; color: var(--text-1); }
.notif-row.unread .notif-title { font-weight: 600; }
.notif-meta { font-size: 11.5px; color: var(--text-3); margin-top: 2px; }
.notif-meta a { color: var(--text-2); font-family: var(--font-mono); text-decoration: none; }
.notif-meta a:hover { color: var(--brass); }
.notif-time { font-size: 11px; color: var(--text-3); font-family: var(--font-mono); white-space: nowrap; }

@media (max-width: 640px) {
  .doc-layout {
    grid-template-columns: minmax(0, 1fr);
  }

  .doc-rail {
    gap: 10px;
  }

  .panel {
    padding: 14px;
  }

  .notif-row {
    display: grid;
    grid-template-columns: 10px minmax(0, 1fr);
    gap: 5px 9px;
    padding: 12px 2px;
  }

  .notif-dot {
    margin-top: 6px;
  }

  .notif-title,
  .notif-meta {
    overflow-wrap: anywhere;
  }

  .notif-time,
  .notif-row .todo-actform {
    grid-column: 2;
  }

  .notif-time {
    white-space: normal;
  }

  .notif-row .todo-act {
    width: auto;
  }
}

/* Project dossier — Activity + Note interleaved timeline */
.tl-row { display: flex; gap: 11px; padding: 11px 2px; border-bottom: 1px solid var(--border-lo); }
.tl-row:last-child { border-bottom: none; }
.tl-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--border); margin-top: 5px; flex: none;
  box-shadow: 0 0 0 3px var(--surface); }
.tl-dot.in { background: var(--brass); }
.tl-dot.warn { background: var(--warning); }
.tl-body { flex: 1; min-width: 0; }
.tl-kind { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-3); }
.tl-text { font-size: 13px; color: var(--text-1); margin-top: 2px; }
.tl-when { font-size: 11px; color: var(--text-3); font-family: var(--font-mono); margin-top: 3px; }

/* Activity composer — one box with a type switcher (Communication / Note / To-do); only the chosen
   type's fields show. Pure CSS: the visually-hidden radios drive both the active tab and which panel
   is visible (no JS). Mono-caps tabs + brass active state echo the timeline labels below. */
.composer { margin-bottom: 18px; }
.composer-radio { position: absolute; width: 1px; height: 1px; margin: -1px; opacity: 0; pointer-events: none; }
.composer-tabs { display: inline-flex; border: 1px solid var(--border); border-radius: var(--r-md);
  overflow: hidden; margin-bottom: 13px; }
.composer-tab { font: 600 11px/1 var(--font-ui); letter-spacing: 0.05em; text-transform: uppercase;
  padding: 9px 16px; cursor: pointer; user-select: none; color: var(--text-3);
  background: var(--surface-lo); border-right: 1px solid var(--border); transition: background .12s, color .12s; }
.composer-tab:last-child { border-right: none; }
.composer-tab:hover { color: var(--text-1); background: var(--surface-hi); }
#ctab-log:checked ~ .composer-tabs .composer-tab[for="ctab-log"],
#ctab-note:checked ~ .composer-tabs .composer-tab[for="ctab-note"],
#ctab-task:checked ~ .composer-tabs .composer-tab[for="ctab-task"] { background: var(--brass); color: #fff; }
#ctab-log:focus-visible ~ .composer-tabs .composer-tab[for="ctab-log"],
#ctab-note:focus-visible ~ .composer-tabs .composer-tab[for="ctab-note"],
#ctab-task:focus-visible ~ .composer-tabs .composer-tab[for="ctab-task"] { outline: 2px solid var(--brass-lo); outline-offset: 2px; }
.composer-form { display: none; align-items: flex-end; gap: 8px; flex-wrap: wrap; }
.composer-form .input.grow { flex: 1 1 13rem; }
#ctab-log:checked ~ .composer-panels .cf-log,
#ctab-note:checked ~ .composer-panels .cf-note,
#ctab-task:checked ~ .composer-panels .cf-task { display: flex; }
.composer-hint { flex-basis: 100%; margin: 3px 0 0; font-size: 11px; color: var(--text-3); }

/* KPI tiles (Accounting / Integrations) */
.kpi-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 14px; margin-bottom: 20px; }
.kpi-tile { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 14px 16px; box-shadow: var(--shadow-card); }
.kpi-tile .k { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-3); }
.kpi-tile .v { font-family: var(--font-display); font-size: 20px; font-weight: 700; margin-top: 4px; }
.kpi-tile .v.sm { font-size: 16px; }
.kpi-tile .v.neg { color: var(--danger); }
/* Horizontal bar (pipeline funnel, supplier perf) — fill width is data-driven (inline %). */
.bar-row { display: flex; align-items: center; gap: 10px; margin: 7px 0; }
.bar-label { width: 78px; font-size: 12px; color: var(--text-2); }
.bar-track { flex: 1; height: 18px; background: var(--surface-hi); border-radius: 5px; overflow: hidden; }
.bar-fill { display: block; height: 100%; border-radius: 5px; background: linear-gradient(90deg, var(--brass-hi), var(--brass-lo)); }
.bar-count { width: 34px; text-align: right; font-family: var(--font-mono); font-size: 12px; }
.kpi-tile .n { font-size: 11px; color: var(--text-3); margin-top: 2px; }
/* Flagged KPI note — draws the eye to a lapsing/expired condition (e.g. crew compliance expiry). */
.kpi-tile .n.kpi-flag { color: var(--warning); font-weight: 600; }
.health-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: 6px; }
.health-dot.ok { background: var(--success); } .health-dot.wait { background: var(--warning); } .health-dot.bad { background: var(--danger); }

/* ── Documents hub (wf-server2 DocumentsHub) ──────────────────────────── */
.doc-layout { display: grid; grid-template-columns: 1fr 330px; gap: 16px; align-items: start; }
@media (max-width: 900px) { .doc-layout { grid-template-columns: 1fr; } }
.doc-group { margin-bottom: 16px; }
.doc-group:last-child { margin-bottom: 0; }
.doc-group .eyebrow { margin-bottom: 6px; display: block; }
.doc-row { display: flex; align-items: center; gap: 10px; padding: 11px 4px;
  border-bottom: 1px solid var(--border-lo); }
.doc-row:last-child { border-bottom: none; }
.doc-row > .ico { width: 16px; height: 16px; color: var(--text-3); flex: none; }
.doc-name { flex: 1; font-size: 13px; color: var(--text-1); }
.sku-tag { font-family: var(--font-mono); font-size: 10px; color: var(--text-3);
  background: var(--surface-hi); border: 1px solid var(--border-lo); border-radius: var(--r-sm);
  padding: 1px 6px; margin-left: 6px; }
.doc-row .badge { text-transform: uppercase; font-family: var(--font-mono); font-size: 10px; flex: none; }
.doc-rail { display: flex; flex-direction: column; gap: 14px; }
.sign-steps { margin-top: 10px; display: flex; flex-direction: column; gap: 9px; }
.sign-step { display: flex; align-items: center; gap: 9px; font-size: 12.5px; color: var(--text-3); }
.sign-step.done { color: var(--text-1); }
.sign-step.now { color: var(--brass-lo); font-weight: 600; }
.sign-dot { width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; flex: none;
  font-family: var(--font-mono); font-size: 11px; border: 1px solid var(--border);
  background: var(--surface-hi); color: var(--text-3); }
.sign-dot .ico { width: 12px; height: 12px; }
.sign-step.done .sign-dot { background: var(--success); border-color: var(--success); color: #fff; }
.sign-step.now .sign-dot { background: var(--brass); border-color: var(--brass); color: #fff; }
.sign-box { margin-top: 12px; border: 1px dashed var(--border); border-radius: var(--r-md);
  text-align: center; padding: 14px; font-family: var(--font-display); font-size: 16px; color: var(--text-3); }
.doc-pills { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.doc-note { font-size: 11.5px; color: var(--text-3); line-height: 1.5; margin: 12px 0 0; }
.doc-note code { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-2); }

/* ── Interactive action controls (To-do queue · lead assignment · inline write actions) ───── */
.todo-acts { display: inline-flex; gap: 6px; align-items: center; margin-left: 8px; }
.todo-actform { display: inline; margin: 0; }
.todo-act { font: 500 11px/1 var(--font-ui); padding: 6px 11px; border-radius: var(--r-sm);
  border: 1px solid var(--border); background: var(--surface); color: var(--text-2); cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s; }
.todo-act:hover { border-color: var(--brass); color: var(--brass-lo); background: var(--brass-soft); }
.todo-act.prim { background: linear-gradient(150deg, var(--brass-hi), var(--brass)); border-color: var(--brass-lo);
  color: #fff; }
.todo-act.prim:hover { filter: brightness(1.05); color: #fff; }
.lead-assign { display: inline-flex; gap: 7px; align-items: center; margin: 0; }
.lead-assign-select { font-size: 12px; padding: 6px 8px; border-radius: var(--r-sm);
  border: 1px solid var(--border); background: var(--surface); color: var(--text-1); }
.lead-assign-select:focus { outline: none; border-color: var(--brass); box-shadow: 0 0 0 3px var(--brass-soft); }

/* ═══════════════════════════════════════════════════════════════════════════
   Design system v2 — confirm modal · toast · form controls · record system
   (UI foundation). New namespaces (.confirm-* / .toast-* / .page-header /
   .record-row / .rr-* / .avatar) plus element-scoped resets for native
   widgets. Nothing here redefines a pre-existing office.css class.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Branded confirm modal (replaces window.confirm globally) ───────────── */
.confirm-backdrop {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(18, 34, 58, 0.55); /* dim navy (--nav-bg) */
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  opacity: 0; transition: opacity .16s ease;
}
.confirm-backdrop.is-open { opacity: 1; }

.confirm-card {
  width: 100%; max-width: 460px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-lift);
  padding: 24px 24px 20px;
  transform: translateY(8px) scale(.98); transition: transform .18s ease;
}
.confirm-backdrop.is-open .confirm-card { transform: translateY(0) scale(1); }

.confirm-title {
  margin: 0 0 8px; font-family: var(--font-display); font-weight: 700;
  font-size: 21px; line-height: 1.15; letter-spacing: -0.01em; color: var(--text-1);
}
.confirm-body {
  margin: 0; font-family: var(--font-ui); font-size: 13.5px; line-height: 1.5;
  color: var(--text-2);
}
.confirm-actions {
  display: flex; justify-content: flex-end; gap: 10px; margin-top: 22px;
}
/* Danger variant: reuse .btn.prim geometry, recolor to --danger (no class redefine) */
.confirm-ok--danger {
  background: var(--danger); border-color: #b91c1c; color: #fff;
}
.confirm-ok--danger:hover { filter: brightness(1.05); background: var(--danger); }

@media (max-width: 480px) {
  .confirm-card { max-width: 100%; }
  .confirm-actions { flex-direction: column-reverse; }
  .confirm-actions .btn { width: 100%; justify-content: center; }
}
@media (prefers-reduced-motion: reduce) {
  .confirm-backdrop, .confirm-card { transition: none; }
}

/* ── Toasts (transient action feedback — additive to the static .flash banner) ──
   Driven by toast_controller.js: a single top-right stack of parchment cards with a
   brass (notice) / danger (alert) left accent, an icon, the message, a dismiss button,
   a subtle slide-in, and ~4s auto-dismiss with a fade-out. */
.toast-stack { position: fixed; top: 16px; right: 16px; z-index: 60;
  display: flex; flex-direction: column; gap: 10px; width: 340px; max-width: calc(100vw - 32px);
  pointer-events: none; }
.toast { pointer-events: auto; display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 12px 12px 14px; background: var(--surface); color: var(--text-1);
  border: 1px solid var(--border); border-left: 3px solid var(--brass);
  border-radius: var(--r-md); box-shadow: var(--shadow-lift); cursor: pointer;
  font-size: 12.5px; line-height: 1.45;
  opacity: 0; transform: translateX(16px); transition: opacity .24s ease, transform .24s ease; }
.toast.in { opacity: 1; transform: translateX(0); }
.toast.out { opacity: 0; transform: translateX(16px); }
.toast.notice { border-left-color: var(--brass); }
.toast.alert { border-left-color: var(--danger); }
.toast .toast-ico { width: 16px; height: 16px; flex: none; margin-top: 1px; }
.toast.notice .toast-ico { color: var(--brass-lo); }
.toast.alert .toast-ico { color: var(--danger); }
.toast .toast-msg { flex: 1; min-width: 0; word-break: break-word; }
.toast .toast-x { flex: none; display: grid; place-items: center; width: 22px; height: 22px;
  margin: -3px -3px -3px 0; padding: 0; background: transparent; border: none; border-radius: var(--r-sm);
  color: var(--text-3); cursor: pointer; transition: background .12s, color .12s; }
.toast .toast-x:hover { background: var(--surface-hi); color: var(--text-1); }
.toast .toast-x .ico { width: 13px; height: 13px; }
@media (prefers-reduced-motion: reduce) {
  .toast { transition: opacity .12s ease; transform: none; }
  .toast.in, .toast.out { transform: none; }
}

/* ── Native form controls (select / date / time / number / check / radio) ──
   Globally dress OS-native widgets so they match .input. Pure CSS, no HTML
   changes: every `select.input` and date/time/number input inherits the
   .input box (border/radius/focus ring) from the existing rule above; these
   rules only add appearance resets, the custom brass chevron, height parity,
   and picker-indicator tinting. Do not duplicate the text-input .input rule. */

/* Custom chevron + appearance reset for <select>. The chevron is an inline
   SVG data-uri stroked in --brass-lo (#b23f1c safety-orange), 12px, right-anchored
   (brightening to --brass on hover). Extra right padding keeps it clear of the text. */
select.input {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 34px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none' stroke='%23b23f1c' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px 12px;
}
/* Brighten the chevron on hover/focus so the control feels live. */
select.input:hover, select.input:focus {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none' stroke='%23d8542a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E");
}
/* Remove the dotted focus outline Firefox paints inside selects. */
select.input:-moz-focusring { color: transparent; text-shadow: 0 0 0 var(--text-1); }
/* Tidy the option list where the platform honors it (Blink/Win, Firefox). */
select.input option { color: var(--text-1); background: var(--surface); }
select.input option:checked { background: var(--brass-soft); }
/* Multi-select: list box, not a single line — drop the chevron, allow height. */
select.input[multiple] {
  background-image: none; padding-right: 12px; height: auto; cursor: default;
}
select.input[multiple] option { padding: 4px 6px; border-radius: var(--r-sm); }
/* Disabled selects read as inert: muted text, no pointer, parchment fill. */
select.input:disabled, select.input[disabled] {
  cursor: not-allowed; color: var(--text-3);
  background-color: var(--surface-hi); opacity: 1;
}

/* Date / time / number inputs already pick up the .input box; these rules
   only normalize platform chrome (height parity, picker + spin buttons). */
input[type="date"].input,
input[type="datetime-local"].input,
input[type="time"].input,
input[type="month"].input,
input[type="week"].input,
input[type="number"].input {
  appearance: none; -webkit-appearance: none;
  font-family: var(--font-ui); font-variant-numeric: tabular-nums;
}
/* WebKit/Blink renders date & time fields with internal flex parts; reset so
   they sit on the same baseline / height as text .input. */
input[type="date"].input::-webkit-datetime-edit,
input[type="datetime-local"].input::-webkit-datetime-edit,
input[type="time"].input::-webkit-datetime-edit { padding: 0; color: var(--text-1); }
input[type="date"].input::-webkit-datetime-edit-fields-wrapper,
input[type="datetime-local"].input::-webkit-datetime-edit-fields-wrapper,
input[type="time"].input::-webkit-datetime-edit-fields-wrapper { padding: 0; }
input.input::-webkit-datetime-edit-text { color: var(--text-3); padding: 0 1px; }
input.input::-webkit-datetime-edit-month-field:focus,
input.input::-webkit-datetime-edit-day-field:focus,
input.input::-webkit-datetime-edit-year-field:focus,
input.input::-webkit-datetime-edit-hour-field:focus,
input.input::-webkit-datetime-edit-minute-field:focus,
input.input::-webkit-datetime-edit-ampm-field:focus {
  background: var(--brass-soft); color: var(--brass-lo); outline: none; border-radius: 3px;
}
/* The little calendar/clock glyph — tint it muted brass instead of OS blue. */
input.input::-webkit-calendar-picker-indicator {
  cursor: pointer; opacity: 0.6;
  filter: invert(58%) sepia(35%) saturate(620%) hue-rotate(2deg) brightness(92%) contrast(86%);
}
input.input::-webkit-calendar-picker-indicator:hover { opacity: 1; }
/* Number spinners — keep them, just slim/tint via the muted-brass treatment. */
input[type="number"].input::-webkit-inner-spin-button,
input[type="number"].input::-webkit-outer-spin-button {
  opacity: 0.55; height: 1.6em; cursor: pointer;
  filter: invert(58%) sepia(35%) saturate(620%) hue-rotate(2deg) brightness(92%) contrast(86%);
}
input[type="number"].input::-webkit-inner-spin-button:hover { opacity: 1; }
/* Firefox: hide the spin arrows for a cleaner mono figure field. */
input[type="number"].input { -moz-appearance: textfield; }

/* Brass-tinted checkbox / radio app-wide (the .checkrow rule already does this
   for that one component; this covers every other inline check/radio so they
   match without per-field classes). Native box, just recolored + focus ring. */
input[type="checkbox"], input[type="radio"] { accent-color: var(--brass); }
input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible {
  outline: none; box-shadow: 0 0 0 3px var(--brass-soft); border-radius: 3px;
}

/* ── Shared layout partials (office/shared/_page_header · _record_row · _avatar) ── */

/* In-body page / section header — lighter than the topbar title; complements it. */
.page-header { display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin: 0 0 18px; }
.page-header-text { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.page-header-text .eyebrow { margin-bottom: 1px; }
.page-header-title { font-family: var(--font-display); font-weight: 700; font-size: 19px;
  line-height: 1.15; letter-spacing: -0.01em; color: var(--text-1); margin: 0; }
.page-header-sub { font-size: 12.5px; color: var(--text-2); }
.page-header-actions { margin-left: auto; }

/* Canonical clickable record row (extends .data-table). Whole row → href via the
   record-row Stimulus controller; brass hover frame signals the click-through. */
.record-row { cursor: pointer; transition: box-shadow .12s; }
.record-row td { box-shadow: inset 0 0 0 0 var(--brass); }
.record-row:hover { background: var(--surface-hi); }
.record-row:hover td:first-child { box-shadow: inset 2px 0 0 0 var(--brass); }
.record-row:focus-within { background: var(--surface-hi); }
.rr-sub { font-size: 11.5px; color: var(--text-3); margin-top: 2px; }
.rr-badges { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.record-row .proj-stage { color: var(--text-2); }
.record-row td.rr-owner { width: 1%; white-space: nowrap; text-align: right; }

/* Initials avatar — generalizes the topbar .office-avatar (navy) + To-do owner (brass). */
.avatar { display: inline-grid; place-items: center; border-radius: 50%; flex: none;
  font-family: var(--font-mono); font-weight: 600; color: #fff;
  background: linear-gradient(150deg, #2a4a6e, #16304f); }
.avatar-sm { width: 24px; height: 24px; font-size: 9.5px; }
.avatar-md { width: 30px; height: 30px; font-size: 11px; }
.avatar.owner { background: var(--brass-pill); color: var(--brass-lo);
  border: 1px solid var(--brass); }

/* ═══════════════════════════════════════════════════════════════════════════
   Design system v2 — rebuilds: pipeline ledger · customer dossier · settings
   toggles · schedule board. Four rebuild agents authored matching views and
   returned these blocks; integrated verbatim here under fresh namespaces
   (.ledger*/.lr-* · .cust-* · .set-*/.as-switch* · .js-*). Verified zero
   collision with any pre-existing office.css selector.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Pipeline ledger (office/pipeline/index) ──────────────────────────────
   The dense, stage-grouped deal ledger that replaces the kanban board. Ports
   v2's `.job-card-lg` 6-col grid ("4px stripe · customer/job · channel · stage
   · trades · value · owner") into the v3 idiom: stripe color comes from the
   existing `.s-*` palette classes, badges reuse channel_badge / stage_pill,
   owner reuses .avatar. New namespaces only (.ledger* / .lr-*). */
.ledger-toolbar { margin-bottom: 18px; }

.ledger { display: flex; flex-direction: column; gap: 22px; }

/* Stage group: colored dot · name · count chip · Σ pipeline value (whole $). */
.ledger-group { display: flex; flex-direction: column; gap: 8px; }
.ledger-grouphead { display: flex; align-items: center; gap: 9px; padding: 0 2px 2px; }
.ledger-grouphead b { font-size: 13px; font-weight: 600; color: var(--text-1); }
.ledger-count { font-family: var(--font-mono); font-size: 11px; color: var(--text-2);
  background: var(--surface-hi); border: 1px solid var(--border-lo); border-radius: var(--r-pill);
  padding: 1px 8px; }
.ledger-sum { margin-left: auto; font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 12px; font-weight: 500; color: var(--text-2); }

/* The rows + a column-header rule so figures line up across the group. */
.ledger-rows { display: flex; flex-direction: column; gap: 7px; }

.ledger-row { display: grid; align-items: center; gap: 14px;
  grid-template-columns: 4px minmax(0, 2fr) auto minmax(0, 1fr) minmax(0, 1.2fr) auto 30px;
  padding: 11px 16px; background: var(--surface); border: 1px solid var(--border-lo);
  border-radius: var(--r-md); box-shadow: var(--shadow-card); text-decoration: none; color: inherit;
  transition: border-color .12s, box-shadow .12s; }
.ledger-row:hover { border-color: var(--brass); box-shadow: var(--shadow-lift); }

.lr-stripe { width: 4px; height: 34px; border-radius: 3px; background: var(--s-lead); }
.lr-stripe.s-lead { background: var(--s-lead); } .lr-stripe.s-qualified { background: var(--s-qualified); }
.lr-stripe.s-quoting { background: var(--s-quoting); } .lr-stripe.s-sold { background: var(--s-sold); }
.lr-stripe.s-completed { background: var(--s-completed); } .lr-stripe.s-closed { background: var(--s-closed); }

.lr-cust { min-width: 0; }
.lr-name { font-size: 13.5px; font-weight: 600; color: var(--text-1);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lr-sub { font-size: 11.5px; color: var(--text-3); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lr-code { font-family: var(--font-mono); font-size: 10.5px; color: var(--brass-lo); letter-spacing: 0.02em; }

.lr-chan { display: flex; align-items: center; }
.lr-stage { display: flex; align-items: center; }

.lr-trades { font-size: 12px; color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.lr-value { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 13px;
  font-weight: 600; color: var(--text-1); text-align: right; white-space: nowrap; }
.lr-value.quote { color: var(--text-3); font-weight: 500; } /* forecast (quote out), not realized */

.lr-owner { display: flex; align-items: center; justify-content: flex-end; }
.lr-noowner { font-family: var(--font-mono); font-size: 12px; color: var(--text-3); }

.ledger-empty { font-size: 11.5px; color: var(--text-3); padding: 12px 16px;
  border: 1px dashed var(--border); border-radius: var(--r-md); }

/* Narrow widths: drop the trades + channel columns, let the row breathe. */
@media (max-width: 860px) {
  .ledger-row { grid-template-columns: 4px minmax(0, 1fr) auto auto 30px; gap: 10px; }
  .lr-chan, .lr-trades { display: none; }
}
@media (max-width: 560px) {
  .ledger-row { grid-template-columns: 4px minmax(0, 1fr) auto; }
  .lr-stage, .lr-owner { display: none; }
}

/* ── Customer dossier (office/customers/show) ──────────────────────────────
   The "locus of history" header: avatar + Saira name + contact-glance meta,
   sitting above the standard .detail two-column shell. New structure only —
   the body composes from .detail / .section / .kv / .job-item / .empty. */
.cust-head { display: flex; align-items: center; gap: 14px; margin-bottom: 22px; }
.cust-head .avatar { width: 46px; height: 46px; font-size: 16px; }
.cust-head-text { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.cust-head-text .proj-name { margin: 0; }
.cust-head-text .proj-meta { margin-top: 0; }

/* Mono engagement code in the .job-item row (the P-#### deep-link label). */
.cust-eng-id { font-family: var(--font-mono); font-size: 12px; font-weight: 500;
  color: var(--brass-lo); flex: none; }
/* Follow-up cue on an open-funnel engagement row — the quote/lead awaiting the next touch. */
.eng-followup { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--brass-lo); background: var(--brass-soft);
  border: 1px solid var(--brass-pill); border-radius: var(--r-sm); padding: 2px 7px; flex: none; }

/* ── Settings registry (Office::Settings#index) ────────────────────────────── */
.set-stack { display: flex; flex-direction: column; gap: 26px; }
.set-empty { font-size: 12.5px; color: var(--text-3); text-align: center; padding: 28px 0;
  background: var(--surface); border: 1px solid var(--border-lo); border-radius: var(--r-lg); }

.set-group__head { display: flex; align-items: baseline; gap: 10px; padding: 0 2px 9px;
  border-bottom: 1px solid var(--border-lo); margin-bottom: 14px; }
.set-group__title { font-family: var(--font-display); font-size: 16px; font-weight: 700;
  letter-spacing: -0.01em; color: var(--text-1); margin: 0; }
.set-group__count { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-3);
  background: var(--surface-hi); border: 1px solid var(--border-lo); border-radius: var(--r-pill);
  padding: 1px 8px; }

.set-list { display: flex; flex-direction: column; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--shadow-card); }
.set-row { display: flex; align-items: center; gap: 20px; padding: 13px 18px;
  border-top: 1px solid var(--border-lo); }
.set-row:first-child { border-top: 0; }
.set-row:hover { background: var(--surface-lo); }

.set-row__body { flex: 1; min-width: 0; }
.set-row__label { font-size: 13.5px; font-weight: 600; color: var(--text-1); line-height: 1.3;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.set-row__key { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-3);
  margin-top: 3px; letter-spacing: 0.01em; }
.set-row__desc { font-size: 12px; color: var(--text-2); margin-top: 4px; line-height: 1.4; }
.set-row__desc--quiet { color: var(--text-3); font-style: italic; }

.set-chip { font-family: var(--font-mono); font-size: 9px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; padding: 2px 7px; border-radius: var(--r-pill);
  color: var(--brass-lo); background: var(--brass-soft); border: 1px solid var(--brass-pill); }

.set-row__editor { flex-shrink: 0; display: flex; justify-content: flex-end; }

.set-edit { display: flex; align-items: center; gap: 8px; margin: 0; }
.set-edit__num { width: 110px; text-align: right; font-family: var(--font-mono); }
.set-edit__num::-webkit-outer-spin-button,
.set-edit__num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.set-edit__num { -moz-appearance: textfield; }
.set-edit__kv { display: inline-flex; align-items: center; gap: 6px; }
.set-edit__kvlabel { font-size: 11px; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.04em; }

/* Document-template editor: merge-field chips + the sample-data preview iframe */
.merge-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.merge-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 11px;
  background: var(--surface-hi); border: 1px solid var(--border-lo); border-radius: 5px; padding: 2px 7px; }
.merge-chip__type { color: var(--text-3); }
.tpl-preview { width: 100%; height: 560px; border: 1px solid var(--border); border-radius: var(--r-sm); background: #fff; }

/* Payment-term step builder (structured replacement for the raw-JSON steps field) */
.step-row { display: flex; gap: 10px; align-items: flex-end; margin-bottom: 12px; }
.step-row .field { margin-bottom: 0; }
.step-row .field.grow { flex: 1; }
.step-row .btn { margin-bottom: 6px; }
.step-foot { display: flex; align-items: center; gap: 14px; margin-top: 4px; }

/* Settings: category jump-nav + brand-logo preview */
.set-jump { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 20px; }
.set-jump a { text-decoration: none; }
.set-group { scroll-margin-top: 80px; }
.set-logo-preview { max-height: 40px; max-width: 180px; border-radius: 6px; background: var(--surface-hi); padding: 4px; }
.set-edit__text { width: 240px; }
.set-edit__unit { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-3);
  white-space: nowrap; min-width: 64px; }

.set-edit--json { flex-direction: column; align-items: stretch; gap: 6px; width: 320px; }
.set-edit__row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.set-edit__type { font-family: var(--font-mono); font-size: 9px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--text-3); background: var(--surface-hi);
  border: 1px solid var(--border-lo); border-radius: 4px; padding: 2px 6px; }
.set-edit__json { width: 100%; resize: vertical; line-height: 1.5; }

/* toggle switch (boolean value_type) — submits on change via the per-setting PATCH form */
.as-switch { display: inline-flex; align-items: center; gap: 9px; margin: 0; }
.as-switch__track { position: relative; display: inline-block; width: 42px; height: 23px; flex-shrink: 0;
  cursor: pointer; }
.as-switch__input { position: absolute; opacity: 0; width: 0; height: 0; }
.as-switch__slider { position: absolute; inset: 0; background: var(--border); border-radius: 999px;
  transition: background .18s ease; }
.as-switch__slider::before { content: ""; position: absolute; top: 3px; left: 3px; width: 17px; height: 17px;
  background: #fff; border-radius: 50%; box-shadow: 0 1px 2px rgba(0,0,0,.18); transition: transform .18s ease; }
.as-switch__input:checked + .as-switch__slider { background: var(--brass); }
.as-switch__input:checked + .as-switch__slider::before { transform: translateX(19px); }
.as-switch__input:focus-visible + .as-switch__slider { outline: 2px solid var(--brass); outline-offset: 2px; }
.as-switch__state { font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
  color: var(--text-3); min-width: 22px; }
.as-switch--on .as-switch__state { color: var(--brass-lo); }

@media (max-width: 720px) {
  .set-row { flex-direction: column; align-items: stretch; gap: 12px; }
  .set-row__editor { justify-content: flex-start; }
  .set-edit__text, .set-edit--json { width: 100%; }
}

/* ── Job schedule — crew × time dispatch board (resource Gantt). One swimlane per crew across a
   two-week window; each milestone Installation is a bar spanning its scheduled days, packed into the
   fewest non-overlapping rows. The header row and every lane share ONE column template
   (gutter + N equal day tracks) so the day grid stays aligned head-to-body. Namespaced .gantt-*. */
.gantt {
  --gantt-gutter: 168px;
  --gantt-bar-h: 42px;
  display: flex; flex-direction: column;
  min-height: min(740px, calc(100vh - 214px)); /* fill the screen; cap so a huge monitor doesn't over-stretch */
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface); overflow: hidden;
}
.gantt-row {
  display: grid;
  grid-template-columns: var(--gantt-gutter) repeat(var(--gantt-days), minmax(0, 1fr));
}

.gantt-head { background: var(--surface-lo); border-bottom: 1px solid var(--border); }
.gantt-gutter {
  grid-row: 1 / -1; min-width: 0;
  display: flex; align-items: center; gap: 7px;
  padding: 8px 12px; border-right: 1px solid var(--border);
}
.gantt-gutter--head {
  font-family: var(--font-mono); font-size: 10px; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--text-3);
}
.gantt-crew-dot { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.gantt-crew-name {
  flex: 1; min-width: 0; font-size: 12.5px; font-weight: 600; color: var(--text-1);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gantt-crew-load {
  flex: none; font-family: var(--font-mono); font-size: 10px; color: var(--text-3);
  background: var(--surface-hi); border-radius: 999px; padding: 1px 7px;
}

.gantt-dhead {
  display: flex; flex-direction: column; align-items: center;
  padding: 7px 2px 8px; text-align: center; border-right: 1px solid var(--border-lo);
}
.gantt-dhead:last-child { border-right: none; }
.gantt-dhead.is-weekend { background: var(--surface-hi); }
.gantt-dhead.is-today { background: var(--brass-soft); }
.gantt-dow {
  font-family: var(--font-mono); font-size: 9px; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--text-3);
}
.gantt-dhead.is-today .gantt-dow { color: var(--brass); }
.gantt-dnum { font-family: var(--font-display); font-size: 16px; font-weight: 600; color: var(--text-1); line-height: 1.1; }
.gantt-dhead.is-today .gantt-dnum { color: var(--brass); }
.gantt-dmon { font-family: var(--font-mono); font-size: 8px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-3); }

.gantt-lane {
  /* explicit bar rows + a trailing 1fr filler so the lane (and its gutter) can grow to fill height —
     the empty band below a crew's bars reads as that crew's open capacity. */
  grid-template-rows: repeat(var(--lane-rows), var(--gantt-bar-h)) 1fr;
  flex: 1 1 auto; row-gap: 7px; padding: 10px 0; min-height: 64px;
  border-bottom: 1px solid var(--border-lo);
}
.gantt-lane:last-child { border-bottom: none; }
.gantt-lane .gantt-gutter { align-items: flex-start; padding-top: 12px; }

.gantt-bar {
  min-width: 0; overflow: hidden; z-index: 1;
  display: flex; flex-direction: column; justify-content: center; gap: 1px;
  margin: 0 3px; padding: 3px 9px; border-radius: var(--r-sm);
  text-decoration: none; cursor: pointer;
  border-left: 3px solid var(--bar-c, var(--s-qualified));
  background: color-mix(in srgb, var(--bar-c, var(--s-qualified)) 12%, var(--surface));
  transition: filter 0.12s, transform 0.12s, box-shadow 0.12s;
}
.gantt-bar.is-scheduled { --bar-c: #2f5fa0; }
.gantt-bar.is-active { --bar-c: var(--brass); }
.gantt-bar:hover { transform: translateY(-1px); box-shadow: var(--shadow-lift, 0 4px 14px rgba(0,0,0,0.12)); filter: brightness(1.03); z-index: 3; }
.gantt-bar.is-clipped-l { border-top-left-radius: 0; border-bottom-left-radius: 0; border-left-style: dashed; margin-left: 0; }
.gantt-bar.is-clipped-r { border-top-right-radius: 0; border-bottom-right-radius: 0; margin-right: 0; }
.gantt-bar-title {
  font-size: 11.5px; font-weight: 600; color: var(--text-1); line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gantt-bar-sub {
  font-family: var(--font-mono); font-size: 9px; color: var(--text-2); line-height: 1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.gantt-empty { padding: 28px; text-align: center; color: var(--text-3); }

.gantt-legend { display: flex; align-items: center; gap: 18px; margin-top: 11px; flex-wrap: wrap; }
.gantt-key { display: inline-flex; align-items: center; gap: 7px; font-size: 11.5px; color: var(--text-2); }
.gantt-swatch { width: 22px; height: 11px; border-radius: 3px; border-left: 3px solid var(--bar-c); background: color-mix(in srgb, var(--bar-c) 14%, var(--surface)); }
.gantt-swatch.is-scheduled { --bar-c: #2f5fa0; }
.gantt-swatch.is-active { --bar-c: var(--brass); }

@media (max-width: 1000px) {
  .gantt { overflow-x: auto; }
  .gantt-row { min-width: 880px; }
}

/* ── Sales visits — Google-style week calendar. Seven day columns + an hour axis; each Appointment is
   a block positioned by start time (top) and sized by duration (height), overlaps split side-by-side.
   Header + body share ONE column template (time gutter + 7 equal day tracks) so the day grid aligns.
   Namespaced .cal-*. */
.cal {
  --cal-gutter: 64px;
  /* Hour rows grow to fill the viewport (taller on a big monitor), floored so they never get cramped
     and capped so they don't get absurd. Events are positioned in % so they scale with the row height. */
  --cal-hour-h: clamp(52px, calc((100vh - 284px) / var(--cal-hours)), 116px);
  --cal-cols: 7;
  --cal-colmin: 0px;
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface); overflow: hidden;
}
/* Day-per-rep board: columns get a floor width and the board scrolls sideways when the bench is big. */
.cal--day { overflow: hidden; overflow-x: auto; --cal-colmin: 132px; }
.cal-head, .cal-body {
  display: grid; grid-template-columns: var(--cal-gutter) repeat(var(--cal-cols), minmax(var(--cal-colmin), 1fr));
}
.cal--day .cal-head, .cal--day .cal-body { min-width: min-content; }

.cal-seg { display: inline-flex; gap: 4px; margin-right: 4px; }
.cal-repfilter { display: inline-flex; }
.cal-repfilter .input { height: 30px; padding: 0 26px 0 10px; font-size: 12.5px; }

/* Day board — rep column header */
.cal-chead {
  display: flex; align-items: center; gap: 7px;
  padding: 7px 10px; border-right: 1px solid var(--border-lo); min-width: 0;
}
.cal-chead:last-child { border-right: none; }
.cal-rep-avatar {
  flex: none; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center; color: #fff;
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.02em;
}
.cal-rep-name {
  flex: 1; min-width: 0; font-size: 12px; font-weight: 600; color: var(--text-1);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cal-rep-load { flex: none; font-family: var(--font-mono); font-size: 9px; color: var(--text-3); }
.cal-rep-load.is-open { color: var(--success); }
.cal-head { border-bottom: 1px solid var(--border); background: var(--surface-lo); }
.cal-corner { border-right: 1px solid var(--border); }
.cal-dhead {
  display: flex; flex-direction: column; align-items: center;
  padding: 7px 2px 8px; border-right: 1px solid var(--border-lo);
}
.cal-dhead:last-child { border-right: none; }
.cal-dhead.is-today { background: var(--brass-soft); }
.cal-dow { font-family: var(--font-mono); font-size: 9.5px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-3); }
.cal-dhead.is-today .cal-dow { color: var(--brass); }
.cal-dnum { font-family: var(--font-display); font-size: 18px; font-weight: 600; color: var(--text-1); line-height: 1.1; }
.cal-dhead.is-today .cal-dnum { color: var(--brass); }

.cal-gutter { border-right: 1px solid var(--border); }
.cal-hourlabel { height: var(--cal-hour-h); position: relative; }
.cal-hourlabel span {
  position: absolute; top: -6px; right: 7px;
  font-family: var(--font-mono); font-size: 9px; color: var(--text-3); white-space: nowrap;
}
.cal-hourlabel:first-child span { top: 4px; }

.cal-day {
  position: relative; height: calc(var(--cal-hours) * var(--cal-hour-h));
  border-right: 1px solid var(--border-lo);
  background-image: repeating-linear-gradient(to bottom,
    transparent 0, transparent calc(var(--cal-hour-h) - 1px),
    var(--border-lo) calc(var(--cal-hour-h) - 1px), var(--border-lo) var(--cal-hour-h));
}
.cal-day:last-child { border-right: none; }
.cal-day.is-today { background-color: color-mix(in srgb, var(--brass-soft) 50%, transparent); }

.cal-now { position: absolute; left: 0; right: 0; border-top: 2px solid var(--danger); z-index: 12; pointer-events: none; }
.cal-now::before { content: ""; position: absolute; left: -3px; top: -4px; width: 7px; height: 7px; border-radius: 50%; background: var(--danger); }

.cal-event {
  position: absolute; overflow: hidden; min-height: 16px;
  display: flex; flex-direction: column; gap: 0;
  padding: 2px 6px; border-radius: 5px; z-index: 2;
  border: 1px solid color-mix(in srgb, var(--ev-c, #2f5fa0) 38%, var(--surface));
  border-left: 3px solid var(--ev-c, #2f5fa0);
  background: color-mix(in srgb, var(--ev-c, #2f5fa0) 15%, var(--surface));
  text-decoration: none; cursor: pointer;
  transition: filter 0.12s, box-shadow 0.12s, min-width 0.12s;
}
/* Overlapping visits split side-by-side (both stay visible); hovering a squeezed one expands it to a
   readable width and lifts it above its neighbour. */
.cal-event:hover {
  min-width: 168px; z-index: 30 !important; /* beat the inline cascade z so a hovered visit lifts fully forward */
  box-shadow: var(--shadow-lift, 0 6px 18px rgba(0,0,0,0.2));
  filter: brightness(1.03);
}
.cal-event.is-scheduled { --ev-c: #2f5fa0; }
.cal-event.is-run { --ev-c: var(--brass); }
.cal-event.is-sold { --ev-c: var(--success); }
.cal-event.is-lost { --ev-c: var(--danger); }
.cal-event.is-followup { --ev-c: var(--warning); }
.cal-event.is-cancelled { --ev-c: var(--text-3); }
.cal-event-time { font-family: var(--font-mono); font-size: 9px; font-weight: 600; color: var(--text-2); line-height: 1.3; }
.cal-event-title { font-size: 11px; font-weight: 600; color: var(--text-1); line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-event-sub { font-size: 9px; color: var(--text-2); line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.cal-legend { display: flex; align-items: center; gap: 16px; margin-top: 11px; flex-wrap: wrap; }
.cal-key { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--text-2); }
.cal-dot { width: 11px; height: 11px; border-radius: 3px; border-left: 3px solid var(--ev-c); background: color-mix(in srgb, var(--ev-c) 16%, var(--surface)); }
.cal-dot.is-scheduled { --ev-c: #2f5fa0; }
.cal-dot.is-run { --ev-c: var(--brass); }
.cal-dot.is-sold { --ev-c: var(--success); }
.cal-dot.is-followup { --ev-c: var(--warning); }
.cal-dot.is-lost { --ev-c: var(--danger); }

@media (max-width: 1000px) {
  .cal { overflow-x: auto; }
  .cal-head, .cal-body { min-width: 820px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Motion — the design system + v2 both mandate a subtle, fast life-on-load.
   List/card children stagger-rise on first paint; interactive cards/rows lift
   to a brass frame on hover with no layout shift. Everything is wrapped in
   `prefers-reduced-motion: no-preference` and hard-reset under `reduce`.
   ═══════════════════════════════════════════════════════════════════════════ */
@keyframes risein { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: no-preference) {
  /* Stagger-rise list/card children on load — subtle (8px) and fast (.3s). */
  .data-table tbody tr,
  .record-row,
  .pipeline-cards > *,
  .job-list > *,
  .ledger-rows > *,
  .kpi-tile,
  .kpi,
  .section {
    animation: risein .3s ease both;
  }
  /* Stagger the first ~10 children so the rise reads as a cascade, not a jump. */
  .data-table tbody tr:nth-child(1), .pipeline-cards > *:nth-child(1),
  .job-list > *:nth-child(1), .ledger-rows > *:nth-child(1) { animation-delay: .00s; }
  .data-table tbody tr:nth-child(2), .pipeline-cards > *:nth-child(2),
  .job-list > *:nth-child(2), .ledger-rows > *:nth-child(2) { animation-delay: .02s; }
  .data-table tbody tr:nth-child(3), .pipeline-cards > *:nth-child(3),
  .job-list > *:nth-child(3), .ledger-rows > *:nth-child(3) { animation-delay: .04s; }
  .data-table tbody tr:nth-child(4), .pipeline-cards > *:nth-child(4),
  .job-list > *:nth-child(4), .ledger-rows > *:nth-child(4) { animation-delay: .06s; }
  .data-table tbody tr:nth-child(5), .pipeline-cards > *:nth-child(5),
  .job-list > *:nth-child(5), .ledger-rows > *:nth-child(5) { animation-delay: .08s; }
  .data-table tbody tr:nth-child(6), .pipeline-cards > *:nth-child(6),
  .job-list > *:nth-child(6), .ledger-rows > *:nth-child(6) { animation-delay: .10s; }
  .data-table tbody tr:nth-child(7), .pipeline-cards > *:nth-child(7),
  .job-list > *:nth-child(7), .ledger-rows > *:nth-child(7) { animation-delay: .12s; }
  .data-table tbody tr:nth-child(8), .pipeline-cards > *:nth-child(8),
  .job-list > *:nth-child(8), .ledger-rows > *:nth-child(8) { animation-delay: .14s; }
  .data-table tbody tr:nth-child(9), .pipeline-cards > *:nth-child(9),
  .job-list > *:nth-child(9), .ledger-rows > *:nth-child(9) { animation-delay: .16s; }
  .data-table tbody tr:nth-child(n+10), .pipeline-cards > *:nth-child(n+10),
  .job-list > *:nth-child(n+10), .ledger-rows > *:nth-child(n+10) { animation-delay: .18s; }
  /* Stagger the KPI strip + section stack a touch as well. */
  .kpi-tile:nth-child(2), .kpi:nth-child(2) { animation-delay: .03s; }
  .kpi-tile:nth-child(3), .kpi:nth-child(3) { animation-delay: .06s; }
  .kpi-tile:nth-child(4), .kpi:nth-child(4) { animation-delay: .09s; }
  .kpi-tile:nth-child(5), .kpi:nth-child(5) { animation-delay: .12s; }
}

/* Hover polish — brass frame + lift on interactive surfaces. Table rows recolor
   only (no translate → no layout shift); free cards may lift 1px. The .12s
   transition is declared unconditionally so it applies even with reduced motion
   (a recolor, not a movement). */
.record-row { transition: background .12s, box-shadow .12s, border-color .12s; }
.panel, .kpi, .kpi-tile, .job-item, .ledger-row, .js-bar {
  transition: border-color .12s, box-shadow .12s, transform .12s;
}
.panel:hover, .kpi:hover, .kpi-tile:hover, .ledger-row:hover {
  border-color: var(--brass); box-shadow: var(--shadow-lift);
}
a.job-item:hover { border-color: var(--brass); box-shadow: var(--shadow-lift); }

@media (prefers-reduced-motion: reduce) {
  .data-table tbody tr, .record-row, .pipeline-cards > *, .job-list > *,
  .ledger-rows > *, .kpi-tile, .kpi, .section {
    animation: none !important;
  }
  .js-bar:hover, .project-card:hover { transform: none; }
}

/* ── Dashboard (dense overview) ──────────────────────────────────────────── */
.dash-hero { margin-bottom: 16px; grid-template-columns: repeat(6, 1fr); }
@media (max-width: 1100px) { .dash-hero { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 560px)  { .dash-hero { grid-template-columns: repeat(2, 1fr); } }

/* Pre-sale → punch funnel strip */
.funnel { display: flex; align-items: stretch; background: var(--surface); border: 1px solid var(--border-lo);
  border-radius: var(--r-lg); box-shadow: var(--shadow-card); padding: 6px 6px; margin-bottom: 20px; overflow-x: auto; }
.funnel-cell { flex: 1 1 0; min-width: 76px; display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 12px 6px; text-decoration: none; border-radius: var(--r-md); transition: background .12s ease; }
.funnel-cell:hover { background: var(--surface-hi); }
.funnel-n { font-family: var(--font-display); font-weight: 700; font-size: 22px; color: var(--text-1); line-height: 1; }
.funnel-cell.zero .funnel-n { color: var(--text-3); }
.funnel-k { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.09em; text-transform: uppercase; color: var(--text-3); }
.funnel-sep { align-self: center; color: var(--border); font-size: 15px; flex: none; }
/* Narrow screens: the 8-stage funnel scrolls horizontally instead of clipping its last stages off-screen. */
@media (max-width: 760px) { .funnel { overflow-x: auto; } }

/* Queues + rail */
.dash-grid { display: grid; grid-template-columns: 1.15fr 1fr; gap: 18px; align-items: start; }
@media (max-width: 980px) { .dash-grid { grid-template-columns: 1fr; } }
/* min-width:0 — grid/flex items default to min-width:auto and refuse to shrink below their content's
   intrinsic width. The Leaflet jobs map (an absolutely-positioned canvas) then locks the column at a width
   wider than its 1fr share, blowing the whole dashboard past the viewport. Letting the columns shrink to
   their track keeps the map (overflow:hidden) clipped to its column. */
.dash-col { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.dash-col .panel + .panel { margin-top: 0; }

.panel-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 6px; gap: 12px; }
.panel-head .panel-title { margin: 0; }
.panel-link { font-size: 11px; color: var(--text-3); text-decoration: none; font-weight: 500; white-space: nowrap; }
.panel-link:hover { color: var(--brass-lo); }

.q-row { display: flex; align-items: center; gap: 11px; padding: 10px 2px; text-decoration: none;
  border-bottom: 1px solid var(--border-lo); }
.q-row:last-of-type { border-bottom: none; }
.q-row:hover .q-ttl { color: var(--brass-lo); }
.q-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.q-dot.visit { background: var(--brass); }
.q-dot.install { background: var(--success); }
.q-dot.wait { background: var(--warning); }
.q-dot.block { background: var(--danger); }
.q-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.q-ttl { font-size: 13px; font-weight: 500; color: var(--text-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.q-meta { font-size: 11.5px; color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.q-side { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-3); flex: none; white-space: nowrap; }
.q-side.over { color: var(--danger); }
.q-more { font-size: 11px; color: var(--text-3); padding: 8px 2px 2px; }

/* Jobs map */
.map-legend { display: flex; gap: 12px; }
.lg { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--text-3); display: inline-flex; align-items: center; gap: 5px; }
.lg::before { content: ""; width: 8px; height: 8px; border-radius: 50%; }
.lg.visit::before { background: var(--brass); }
.lg.install::before { background: var(--success); }
.lg.blocked::before { background: var(--danger); }
.dash-map { height: 300px; border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--border-lo);
  background: var(--surface-hi); display: grid; place-items: center; }
.dash-map.is-live { display: block; }
.dash-map.is-live .map-empty { display: none; }
.map-empty { margin: 0; }
.leaflet-container { font-family: var(--font-ui); background: var(--surface-hi); }
.leaflet-container a { color: var(--brass-lo); }

/* Today schedule */
.sched-row { display: flex; align-items: center; gap: 10px; padding: 9px 2px; text-decoration: none;
  border-bottom: 1px solid var(--border-lo); }
.sched-row:last-of-type { border-bottom: none; }
.sched-row:hover .sched-who { color: var(--brass-lo); }
.sched-time { font-family: var(--font-mono); font-size: 11px; color: var(--text-2); width: 62px; flex: none; }
.sched-who { font-size: 13px; font-weight: 500; color: var(--text-1); flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sched-what { font-size: 11.5px; color: var(--text-3); flex: none; }

/* ── Single-card sectioned form (intake / create) ────────────────────────── */
.form-narrow { max-width: 760px; }
.form-card { background: var(--surface); border: 1px solid var(--border-lo); border-radius: var(--r-lg);
  box-shadow: var(--shadow-card); overflow: hidden; margin-top: 4px; }
.fset { padding: 20px 24px; border-bottom: 1px solid var(--border-lo); }
.fset-h { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-3); margin-bottom: 16px; }
.fset .field:last-child, .fset .field-row:last-child .field { margin-bottom: 0; }
.field-opt { font-family: var(--font-ui); letter-spacing: 0; text-transform: none; font-size: 10px;
  color: var(--text-3); background: var(--surface-hi); border-radius: 3px; padding: 1px 5px; margin-left: 4px; }
.form-foot { display: flex; justify-content: flex-end; align-items: center; gap: 10px;
  padding: 15px 24px; background: var(--surface-lo); }

/* ── Lead intake queue (routing suggestion + referral) ───────────────────── */
.lead-suggest { margin-top: 5px; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.02em; color: var(--brass-lo); }
.lead-suggest strong { color: var(--text-1); font-weight: 600; }
.lead-suggest.none { color: var(--text-3); }
.lead-ref { margin-left: 7px; font-size: 9.5px; vertical-align: middle; }
.rr-dnc { margin-left: 8px; font-size: 9.5px; vertical-align: middle; }
.visit-rep { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--text-2); }
.js-nav { gap: 8px; margin-bottom: 14px; }
.js-week-label { font-family: var(--font-display); font-size: 15px; font-weight: 600; color: var(--text-1); margin-left: 6px; }

/* ── Address autocomplete (intake form) ──────────────────────────────────── */
.hidden { display: none !important; }
.field-row { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 12px; }
@media (max-width: 560px) { .field-row { grid-template-columns: 1fr; } }
.addr-toggle { margin-top: 5px; font-size: 11px; color: var(--text-3); }
.addr-toggle a { color: var(--brass); text-decoration: none; }
.addr-toggle a:hover { color: var(--brass-lo); text-decoration: underline; }
/* The Google Places web component sits where the street input was; match field rhythm. */
gmp-place-autocomplete { display: block; width: 100%; }

/* ───────────────────────────────────────────────────────────────────────────
   UI/UX audit 2026-06-08 — sweep additions (one block; classes consumed by the
   views edited in the same pass). Shared component layer, no inline styles.
   ─────────────────────────────────────────────────────────────────────────── */

/* [#63] Aside reorder: on a finished WorkOrder the Dispatch crew card yields the
   sticky prime slot to the compliance record (gates / 811 / inspections).
   .detail-aside is flex-column, so `order` pushes the tagged card to the bottom. */
.detail-aside .aside-order-last { order: 1; }

/* [#12] Notifications inbox rail: separate a second .eyebrow filter-group header
   (e.g. "Type") from the preceding .todo-filt group within one .doc-rail panel. */
.doc-rail .panel .eyebrow { display: block; }
.doc-rail .todo-filt + .eyebrow { margin-top: 12px; }

/* [#16] Settings — brand-colors structured editor. Mirrors .set-edit--json's column
   layout; reuses .set-edit__kv / .set-edit__kvlabel for the slot rows. */
.set-edit--colors { flex-direction: column; align-items: stretch; gap: 8px; width: 320px; }
.set-edit--colors .set-edit__kv { justify-content: space-between; }
.set-edit__color { width: 44px; height: 28px; padding: 2px; border: 1px solid var(--border-lo);
  border-radius: var(--r-sm); background: var(--surface-hi); cursor: pointer; }
.set-edit__color::-webkit-color-swatch-wrapper { padding: 0; }
.set-edit__color::-webkit-color-swatch { border: none; border-radius: 4px; }

/* [#22] Sidebar nav pending-triage count pill (trailing-edge badge on To-do /
   Notifications). Brass pill reads as an attention badge against the dark sidebar. */
.office-navitem-count { margin-left: auto; font-family: var(--font-mono); font-size: 10.5px;
  line-height: 1; color: var(--brass-hi); background: var(--brass-pill);
  border-radius: var(--r-pill); padding: 2px 7px; }
.office-navitem.active .office-navitem-count { color: #fff; background: rgba(255, 255, 255, 0.18); }

/* [#29 / #32] Page-level empty state — a real centered card for whole-page
   "nothing here yet" bodies. ONE container; two child-class sets are in use:
   change_orders/index uses .empty-state__ico/__head/__body; material_orders/new
   uses .empty-ic/.empty-h/.empty-p/.empty-acts. Both supported below. */
.empty-state { display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 12px; max-width: 460px; margin: 40px auto; padding: 40px 32px;
  background: var(--surface); border: 1px solid var(--border-lo); border-radius: var(--r-lg);
  box-shadow: var(--shadow-card); }
.empty-state__ico { width: 30px; height: 30px; stroke: var(--brass); fill: none; stroke-width: 1.75;
  stroke-linecap: round; stroke-linejoin: round; opacity: .9; }
.empty-state__head { font-family: var(--font-display); font-size: 18px; font-weight: 700;
  letter-spacing: -0.01em; color: var(--text-1); }
.empty-state__body { font-size: 13px; line-height: 1.55; color: var(--text-2); margin: 0; max-width: 38ch; }
.empty-state .btn { margin-top: 4px; }
.empty-ic { width: 48px; height: 48px; margin: 0 auto 4px; display: flex; align-items: center;
  justify-content: center; border-radius: var(--r-pill); background: var(--brass-soft); color: var(--brass-lo); }
.empty-ic .ico { width: 22px; height: 22px; }
.empty-h { font-family: var(--font-display); font-weight: 700; font-size: 16px; color: var(--text-1); }
.empty-p { font-size: 12.5px; line-height: 1.5; color: var(--text-2); }
.empty-acts { display: flex; gap: 8px; justify-content: center; margin-top: 6px; }

/* [#34] Customers index: dedicated tap-to-call Phone column. Mono + tabular numerals
   at a fixed nowrap x-position so the eye runs straight down the column when dialing. */
.data-table td.rr-phone { font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  white-space: nowrap; color: var(--text-2); }
.data-table td.rr-phone a { color: var(--text-2); text-decoration: none; }
.data-table td.rr-phone a:hover { color: var(--brass-lo); }

/* [#43] Crews roster empty-state action — separates the inline "New subcontractor"
   CTA from the empty-bench copy. Pairs with .col-empty. */
.col-empty-act { margin-top: 12px; }

/* [#55] Office user form: reveal the Salesperson-only fields (commission % + tax
   treatment) only when the Salesperson role is checked. Declarative :has() reveal —
   no Stimulus, no inline styles. */
.form-card-roles .fset-salesperson { display: none; }
.form-card-roles:has(input[name="user[roles][]"][value="salesperson"]:checked) .fset-salesperson { display: block; }

/* [#65] Sales-visits calendar: .cal-event blocks are absolutely positioned within
   .cal-day; the last block of the day (e.g. a 4 PM visit) bottoms out flush against
   the overflow:hidden container border and its subtitle gets sliced. Give the body
   a few px of bottom breathing room so the lowest visit card clears the grid border. */
.cal-body { padding-bottom: 8px; }

/* [#66] Widen the job-schedule Gantt crew gutter so seeded company names
   ("Old Dominion Decking", "Blue Ridge Decks", …) fit without truncating. Overrides
   the --gantt-gutter:168px set earlier in the .gantt block (later declaration wins). */
.gantt { --gantt-gutter: 205px; }

/* [#39] Sales-Visits board "Book a visit" disclosure — a compact inline booking row under the toolbar
   (project picker + datetime → Appointment). Mirrors the project-show reschedule <details> pattern. */
.cal-book { margin: 0 0 14px; }
.cal-book > summary { display: inline-flex; cursor: pointer; list-style: none; }
.cal-book > summary::-webkit-details-marker { display: none; }
.cal-book__form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; margin-top: 10px;
  padding: 14px; background: var(--surface); border: 1px solid var(--border-lo);
  border-radius: var(--r-lg); box-shadow: var(--shadow-card); }
.cal-book__field { display: flex; flex-direction: column; gap: 4px; font-size: 11px; font-weight: 600;
  letter-spacing: .02em; text-transform: uppercase; color: var(--text-3); }
.cal-book__field .input { min-width: 220px; font-size: 13px; text-transform: none; font-weight: 400;
  letter-spacing: 0; color: var(--text-1); }

/* Phase 0.8 suggested drive-time slots — radio list of feasible visit times inside the Book-a-visit panel. */
.cal-book__slots { flex-direction: column; align-items: stretch; }
.cal-book__slotset { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; border: 0; min-width: 280px; }
.cal-book__slotset > legend { padding: 0 0 4px; }
.cal-book__slot { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 400;
  text-transform: none; letter-spacing: 0; color: var(--text-1); cursor: pointer; }
.cal-book__empty { margin: 10px 0 0; font-size: 12px; color: var(--text-3); max-width: 420px; }

/* [#27] Documents hub upload disclosure — header "Upload document" reveals a compact type+file form.
   [#68] reused on the crew detail for compliance-doc upload. Same shape as .cal-book. */
.doc-upload, .crew-upload { display: inline-block; }
.doc-upload > summary, .crew-upload > summary { display: inline-flex; cursor: pointer; list-style: none; }
.doc-upload > summary::-webkit-details-marker, .crew-upload > summary::-webkit-details-marker { display: none; }
.doc-upload__form, .crew-upload__form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px;
  margin-top: 10px; padding: 14px; background: var(--surface); border: 1px solid var(--border-lo);
  border-radius: var(--r-lg); box-shadow: var(--shadow-card); }
.doc-upload__field, .crew-upload__field { display: flex; flex-direction: column; gap: 4px; font-size: 11px;
  font-weight: 600; letter-spacing: .02em; text-transform: uppercase; color: var(--text-3); }
.doc-upload__field .input, .crew-upload__field .input { min-width: 200px; font-size: 13px;
  text-transform: none; font-weight: 400; letter-spacing: 0; color: var(--text-1); }

/* [#68] Crew detail "Invite field user" disclosure — name+email → sub_user invite (Devise reset email). */
.crew-invite { display: inline-block; }
.crew-invite > summary { display: inline-flex; cursor: pointer; list-style: none; }
.crew-invite > summary::-webkit-details-marker { display: none; }
.crew-invite__form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; margin-top: 10px;
  padding: 14px; background: var(--surface); border: 1px solid var(--border-lo); border-radius: var(--r-lg);
  box-shadow: var(--shadow-card); }
.crew-invite__field { display: flex; flex-direction: column; gap: 4px; font-size: 11px; font-weight: 600;
  letter-spacing: .02em; text-transform: uppercase; color: var(--text-3); }
.crew-invite__field .input { min-width: 200px; font-size: 13px; text-transform: none; font-weight: 400;
  letter-spacing: 0; color: var(--text-1); }

/* [#68] Panel title with a trailing action (the compliance-doc Upload disclosure on the crew detail). */
.panel-title--withaction { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
/* Phone width: stack the upload/invite form fields full-width so a 200px-min field or a non-shrinking
   file input can't push the panel (and the page) wider than the viewport; let the title+action wrap. */
@media (max-width: 560px) {
  .crew-upload__field, .crew-invite__field, .doc-upload__field { width: 100%; }
  .crew-upload__field .input, .crew-invite__field .input, .doc-upload__field .input { min-width: 0; }
  .panel-title--withaction { flex-wrap: wrap; }
}

/* ── Project detail — frontend-design pass (2026-06-09): pro toolbar + sale section ───────── */

/* Quote line-item table footer — a clear total row, not text cramped against the rounded border. */
.data-table tfoot td { padding: 13px 16px; font-size: 13px; font-weight: 600; color: var(--text-1);
  background: var(--surface-lo); border-top: 2px solid var(--border); }
.data-table tfoot td.num { font-family: var(--font-display); font-size: 16px; font-weight: 700;
  letter-spacing: -0.01em; }
.sale-quote { margin-bottom: 0; }

/* Estimate + Sale-contract status as two compact cells — replaces the sparse label↔value rows that
   stranded a tiny value at the far right of a wide panel. */
.sale-states { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 14px; }
@media (max-width: 620px) { .sale-states { grid-template-columns: 1fr; } }
.sale-state { padding: 12px 14px; background: var(--surface-lo); border: 1px solid var(--border-lo);
  border-radius: var(--r-md); display: flex; flex-direction: column; gap: 7px; }
.sale-state__label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--text-3); }
.sale-state__val { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13px;
  color: var(--text-1); }
.sale-state__val .muted { font-size: 12.5px; }
.sale-state__val form { margin: 0; }
.sale-actions { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border-lo); }
.sale-actions .hint { color: var(--text-3); font-size: 12.5px; font-style: italic; }

/* Project action toolbar — a clean bar with the destructive action separated to the right. */
.proj-toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 18px; }

/* Toolbar dropdown-button: a btn summary reveals a small popover form (Add trade / Mark lost) so a bare
   <select> never floats in the bar reading as a mystery control. */
.tb-menu { position: relative; }
.tb-menu > summary { list-style: none; cursor: pointer; }
.tb-menu > summary::-webkit-details-marker { display: none; }
.tb-menu > summary::after { content: "▾"; margin-left: 6px; font-size: 10px; opacity: 0.6; }
.tb-menu--end { margin-left: auto; }
.tb-menu__pop { position: absolute; z-index: 30; top: calc(100% + 6px); left: 0; min-width: 230px;
  padding: 12px; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); box-shadow: var(--shadow-card); }
.tb-menu--end .tb-menu__pop { left: auto; right: 0; }
.tb-menu__pop form { display: flex; flex-direction: column; gap: 9px; margin: 0; }
.tb-menu__pop .input { width: 100%; }
.tb-menu__lbl { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--text-3); }
.tb-menu--danger > summary:hover { color: var(--danger); border-color: var(--danger); }

/* ══ Project detail v2 — hero, deal focal point, contact + next-step (frontend-design 2026-06-09) ══ */

/* Header: identity on the left, the ONE primary next-step action on the right. */
.proj-hero { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; margin: 4px 0 18px; }
.proj-hero__id { min-width: 0; }
.proj-hero .proj-code { display: inline-block; margin-bottom: 8px; }
.proj-hero .proj-name { font-family: var(--font-display); font-size: 30px; font-weight: 700;
  letter-spacing: -0.02em; line-height: 1.05; color: var(--text-1); margin: 0; }
.proj-hero .proj-name .muted { font-weight: 600; font-size: 22px; }
.proj-hero .proj-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-top: 10px;
  font-size: 12.5px; color: var(--text-2); }
.proj-hero .proj-stage { display: inline-flex; align-items: center; gap: 6px; }
.proj-hero__cta { flex-shrink: 0; }
.btn-lg { padding: 11px 22px; font-size: 14px; border-radius: var(--r-md); }

.proj-stepper { margin-bottom: 16px; }
/* Header right column: the secondary "manage this deal" tools stack just above the primary CTA,
   both right-aligned. The tools are quiet ghost buttons; Mark lost keeps its danger-on-hover cue
   (from .tb-menu--danger) and right-aligns its popover (.tb-menu--end) so it never runs off-screen. */
.proj-hero__actions { display: flex; flex-direction: column; align-items: flex-end; gap: 10px; flex-shrink: 0; }
.proj-hero__tools { display: flex; align-items: center; gap: 4px; }

/* Terminal-outcome banner (lost / cancelled) — flat, pencil-rule, left datum edge in the outcome tone. */
.proj-terminal { display: flex; align-items: flex-start; gap: 14px; padding: 14px 16px;
  background: var(--surface); border: 1px solid var(--border-lo); border-radius: var(--r-md);
  border-left: 4px solid var(--c); }
.proj-terminal--lost { --c: var(--danger); }
.proj-terminal--cancelled { --c: var(--text-3); }
.proj-terminal__mark { font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--c); padding-top: 2px; flex: none; }
.proj-terminal__body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.proj-terminal__body strong { font-size: 14px; color: var(--text-1); }
.proj-terminal__body .muted { font-size: 12.5px; }

/* ════ THE DEAL — the page's focal point: a hero amount + per-trade scope + status + actions. ════ */
.deal__head { display: flex; align-items: baseline; gap: 14px; }
.deal__label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-3); }
.deal__amount { font-family: var(--font-display); font-size: 34px; font-weight: 700;
  letter-spacing: -0.02em; color: var(--text-1); line-height: 1; margin-left: auto; }
.deal__amount--empty { color: var(--text-3); font-size: 28px; }
.deal__facts { display: flex; flex-wrap: wrap; gap: 12px 30px; margin-top: 16px; }
.deal__fact { display: flex; flex-direction: column; gap: 3px; }
.deal__fact .k { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--text-3); }
.deal__fact .v { font-size: 13.5px; color: var(--text-1); font-weight: 500; }

/* Per-trade scope list (every trade on the engagement, priced or awaiting a design). */
.scope { margin-top: 16px; border-top: 1px solid var(--border-lo); }
.scope__line { display: flex; align-items: baseline; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border-lo); }
.scope__trade { font-size: 13.5px; font-weight: 600; color: var(--text-1); text-decoration: none; }
.scope__trade:hover { color: var(--brass-lo); }
.scope__design { font-size: 12px; }
.scope__price { margin-left: auto; font-size: 13.5px; color: var(--text-1); font-variant-numeric: tabular-nums; }
.scope__add { display: flex; gap: 8px; margin-top: 12px; }
.scope__add .input { max-width: 170px; }

/* Next-step guidance card — plain-language "do this next", brass-tinted so it reads as the prompt. */
.nextstep { background: linear-gradient(160deg, var(--brass-soft), var(--surface)); border-color: var(--brass-lo); }
.nextstep__label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--brass-lo); margin-bottom: 8px; }
.nextstep__hint { font-size: 13.5px; line-height: 1.5; color: var(--text-1); margin: 0 0 14px; }
.nextstep .btn.prim { width: 100%; justify-content: center; }

/* Customer card — actionable contact, not a database dump. */
.contact__name { font-family: var(--font-display); font-size: 17px; font-weight: 700; color: var(--text-1); margin-bottom: 8px; }
.contact__line { padding: 3px 0; }
.contact__val { font-family: var(--font-mono); font-size: 13px; color: var(--brass-lo); text-decoration: none; }
.contact__val:hover { text-decoration: underline; }
.contact__meta { font-size: 12.5px; color: var(--text-2); margin-top: 6px; }
/* The customer-name link (contact card) reads as ink, not UA blue (F005). */
.contact__namelink { color: var(--text-1); text-decoration: none; }
.contact__namelink:hover { color: var(--brass-lo); text-decoration: underline; }
/* Bare links inside a key/value cell (dossier phone/email/referrer) take the brass accent, not UA blue (F006). */
.kv .v a, .kv > .v a { color: var(--brass-lo); text-decoration: none; }
.kv .v a:hover, .kv > .v a:hover { text-decoration: underline; }
.contact__sep { height: 1px; background: var(--border-lo); margin: 14px 0; }

/* ── Blueprint direction — display-weight + annotation details (direction A, 2026-06-09) ── */
/* Saira carries the display voice at 800 where Playfair sat at 700. */
.office-toptitle, .proj-hero .proj-name, .deal__amount, .kpi-tile .v { font-weight: 800; }
.proj-hero .proj-code, .h-code { color: var(--brass); }
/* The reference-number chip reads as a drawing label: orange mono, no pill. */
.proj-code { font-family: var(--font-mono); letter-spacing: 0.08em; }

/* ── §5 holds — the stop-work banner (Phase 1 coverage build, 2026-06-09). A frozen engagement
   must be impossible to miss: danger-edged flat card, drafting style, above the stepper. ── */
.hold-banner { background: rgba(194,54,43,0.06); border: 1px solid var(--danger);
  border-left: 4px solid var(--danger); border-radius: var(--r-md); padding: 13px 16px; margin: 0 0 16px; }
.hold-banner__head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  color: var(--danger); font-size: 13.5px; }
.hold-banner__head .ico { width: 16px; height: 16px; }
.hold-banner__head strong { color: var(--text-1); font-weight: 700; }
.hold-banner__body { margin-top: 6px; font-size: 12.5px; color: var(--text-2); }
.hold-banner__acts { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.hold-banner__link { color: var(--danger); font-weight: 600; text-decoration: none; margin-left: 8px; }
.hold-banner__link:hover { text-decoration: underline; }

/* Portal terminal-project note (Phase 1 — dead engagement never collects). */
.portal-note { font-size: 13px; line-height: 1.55; color: var(--text-2); background: var(--surface-lo);
  border: 1px solid var(--border-lo); border-radius: var(--r-md); padding: 12px 14px; margin: 0 0 14px; }

/* D-24 portal estimate card fine print. */
.portal-finehint { font-size: 11.5px; margin-top: 8px; }


/* ══ Phase 2 — recovery paths (2026-06-09) ══ */
/* Payments worklist (money-events): next-step hint text in table rows + under the record form. */
.cell-hint { color: var(--text-3); font-size: 12.5px; max-width: 26rem; display: inline-block; }

/* ── Purchasing (materials cluster, 2026-06-09): per-order tool rows + disclosures ─────────────
   The purchasing table grows a sub-row under each order carrying its state-gated tools
   (receive lines / promised date / invoice / re-source / start return). Disclosure pattern
   mirrors .doc-upload. */
.data-table tr.mo-tools > td { background: var(--surface-lo); border-top: 0; padding: 8px 16px 12px; }
.mo-tools .inline-form, .mo-tools .todo-actform { display: inline-flex; vertical-align: middle;
  margin: 4px 12px 0 0; }
.mo-tools > td > .muted { margin-right: 12px; }
.mo-disclose { display: inline-block; vertical-align: middle; margin: 4px 12px 0 0; }
.mo-disclose > summary { display: inline-flex; cursor: pointer; list-style: none; }
.mo-disclose > summary::-webkit-details-marker { display: none; }
.mo-disclose__form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px;
  margin-top: 10px; padding: 14px; background: var(--surface); border: 1px solid var(--border-lo);
  border-radius: var(--r-lg); box-shadow: var(--shadow-card); }
.mo-disclose__field { display: flex; flex-direction: column; gap: 4px; font-size: 11px;
  font-weight: 600; letter-spacing: .02em; text-transform: uppercase; color: var(--text-3); }
.mo-disclose__field .input { min-width: 160px; font-size: 13px; text-transform: none;
  font-weight: 400; letter-spacing: 0; color: var(--text-1); }
.mo-disclose__form .mo-lines { flex: 1 1 100%; }
.mo-lines { width: 100%; border-collapse: collapse; }
.mo-lines th { font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-3); text-align: left; padding: 4px 8px; }
.mo-lines td { padding: 4px 8px; font-size: 12.5px; color: var(--text-2);
  border-top: 1px solid var(--border-lo); }
.mo-lines th.num, .mo-lines td.num { text-align: right; }
.input.mo-qty { width: 92px; }

/* ══ Phase 3 — the five-pattern visual sweep (2026-06-09) ══ */
/* ── Phase-3 dash-todo sweep ─────────────────────────────────────────────── */
/* Toasts clear the sticky topbar (search / sign-out) instead of covering it. */
.toast-stack { top: 78px; }

/* Blueprint geometry: square the initials avatars (retheme seam — were 50% circles). */
.avatar, .office-avatar, .todo-avatar { border-radius: var(--r-sm); }

/* Channel-mix bar: drop the hardcoded 7px pill radius to the token scale. */
.chan-bar { border-radius: var(--r-sm); }

/* "Visit" markers move to blueprint blue — danger red stays exclusively "blocked",
   and the brass accent stops doubling as a data color on the map/queues. */
.q-dot.visit { background: var(--s-quoting); }
.lg.visit::before { background: var(--s-quoting); }

/* To-do queue: row titles are links to the task's record. */
a.todo-title { color: var(--text-1); text-decoration: none; }
a.todo-title:hover { color: var(--brass-lo); text-decoration: underline; }

/* Collapsible due buckets (details/summary) — "No date" ships closed. */
details.todo-bucket > summary.todo-buckethead { cursor: pointer; user-select: none; list-style: none; }
details.todo-bucket > summary.todo-buckethead::-webkit-details-marker { display: none; }
details.todo-bucket > summary.todo-buckethead::before { content: "▸"; font-size: 10px; color: var(--text-3); }
details.todo-bucket[open] > summary.todo-buckethead::before { content: "▾"; }

/* Quiet exception actions (Block / Cancel) so Start `prim` reads as the row's one next step. */
.todo-act.ghost { border-color: transparent; color: var(--text-3); background: none; }
.todo-act.ghost:hover { border-color: var(--border); color: var(--text-1); background: var(--surface-hi); }

/* Untimed installs read "All day" — muted so timed slots still pop. */
.sched-time.allday { color: var(--text-3); }

/* ── Phase 3 · funnel sweep ─────────────────────────────────────────────── */

/* Pipeline ledger groups are now <details>/<summary> (summary carries the
   existing .ledger-grouphead class): stage headers chunk the long scroll —
   bigger label, Blueprint surveyor's-diamond stage marker, sticky under the
   topbar, full-width rule, disclosure caret. Completed/Closed start collapsed
   in the view; count + sum stay visible in the folded header. */
summary.ledger-grouphead { list-style: none; cursor: pointer; position: sticky; top: 76px; z-index: 3;
  background: var(--bg); }
summary.ledger-grouphead::-webkit-details-marker { display: none; }
.ledger-grouphead { padding: 8px 2px 7px; border-bottom: 1px solid var(--border); }
.ledger-grouphead b { font-size: 14px; }
.ledger-grouphead .stage-dot { border-radius: 1px; transform: rotate(45deg); }
.ledger-grouphead::after { content: ""; flex: none; width: 7px; height: 7px; margin: -2px 4px 0 10px;
  border-right: 1.5px solid var(--text-3); border-bottom: 1.5px solid var(--text-3);
  transform: rotate(-45deg); transition: transform .12s; }
details.ledger-group[open] > .ledger-grouphead::after { transform: rotate(45deg); margin-top: -4px; }
.ledger-rows { margin-top: 10px; }
/* A group sum that includes unsold quotes is forecast, not booked money. */
.ledger-sum.quote { color: var(--text-3); font-weight: 500; }

/* Lead intake: the per-row assign select gets the same appearance reset +
   brass chevron as select.input — it sat as the screen's one native-rounded
   control beside the square Assign button. (Not given .input: that rule's
   width:100% would break the row's inline-flex.) */
select.lead-assign-select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 28px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none' stroke='%23b23f1c' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center; background-size: 12px 12px;
}
select.lead-assign-select:hover, select.lead-assign-select:focus {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none' stroke='%23d8542a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E");
}

/* Suggested-rep line: the happy path is a quiet confirmation (gray); the
   no-coverage case is the alarming one — orange/danger means "look here". */
.lead-suggest { color: var(--text-3); }
.lead-suggest.none { color: var(--danger); }

/* Sentence-case help line under a field's controls (e.g. Trades on lead intake). */
.field-help { font-size: 11.5px; color: var(--text-3); }

/* ── [customers sweep] ──────────────────────────────────────────────────── */
/* Demote the rolodex mailto: tertiary data, not a call to action — muted like the rest
   of .rr-sub, underline only on hover, so names carry the scan track. */
.record-row .rr-sub a { color: var(--text-3); text-decoration: none; }
.record-row .rr-sub a:hover { color: var(--brass-lo); text-decoration: underline; }

/* Terminal stages share the stage-dot anatomy (one pill silhouette per column).
   Lost = muted (didn't win); cancelled/rescinded = red (ended a live deal).
   NOTE: inert until Office::UiHelper::STAGE_CLASSES includes these statuses — see shared_notes. */
.s-lost { background: var(--text-3); }
.s-cancelled, .s-rescinded { background: var(--danger); }

/* Blueprint pass for the one remaining circle family: avatars square off like every
   other tile in the system (later rule wins over the 50% radii at equal specificity). */
.avatar, .office-avatar, .todo-avatar { border-radius: var(--r-sm); }

/* ── Calendars sweep (visual-audit Phase 3) ──────────────────────────────── */

/* [cal] The viewed date is the toolbar's title on a date-paging surface — promote it
   to the display face (overrides the 15px .js-week-label rule earlier in the file;
   it already carries var(--font-display)/var(--text-1)). */
.js-week-label { font-size: 19px; }

/* [cal] Blueprint corner tokens — retire the old-skin rounded shapes on the calendar
   and dispatch board (hardcoded 50% / 5px / 3px / 999px radii predate the token layer). */
.cal-event { border-radius: var(--r-sm); }
.cal-rep-avatar { border-radius: var(--r-sm); }
.cal-dot, .gantt-swatch, .gantt-crew-dot { border-radius: var(--r-sm); }
.gantt-crew-load { border-radius: var(--r-pill); }

/* [cal] Week view, all reps: the rep-initials chip on each block (who covers the visit).
   Absolutely positioned inside .cal-event; pointer-events off so the block stays the tap target. */
.cal-event-rep { position: absolute; top: 2px; right: 2px; width: 15px; height: 15px;
  border-radius: var(--r-sm); display: grid; place-items: center; color: #fff;
  font-size: 7.5px; font-weight: 700; letter-spacing: 0.02em; pointer-events: none; }

/* [gantt] Today/weekend cues carried through the lane bodies. Grid items honor z-index
   even when static — shades sit at 0, bars at 1. Negative vertical margin bleeds the
   column through the lane's 10px padding so it reads floor-to-ceiling. */
.gantt-colshade { pointer-events: none; z-index: 0; margin: -10px 0; background: var(--surface-hi); }
.gantt-colshade.is-today { background: color-mix(in srgb, var(--brass-soft) 60%, transparent);
  border-left: 1px solid var(--brass); border-right: 1px solid var(--brass); }

/* [gantt] Double-booked crew: overlapping bars get a hatched warning fill; the lane
   gutter carries an "N overlap" chip. */
.gantt-bar.is-conflict { border-left-color: var(--warning);
  background-image: repeating-linear-gradient(135deg, transparent 0 6px, color-mix(in srgb, var(--warning) 16%, transparent) 6px 12px); }
.gantt-swatch.is-conflict { --bar-c: var(--warning);
  background-image: repeating-linear-gradient(135deg, transparent 0 3px, color-mix(in srgb, var(--warning) 16%, transparent) 3px 6px); }
.gantt-crew-conflict { flex: none; font-family: var(--font-mono); font-size: 9.5px; color: var(--text-1);
  background: color-mix(in srgb, var(--warning) 18%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--warning) 45%, var(--surface));
  border-radius: var(--r-pill); padding: 1px 7px; white-space: nowrap; }

/* [gantt] Clipped-bar affordance: dash the RIGHT edge too (only the left dashed before),
   plus the legend swatch that explains the dashes. */
.gantt-bar.is-clipped-r { border-right: 3px dashed var(--bar-c, var(--s-qualified)); }
.gantt-swatch.is-clipped { border-left-style: dashed; }

/* [gantt] Crew gutter: the row key of a dispatch board must read without a hover —
   widen further (the [#66] 205px attempt still truncated) and wrap to two lines. */
.gantt { --gantt-gutter: 240px; }
.gantt-crew-name { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 2; overflow: hidden; line-height: 1.25; }

/* ── Phase 3 · project cluster ──────────────────────────────────────────────── */
/* Inline-form selects: the compact `padding: 8px 10px` shorthand (.inline-form rule)
   clobbers the 34px chevron clearance from `select.input`, so medium-length options
   ("Inbound", "Med") underlapped the brass caret. Restore the right padding at the
   same specificity, later in the cascade. */
.inline-form select.input { padding-right: 30px; }

/* Empty quote amount: plain words at body scale — the display-size em dash read as a
   window-collapse bar in the deal card's top-right corner. Double class out-specifies
   the 34px/800-weight .deal__amount base rules. */
.deal__amount.deal__amount--empty { font-family: var(--font-ui); font-size: 12.5px;
  font-weight: 500; letter-spacing: 0; }

/* A human name in a .kv key slot reads in body case, not mono-caps annotation
   (Money > Commissions salesperson rows). */
.kv > .k.k--person { font-family: var(--font-ui); font-size: 12.5px; letter-spacing: 0;
  text-transform: none; color: var(--text-1); font-weight: 500;
  display: inline-flex; align-items: center; gap: 6px; }

/* Blueprint seam: the shared initials avatar squares to the geometry tokens.
   (Safe to dedup if the avatar-owning cluster returned the same rule.) */
.avatar { border-radius: var(--r-sm); }

/* Quiet jump-links in the detail aside (e.g. the WO "Related" card) — navigation, not actions. */
.aside-links { display: flex; flex-direction: column; gap: 8px; }
.aside-links a { display: inline-flex; align-items: center; gap: 8px; color: var(--text-2); font-size: 13px; text-decoration: none; }
.aside-links a:hover { color: var(--brass-lo); text-decoration: underline; }
.aside-links a .ico { width: 14px; height: 14px; color: var(--text-3); }

/* crews-claims sweep — append to office.css */

/* Button component is invariant: don't inherit the panel title's uppercase/letter-spacing
   when an action button sits inside .panel-title--withaction (crew show "＋ Upload"). */
.panel-title--withaction .btn { text-transform: none; letter-spacing: normal; }

/* Keep the brass chevron visible on selects inside inline forms: the
   `.inline-form .input, .inline-form select.input { padding: 8px 10px }` shrink override
   (specificity 0,2,1) clobbers select.input's right-side chevron reserve (0,1,1).
   Must appear AFTER the existing .inline-form rule. */
.inline-form select.input { padding-right: 34px; }

/* ── Finance sweep (visual-audit Phase 3) ─────────────────────────────────────────── */
/* Payments: past-due receivables are the day's first calls — tint + left rule so they lead the scan. */
.row-overdue td, .row-attention td { background: color-mix(in srgb, var(--danger) 6%, transparent); }
.row-overdue td:first-child, .row-attention td:first-child { box-shadow: inset 3px 0 0 var(--danger); }
/* AR board: "Collect now" leads; the overdue total floats right of its heading. The future schedule
   recedes (dimmed) so the actionable worklist pops, and comes back to full weight on hover. */
.ar-head .badge { margin-left: auto; }
.ar-scheduled { opacity: 0.8; transition: opacity 0.15s ease; }
.ar-scheduled:hover { opacity: 1; }

/* Accounting: settled (closed/locked) periods stay quiet — Reopen lives behind a disclosure that
   reveals reason + a danger-confirmed submit, never a standing orange button per row. */
.reopen-disclosure { display: inline-block; }
.reopen-disclosure > summary { display: inline-flex; cursor: pointer; list-style: none; }
.reopen-disclosure > summary::-webkit-details-marker { display: none; }
.reopen-disclosure__form { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.reopen-disclosure__form .input { max-width: 220px; }

/* Commissions: the rep grouping is the page's primary axis — a real band with the owed figure,
   not a 10px mono eyebrow weaker than its own table rows. */
.rep-band { display: flex; align-items: center; gap: 10px; }
.rep-band__name { font-family: var(--font-display); font-weight: 700; font-size: 16px; color: var(--text-1); }
.rep-band__owed { margin-left: auto; font-family: var(--font-display); font-weight: 700; font-size: 16px;
  color: var(--text-1); font-variant-numeric: tabular-nums; }
.rep-band__owed .muted { font: 500 12px var(--font-ui); }

/* Pricing: category · subcategory section bands replace the Category column that repeated
   "Fence · Fence panel" hundreds of times down the flat all-trades dump. */
.table-group-row td { background: var(--surface-lo); font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-3); padding: 8px 16px; }
.table-group-row .count { color: var(--text-2); }

/* system cluster (audit 38-settings-users) — identity avatars join the Blueprint
   square-corner geometry. Indicator dots (.stage-dot/.notif-dot/.health-dot/.state-dot)
   stay round on purpose: they're status dots, not identity chips. */
.avatar, .office-avatar, .todo-avatar { border-radius: var(--r-sm); }
/* ── RRP qualification form (model §RRP — build year + per-trade paint-disturbance) ── */
.tb-menu__pop--wide { min-width: 340px; }
.qualify-row { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; }
.qualify-field { display: flex; flex-direction: column; gap: 4px; font-size: 11px; font-weight: 600;
  letter-spacing: .02em; text-transform: uppercase; color: var(--text-3); }
.qualify-field .input { width: 110px; font-size: 13px; font-weight: 400; text-transform: none; letter-spacing: 0; }
.qualify-window { align-self: center; padding-top: 12px; }
/* The RRP banner on a gated job — same stop-work language family as holds, informational tone. */
.rrp-chip { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-mono);
  font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--warning);
  border: 1px solid var(--warning); border-radius: var(--r-sm); padding: 3px 8px; }
/* ── close-decline-qvf: the per-trade close picker (office/projects/_close_sale_form) ── */
.close-sale { display: flex; flex-direction: column; gap: 10px; }
.close-sale--hero { align-items: flex-end; }
.close-sale__trades { border: 1px solid var(--border-lo); border-radius: var(--r-md); padding: 8px 12px; margin: 0; display: flex; flex-direction: column; gap: 6px; background: var(--surface-hi); }
.close-sale__trades legend { font-size: 12px; color: var(--text-3); padding: 0 4px; }
.close-sale__trade { display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; }
.close-sale__trade .money { margin-left: auto; }
/* ── Milestone chain two-layer rows (owner 2026-06-11 — the single mega-cell read "thrown on
   there"): the table row keeps identity + the one forward action; the proof package + every
   input-bearing secondary op live in this structured sub-panel under the row. ── */
.ms-table td.ms-actcol { text-align: right; white-space: nowrap; }
.ms-table th.ms-actcol { text-align: right; }
/* Fixed layout pins the six columns to the main column's width. Auto-layout grew the table to keep
   "Blue Ridge Deck Builders" on one line, spilling the action cell under the sticky aside; now the
   crew cell wraps and every column stays put. Gutters tightened so the columns breathe. */
.ms-table { table-layout: fixed; }
.ms-table thead th, .ms-table tbody td { padding-left: 11px; padding-right: 11px; }
.ms-table th:nth-child(1), .ms-table td:nth-child(1) { width: 15%; } /* milestone */
.ms-table th:nth-child(2), .ms-table td:nth-child(2) { width: 24%; } /* crew (wraps) */
.ms-table th:nth-child(3), .ms-table td:nth-child(3) { width: 12%; } /* scheduled */
.ms-table th:nth-child(4), .ms-table td:nth-child(4) { width: 7%; }  /* % */
.ms-table th:nth-child(5), .ms-table td:nth-child(5) { width: 17%; } /* status */
.ms-table th:nth-child(6), .ms-table td:nth-child(6) { width: 25%; } /* action */
.ms-actwrap { flex-wrap: wrap; }
.ms-table .actions.end { justify-content: flex-end; flex-wrap: nowrap; }
/* Accordion rows — expandable rows are clickable; only one panel opens at a time. The forward
   action + the caret toggle ride together in the action cell (the caret is the keyboard target). */
.ms-table tr.ms-row--exp { cursor: pointer; }
.ms-table tr.ms-row--exp:hover { background: var(--surface-hi); }
.ms-actwrap { display: inline-flex; align-items: center; gap: 8px; justify-content: flex-end; }
.ms-caret { border: none; background: none; padding: 2px 4px; line-height: 1; cursor: pointer;
  color: var(--text-3); font-size: 11px; transition: transform 0.15s ease, color 0.12s ease; }
.ms-caret:hover { color: var(--brass-lo); }
.ms-table tr.ms-row.is-open .ms-caret { transform: rotate(180deg); }
/* The open row hands off to its panel — kill the bottom rule so they read as one unit. */
.ms-table tbody tr.ms-row.is-open > td { border-bottom: none; }
.ms-table tbody tr.ms-sub[hidden] { display: none; }
.ms-table tbody tr.ms-sub td { padding: 0 16px 14px; }
.ms-table tbody tr.ms-sub:hover { background: transparent; }
.ms-panel { display: flex; flex-direction: column; gap: 12px;
  border: 1px solid var(--border-lo); border-left: 3px solid var(--brass);
  border-radius: var(--r-sm); background: var(--surface-hi); padding: 12px 14px; }
.ms-label { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--text-3); white-space: nowrap; align-self: center; }
/* Field-proof evidence card — the package the office certifies, framed as evidence. */
.proof-card { display: flex; flex-direction: column; gap: 8px; }
.proof-card + .proof-card { border-top: 1px dashed var(--border-lo); padding-top: 12px; }
.proof-head { display: flex; align-items: center; gap: 10px; }
.proof-meta { font-size: 11.5px; color: var(--text-3); }
.proof-evidence { display: grid; grid-template-columns: max-content 1fr; gap: 5px 16px;
  align-items: baseline; }
.proof-evidence .ms-label { align-self: baseline; padding-top: 2px; }
.proof-val { font-size: 12.5px; color: var(--text-2); display: flex; align-items: center;
  gap: 8px; flex-wrap: wrap; }
.proof-photo { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-mono);
  font-size: 11px; color: var(--text-2); border: 1px solid var(--border-lo);
  border-radius: var(--r-sm); padding: 3px 8px; background: var(--surface); }
.proof-photo a { color: var(--brass-lo); font-weight: 600; text-decoration: none; }
.proof-photo a:hover { text-decoration: underline; }
/* Accept/reject — one right-anchored review line; accept is the single primary. */
.proof-review { display: flex; align-items: center; justify-content: flex-end; gap: 10px;
  border-top: 1px dashed var(--border-lo); padding-top: 10px; }
.proof-review .ms-op { flex: 0 1 360px; }
/* Labeled secondary-op lines — every input-bearing form is one aligned cluster. */
.ms-op { display: flex; align-items: center; gap: 8px; margin: 0; }
.ms-op .input { width: auto; font-size: 12px; padding: 5px 8px; }
.ms-op .input.grow { flex: 1 1 10rem; }
.ms-op .input[type="file"] { font-size: 11px; }
.ms-ops { display: flex; align-items: center; gap: 10px 26px; flex-wrap: wrap;
  border-top: 1px dashed var(--border-lo); padding-top: 10px; }
.ms-ops .ms-op-end { margin-left: auto; }
.ms-input-pct { width: 64px; }
.ms-input-amount { width: 96px; }
/* Routine vs exception split — the panel's ops are grouped so the everyday "Update" path reads first
   and the "something went wrong" recovery/unwind controls sit apart and quieter. */
.ms-ops__lead { color: var(--text-2); font-weight: 600; align-self: center; }
.ms-ops--exc { margin-top: 2px; }
.ms-ops__lead--exc { color: var(--danger); }
.todo-act.ms-op-danger:hover { color: var(--danger); border-color: var(--danger); }
/* Dispatch-a-replacement-milestone — a rare mid-chain recovery, folded behind its subhead (caret)
   so it doesn't sit open under the chain. Mirrors the payment-history disclosure pattern. */
.ms-extra > summary { cursor: pointer; list-style: none; display: inline-flex; align-items: center;
  gap: 6px; width: fit-content; }
.ms-extra > summary::-webkit-details-marker { display: none; }
.ms-extra > summary::after { content: "▾"; font-size: 9px; opacity: 0.55; }
.ms-extra[open] > summary::after { content: "▴"; }
.ms-extra > summary:hover { color: var(--text-2); }
.ms-extra .doc-note { margin-top: 8px; }
/* ── Crew dispatch profile (service area + payout rate cards) ── */
.dispatch-profile { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: 26px; align-items: start; }
@media (max-width: 760px) { .dispatch-profile { grid-template-columns: minmax(0, 1fr); gap: 18px; } }
.service-area-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 6px 14px; }
.service-area-opt { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-2);
  cursor: pointer; padding: 4px 2px; }
.service-area-opt input { accent-color: var(--brass); }
.rate-card { border: 1px solid var(--border-lo); border-radius: var(--r-sm); background: var(--surface-hi);
  padding: 12px 14px; display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.rate-card-head { font-family: var(--font-display); font-weight: 700; font-size: 14px; color: var(--text-1); }
.rate-card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px 16px; }
.rate-cell { display: flex; flex-direction: column; gap: 4px; }
.rate-input { display: flex; align-items: center; gap: 5px; }
.rate-input .input { width: 100%; font-size: 13px; padding: 6px 8px; }
.rate-card .todo-act { align-self: flex-start; }
/* Over-ceiling discount approval gate on the close form (audit G5) */
.ceiling-gate { margin-top: 10px; padding: 10px 12px; border: 1px solid var(--warning);
  border-left: 3px solid var(--warning); border-radius: var(--r-sm); background: rgba(199,121,27,0.06);
  display: flex; flex-direction: column; gap: 8px; }
.ceiling-gate .doc-note { margin: 0; }
/* C-6 office IME SKU mapping screen (audit G11) — one form-card per unmapped product */
.sku-map-list { display: flex; flex-direction: column; gap: 10px; }
.sku-map-card { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; margin: 0;
  border: 1px solid var(--border-lo); border-radius: var(--r-sm); background: var(--surface-hi); padding: 12px 14px; }
.sku-map-product { flex: 1 1 220px; min-width: 0; }
.sku-map-field { display: flex; flex-direction: column; gap: 4px; }
.sku-map-field .input { width: auto; min-width: 150px; }

/* ── Follow-up cadence admin (Office::CadencesController; Phase 3.5). The config view behind the
   operational Follow-ups screen: per-sequence cards with the ordered touches, channel cues, a
   per-channel count summary, an active toggle, and the dark-launch status. Tokens only. .cad-* */
.cad-darklaunch { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 18px;
  padding: 13px 15px; border: 1px solid var(--warning); border-left: 3px solid var(--warning);
  border-radius: var(--r-sm); background: color-mix(in srgb, var(--warning) 9%, var(--surface));
  font-size: 13px; line-height: 1.5; color: var(--text-2); }
.cad-darklaunch--off { border-color: var(--danger); border-left-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 9%, var(--surface)); }
.cad-darklaunch > .ico { width: 18px; height: 18px; flex: none; margin-top: 1px; color: var(--danger); }
.cad-darklaunch:not(.cad-darklaunch--off) > .ico { color: var(--warning); }
.cad-darklaunch strong { color: var(--text-1); }
.cad-darklaunch__body { flex: 1; min-width: 0; }
.cad-darklaunch__cta { flex: none; align-self: center; white-space: nowrap; }
.cad-darklaunch__knobs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 9px; }
.cad-flag { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.04em; font-weight: 700;
  padding: 2px 8px; border-radius: var(--r-pill); border: 1px solid var(--border); }
.cad-flag--on  { color: var(--success); border-color: color-mix(in srgb, var(--success) 45%, transparent);
  background: color-mix(in srgb, var(--success) 12%, transparent); }
.cad-flag--off { color: var(--text-3); border-color: var(--border); background: var(--surface-lo); }

.cad-tune { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 18px;
  font-size: 12px; }
.cad-tune .muted { color: var(--text-3); }

.cad-stack { display: flex; flex-direction: column; gap: 16px; }
.cad-seq { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: 16px 18px; }
.cad-seq--paused { background: var(--surface-lo); border-style: dashed; }
.cad-seq__head { display: flex; align-items: flex-start; gap: 16px; }
.cad-seq__id { flex: 1; min-width: 0; }
.cad-seq__name { font-family: var(--font-display); font-weight: 700; font-size: 16px; color: var(--text-1);
  margin: 0 0 7px; }
.cad-seq__meta { display: flex; flex-wrap: wrap; gap: 6px; }
.cad-seq__head .as-switch { flex: none; }
.cad-seq__summary { margin: 12px 0 4px; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.03em;
  color: var(--text-2); }
.cad-seq__count { color: var(--text-1); font-weight: 700; }

.cad-steps { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; }
.cad-step { display: flex; align-items: center; gap: 12px; padding: 9px 4px;
  border-top: 1px solid var(--border-lo); font-size: 13px; }
.cad-step:first-child { border-top: 0; }
.cad-step__n { font-family: var(--font-mono); font-size: 10px; font-weight: 700; color: var(--text-3);
  width: 20px; flex: none; text-align: right; }
.cad-step__when { font-family: var(--font-mono); font-size: 11px; color: var(--text-2);
  min-width: 92px; flex: none; }
.cad-step__what { color: var(--text-2); min-width: 0; }
.cad-chan { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.06em; font-weight: 700;
  text-transform: uppercase; padding: 2px 8px; border-radius: var(--r-pill); border: 1px solid;
  flex: none; min-width: 64px; text-align: center; }
.cad-chan--voice { color: var(--brass-lo); border-color: color-mix(in srgb, var(--brass) 45%, transparent);
  background: var(--brass-pill); }
.cad-chan--sms { color: var(--s-quoting); border-color: color-mix(in srgb, var(--s-quoting) 45%, transparent);
  background: color-mix(in srgb, var(--s-quoting) 12%, transparent); }
.cad-chan--email { color: var(--s-qualified); border-color: color-mix(in srgb, var(--s-qualified) 45%, transparent);
  background: color-mix(in srgb, var(--s-qualified) 12%, transparent); }
.cad-chan--task { color: var(--text-3); border-color: var(--border); background: var(--surface-lo); }

@media (max-width: 720px) {
  .cad-seq__head { flex-direction: column; }
  .cad-darklaunch { flex-direction: column; }
  .cad-darklaunch__cta { align-self: flex-start; }
  .cad-step { flex-wrap: wrap; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Project page — progressive-disclosure cards (lead with the object, hide
   the machinery until reached for). Sales visits / Conversation / Quote-start.
   Token-only; reuses .btn, .todo-act, .cal-book, .notif-row, .badge.
   ═══════════════════════════════════════════════════════════════════════ */

/* A .btn / .todo-act used as a <summary> shouldn't carry the disclosure triangle. */
.appt-book > summary,
.appt-disc > summary,
.quote-start > summary,
.quote-addtrade > summary { list-style: none; cursor: pointer; }
.appt-book > summary::-webkit-details-marker,
.appt-disc > summary::-webkit-details-marker,
.quote-start > summary::-webkit-details-marker,
.quote-addtrade > summary::-webkit-details-marker { display: none; }

/* ── Shared inline-control height (GENERAL) ──────────────────────────────────────────────────────────
   Every control that shares an inline write-row aligns to --control-h, so an input, select, .btn, and
   .todo-act all land on ONE height instead of each at its own. Coverage:
   • every `.inline-form` on the page (add-trade, refund, reschedule/follow-up/book manual, reassign) —
     their `.input` / `.btn` / `.todo-act` row members;
   • the Activity & Notes composer (`.composer-form`) — its selects, the `What happened?`/note/to-do input,
     and the `.todo-act.prim` Log-it / Add-note / Add-to-do button (the one the owner circled);
   • the three rows round 2 already squared: the sales-visit status pill + its action buttons, and the
     conversation composer's message input + channel select + Send.
   The forms stay `align-items: flex-end` + `flex-wrap`, so STACKED layouts (a `.cal-book__field` label
   over its datetime input, then a button below) and MULTI-control rows keep their wrapping — this only
   equalizes heights, it never forces controls onto one line. */
.inline-form .input,
.inline-form .btn,
.inline-form .todo-act,
.composer-form .input,
.composer-form .btn,
.composer-form .todo-act,
.notif-row > .badge,
.notif-row .todo-acts > .todo-actform > .todo-act,
.notif-row .todo-acts > details > summary.todo-act,
.thread-composer__send .input,
.thread-composer__send .btn { min-height: var(--control-h); box-sizing: border-box; }
/* Buttons/pills (flex children) center their label within the matched height; inputs/selects center their
   own text natively. */
.inline-form .btn,
.inline-form .todo-act,
.composer-form .btn,
.composer-form .todo-act,
.notif-row > .badge,
.notif-row .todo-acts > .todo-actform > .todo-act,
.notif-row .todo-acts > details > summary.todo-act,
.thread-composer__send .btn { display: inline-flex; align-items: center; }
/* Trim the inputs/selects whose default vertical padding runs taller than --control-h down to the shared
   height, so a field and its neighbouring button meet exactly (round 2 did this for two rows; now general).
   The `select.input` variants are listed explicitly: `.inline-form select.input` (line ~502) carries an
   element in its selector, so a class-only rule would lose to it on a <select>. */
.inline-form .input, .inline-form select.input,
.composer-form .input, .composer-form select.input,
.thread-composer__send .input, .thread-composer__send select.input { padding-top: 0; padding-bottom: 0; }

/* ── Card 1 · Sales visits — booking collapses to one "＋ Book a visit" door ── */
.appt-book { display: block; }
/* Right-align only the trigger; the body is block-level so the expanded picker spans the full card. */
.appt-book > summary { display: flex; width: fit-content; margin-left: auto; }
.appt-book__body { margin-top: 12px; padding-top: 14px;
  border-top: 1px solid var(--border-lo); display: flex;
  flex-direction: column; gap: 12px; }
/* The manual-time fallback reads as a quiet link, not a button — the slots are the path. */
.appt-link { display: inline-flex; align-items: center; cursor: pointer; padding: 2px 0;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.02em; color: var(--text-3);
  text-decoration: underline; text-underline-offset: 3px; }
.appt-link:hover { color: var(--text-2); }

/* The slot-picker form sits INSIDE the disclosure's own --surface-lo box — strip its standalone card
   chrome (padding / border / background) so the picker reads as one surface, not box-in-box. */
.appt-book__body .cal-book__form,
.appt-disc__body .cal-book__form { padding: 0; border: 0; background: none; box-shadow: none; margin-top: 0; }
/* "Book selected slot" / "Reschedule to slot" size to their label, not the stretched column width. */
.appt-book__body .cal-book__slots > [type="submit"],
.appt-disc__body .cal-book__slots > [type="submit"] { align-self: flex-start; }

/* The quiet per-visit reschedule / follow-up disclosure (and the nested manual-time fallback). */
.appt-disc { display: block; }
.appt-disc > summary { display: inline-flex; }
.appt-disc__body { margin-top: 10px; display: flex; flex-direction: column; gap: 10px; }
/* "More times" tucked under the top-3 slot list — a calm indented continuation. */
.appt-disc--more { margin-top: 2px; }
.appt-disc--more > summary { color: var(--text-3); }
.appt-disc--more .cal-book__slot { margin-top: 6px; }

/* ── Card 2 · Conversation — ONE unified omni-channel thread (GROUPED), then a slim composer below.
   Lead with the message: customer (inbound) left in a paper bubble, us (Emma / a rep) right in a warm
   safety-orange bubble. Consecutive messages from the same person on the same channel CLUSTER under one
   author·time caption — no repeated meta per line (that repetition was the bulk of the old padding). The
   channel lives as a small glyph in the caption, not the word "Sms"; direction is encoded by side. Calls
   break the rhythm as a full-width event card. An All/Texts/Emails/Calls filter narrows the one thread on
   demand (no data split). Drafting-table tokens — square corners, one flat corner as a subtle tail. ── */
.convo-wrap { display: flex; flex-direction: column; }

/* Channel filter — pure CSS: the radios (visually hidden but focusable) drive the `:checked ~ .convo`
   hide rules below; one thread per page, so the fixed ids are safe. */
.convo-filter__in { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.convo-filter { display: flex; gap: 3px; margin-bottom: 12px; }
.convo-filter label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--text-3); padding: 4px 9px; border: 1px solid var(--border-lo);
  border-radius: var(--r-sm); background: var(--surface-hi); cursor: pointer; user-select: none; }
.convo-filter label:hover { color: var(--text-1); border-color: var(--border); }
#cf-all:checked ~ .convo-filter label[for="cf-all"],
#cf-sms:checked ~ .convo-filter label[for="cf-sms"],
#cf-email:checked ~ .convo-filter label[for="cf-email"],
#cf-voice:checked ~ .convo-filter label[for="cf-voice"] {
  color: var(--brass); border-color: var(--brass); background: var(--brass-soft); }
#cf-all:focus-visible ~ .convo-filter label[for="cf-all"],
#cf-sms:focus-visible ~ .convo-filter label[for="cf-sms"],
#cf-email:focus-visible ~ .convo-filter label[for="cf-email"],
#cf-voice:focus-visible ~ .convo-filter label[for="cf-voice"] { outline: 2px solid var(--brass); outline-offset: 1px; }
/* Narrow to one channel — hide the non-matching blocks + the now-orphaned day rules. */
#cf-sms:checked ~ .convo [data-channel]:not([data-channel="sms"]),
#cf-email:checked ~ .convo [data-channel]:not([data-channel="email"]),
#cf-voice:checked ~ .convo [data-channel]:not([data-channel="voice"]),
#cf-sms:checked ~ .convo .convo-day,
#cf-email:checked ~ .convo .convo-day,
#cf-voice:checked ~ .convo .convo-day { display: none; }

.convo { display: flex; flex-direction: column; gap: 12px; padding: 2px 0; }

/* Day separator — a mono datum label between two hairline rules. */
.convo-day { display: flex; align-items: center; gap: 12px; margin: 4px 0 0; }
.convo-day::before, .convo-day::after { content: ""; flex: 1; height: 1px; background: var(--border-lo); }
.convo-day span { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--text-3); white-space: nowrap; }

/* A cluster — a tight stack of same-sender bubbles + one quiet caption, hugging its side. */
.convo-msg { display: flex; flex-direction: column; gap: 3px; max-width: 80%; }
.convo-msg--in { align-self: flex-start; align-items: flex-start; }
.convo-msg--out { align-self: flex-end; align-items: flex-end; }
.convo-bubble { padding: 8px 11px; border: 1px solid; border-radius: var(--r-md); font-size: 13.5px;
  line-height: 1.5; color: var(--text-1); overflow-wrap: anywhere; }
/* pre-wrap ONLY around the body text — so a message's own line breaks survive without the ERB template's
   indentation/newlines inflating the bubble (the bubble itself collapses that whitespace). */
.convo-bubble__text { white-space: pre-wrap; }
.convo-msg--in .convo-bubble { background: var(--surface-hi); border-color: var(--border); }
.convo-msg--out .convo-bubble { background: var(--brass-soft); border-color: rgba(216,84,42,0.30); }
/* One flat corner on the lead bubble only — a subtle tail toward the speaker. */
.convo-msg--in .convo-bubble:first-child { border-top-left-radius: 0; }
.convo-msg--out .convo-bubble:first-child { border-top-right-radius: 0; }
/* An email is titled — its subject reads as a header rule above the body (a text has none), making a
   formal email instantly distinct from a quick text. */
.convo-bubble--email .convo-subject { font-weight: 600; font-size: 13px; color: var(--text-1);
  padding-bottom: 6px; margin-bottom: 7px; border-bottom: 1px solid var(--border-lo); }
.convo-meta { display: flex; align-items: center; gap: 5px; font-family: var(--font-mono);
  font-size: 10.5px; letter-spacing: 0.02em; color: var(--text-3); margin-top: 1px; padding: 0 2px; }
.convo-chan { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round; flex: none; opacity: 0.8; }
.convo-who { color: var(--text-2); font-weight: 500; }

/* AI call — a full-width event card with the safety-orange datum edge; transcript expands in place. */
.convo-call { align-self: stretch; display: flex; gap: 11px; padding: 11px 13px;
  background: var(--surface-lo); border: 1px solid var(--border-lo); border-left: 2px solid var(--brass);
  border-radius: var(--r-md); }
.convo-call__icon { flex: none; width: 30px; height: 30px; display: grid; place-items: center;
  background: var(--brass-soft); border-radius: var(--r-sm); color: var(--brass); }
.convo-call__icon .ico { width: 15px; height: 15px; }
.convo-call__body { flex: 1; min-width: 0; }
.convo-call__head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.convo-call__title { font-size: 13px; font-weight: 600; color: var(--text-1); }
.convo-call__meta { font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.02em;
  color: var(--text-3); }
.convo-call__summary { margin: 5px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--text-2); }
.convo-call__more { margin-top: 7px; }

/* ── Card 2 · Conversation composer — one slim composer pinned below the thread ── */
.thread { margin-bottom: 4px; }
.thread-composer { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border-lo);
  display: flex; flex-direction: column; gap: 9px; }
.thread-composer__send { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0; }
.thread-composer__send .input.grow { flex: 1 1 14rem; min-width: 0; }
.thread-composer__chan { flex: 0 0 auto; width: auto; }
.thread-composer__aux { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.thread-composer__call { margin: 0; }
.thread-composer__aux .badge { font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.06em; text-transform: uppercase; }

/* ── Card 3 · Quote — single "Start quoting" door / first-trade picker over the empty scope.
   qualified: the real Start-quoting button leads, hint sits under it. quoting: the hint leads the inline
   trade picker. Both follow source order in this column. ── */
.quote-start { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; padding: 6px 0 2px; }
.quote-start__hint { margin: 0; font-size: 12.5px; color: var(--text-2); }
.quote-addtrade { display: block; }
.quote-addtrade > summary { display: inline-flex; }

/* ── Holds aside card — two tiers, soft pause → hard freeze. Each action = a content-width button + one
   quiet descriptor line; the two freezes group under a mono sub-eyebrow. Status lives in the top-of-page
   hold-banner, not here. Square/technical, token-only. ── */
.holds { display: flex; flex-direction: column; gap: 12px; }
.holds__row { display: flex; flex-direction: column; gap: 4px; }
/* Each action's form/disclosure shrinks to its label (a pill), left-aligned — never a full-width slab. */
.holds__act { align-self: flex-start; margin: 0; }
.holds__act > .btn { width: auto; }
.holds__desc { margin: 0; font-size: 12px; line-height: 1.4; color: var(--text-3); }
.holds__desc--danger { color: var(--danger); }
/* Hairline divider + the "FREEZE WORK" sub-eyebrow separating the soft pause from the hard holds. */
.holds__rule { border: 0; border-top: 1px solid var(--border-lo); margin: 4px 0 0; }
.holds__tier { margin: 0; }

/* ── Pool-barrier safety advisory (fence F1a.5) — the LOUD, honest itemized §305 result. A boxed,
   color-coded callout so a fence enclosing a pool is impossible to miss; field_verify rows read as a
   distinct amber "needs field verification", never as a green pass. Token-only / square / technical. ── */
.pba { margin: 16px 0; border: 1.5px solid var(--warning); border-left-width: 5px;
  border-radius: var(--r-lg); background: rgba(199,121,27,0.06); padding: 14px 16px; }
.pba--fail   { border-color: var(--danger);  background: rgba(194,54,43,0.07); }
.pba--verify { border-color: var(--warning); background: rgba(199,121,27,0.07); }
.pba--pass   { border-color: var(--success); background: rgba(44,118,77,0.07); }
.pba__head { display: flex; align-items: center; gap: 12px; }
.pba__icon { flex: none; width: 28px; height: 28px; display: grid; place-items: center;
  border-radius: var(--r-sm); font-family: var(--font-display); font-weight: 700; font-size: 16px;
  color: #fff; background: var(--warning); }
.pba--fail   .pba__icon { background: var(--danger); }
.pba--pass   .pba__icon { background: var(--success); }
.pba__headtext { flex: 1 1 auto; min-width: 0; }
.pba__eyebrow { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-3); }
.pba__summary { font-family: var(--font-display); font-weight: 700; font-size: 15px; color: var(--text-1);
  line-height: 1.25; margin-top: 2px; }
.pba__note { font-size: 12.5px; line-height: 1.5; color: var(--text-2); margin: 10px 0 4px; }
.pba__rules { margin: 10px 0 0; }
.pba__cite { font-family: var(--font-mono); font-size: 11px; color: var(--brass-lo);
  background: var(--brass-soft); border: 1px solid var(--brass-pill); border-radius: var(--r-sm);
  padding: 2px 6px; white-space: nowrap; }
/* The honesty cue: a field_verify row is tinted amber + left-flagged so it reads as UNVERIFIED, visually
   separate from a system-checked pass (which carries no row tint). A fail row is tinted red. */
.pba__row--field_verify > td { background: rgba(199,121,27,0.07); }
.pba__row--field_verify > td:first-child { box-shadow: inset 3px 0 0 var(--warning); }
.pba__row--fail > td { background: rgba(194,54,43,0.07); }
.pba__row--fail > td:first-child { box-shadow: inset 3px 0 0 var(--danger); }
.pba__verify { text-transform: none; letter-spacing: 0.01em; }
.pba__basis { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.04em; color: var(--text-3);
  margin: 10px 0 0; }

/* Fence F4.1 — the build/permit BILL-OF-MATERIALS. A quiet, neutral take-off card (NOT the loud safety
   tint of .pba) — it sits under the customer LF price and reads as the crew/permit quantity list. */
.bom { margin: 12px 0 0; border: 1px solid var(--line); border-left: 3px solid var(--brass);
  border-radius: var(--r-lg); background: var(--surface-2, rgba(0,0,0,0.015)); padding: 12px 14px; }
.bom + .bom { margin-top: 14px; }
.bom__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.bom__title { margin-top: 0; }
.bom-gate { border: 1px solid var(--line); border-radius: var(--r-sm); padding: 8px 10px; margin: 6px 0; }
.bom-gate__head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
/* Costed BOM (MAT-1) — the estimated material-cost total under the quantity take-off. */
.bom__total { display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--line); }
.bom__total strong { font-size: 1.05em; }

/* ── Web Designer (CAD-WEB-1 Phase 0) — the composed read-only plan view. The canvas is the
   drafting sheet itself: parchment surface, pencil-rule border, mono annotations. The JS reads
   these tokens off :root at draw time, so canvas colors stay on the BLUEPRINT contract. ── */
.designer { display: flex; flex-direction: column; gap: 12px; }
.designer__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; }
.designer__id { display: flex; align-items: baseline; gap: 12px; }
.designer__title { margin: 0; font-family: var(--font-display); font-size: 20px; font-weight: 700; }
.designer__mode { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em;
  color: var(--brass); border: 1px solid var(--brass); border-radius: var(--r-pill); padding: 2px 8px; }
.designer__status { font-family: var(--font-mono); font-size: 11px; color: var(--text-3); }
/* POL-07 -- the persistent save indicator beside the mode pill. */
.designer-save { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em;
  color: var(--text-3); border: 1px solid var(--border-lo); padding: 2px 8px; white-space: nowrap; }
.designer-save[hidden] { display: none; }
.designer-save.is-saving { color: var(--text-2); border-color: var(--border); }
.designer-save.is-error { color: var(--danger); border-color: var(--danger); }
/* Phase 1 — the 2D/3D + FINISHED⇄FRAMING segmented controls (BLUEPRINT: square corners, mono caps). */
.designer__tools { display: flex; align-items: center; gap: 12px; }
.designer-seg { display: inline-flex; border: 1px solid var(--border); background: var(--surface); }
.designer-seg[hidden] { display: none; } /* the author display would otherwise defeat `hidden` */
.designer-seg__btn { appearance: none; border: 0; background: transparent; cursor: pointer;
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-2); padding: 5px 12px; }
.designer-seg__btn + .designer-seg__btn { border-left: 1px solid var(--border); }
.designer-seg__btn:hover { color: var(--text-1); background: var(--surface-hi); }
.designer-seg__btn.is-active { background: var(--brass); color: var(--surface-hi); }
/* The Three.js canvas gets orbit affordances, not the 2D grab cursor. */
.designer__canvas canvas.designer__gl { cursor: default; }
.designer__canvas canvas.designer__gl:active { cursor: move; }
.designer__body { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 12px;
  align-items: stretch; }
.designer__canvas { position: relative; min-height: 60vh; height: calc(100vh - 220px);
  background: var(--surface-hi); border: 1px solid var(--border); border-radius: var(--r-md);
  box-shadow: var(--shadow-lift); overflow: hidden; }
.designer__canvas canvas { display: block; width: 100%; height: 100%; touch-action: none;
  user-select: none; -webkit-user-select: none; cursor: grab; }
.designer__canvas canvas:active { cursor: grabbing; }
.designer__empty { margin: 0; padding: 24px; color: var(--text-3); font-size: 13px; }
.designer__rail { background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: 14px; overflow-y: auto; height: calc(100vh - 220px); }
.designer__rail-title { margin: 0 0 10px; font-family: var(--font-mono); font-size: 11px;
  font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-2); }
.designer-wo { border-top: 1px solid var(--border-lo); padding: 10px 0; }
.designer-wo:first-of-type { border-top: none; padding-top: 0; }
/* POL-01: the head row wraps rather than clipping -- with a status chip + History/Gates/
   Materials buttons at 1280px the price overflowed the 320px rail. The money never truncates. */
.designer-wo__head { display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: flex-start; gap: 4px 8px; }
.designer-wo__trade { font-family: var(--font-display); font-weight: 700; font-size: 13.5px; }
.designer-wo__total { font-family: var(--font-mono); font-weight: 600; white-space: nowrap;
  margin-left: auto; }
.designer-wo__lines { list-style: none; margin: 6px 0 0; padding: 0; }
.designer-wo__line { display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  font-size: 12px; padding: 2px 0; color: var(--text-2); }
.designer-wo__line-price { font-family: var(--font-mono); white-space: nowrap; color: var(--text-1); }
.designer-wo__err { color: var(--danger); font-size: 12px; margin: 6px 0 0; }

/* ── Web Designer Phase 2 — editing chrome (CAD-WEB-1): Edit toggle, undo/redo, W×D numeric
   entry, and the lease/lifecycle banner. Same BLUEPRINT vocabulary as the Phase 1 segs. ── */
.designer__mode.is-editing { color: var(--surface-hi); background: var(--brass); }
.designer-edit-btn { border: 1px solid var(--border); background: var(--surface); }
.designer-edit-btn.is-active { border-color: var(--brass); }
.designer-seg__btn[hidden] { display: none; }
.designer-seg__btn:disabled { color: var(--text-3); cursor: default; background: transparent; }
.designer-dims { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--border);
  background: var(--surface); padding: 3px 8px; }
.designer-dims[hidden] { display: none; }
.designer-dims__label { display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em; color: var(--text-3); }
.designer-dims__input { width: 52px; border: 1px solid var(--border-lo); background: var(--surface-hi);
  font-family: var(--font-mono); font-size: 12px; padding: 2px 4px; color: var(--text-1); }
.designer-dims__x, .designer-dims__unit { font-family: var(--font-mono); font-size: 10px; color: var(--text-3); }
.designer-banner { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  border: 1px solid var(--danger); border-left-width: 4px; background: var(--surface);
  padding: 8px 12px; font-family: var(--font-mono); font-size: 12px; color: var(--text-1); }
.designer-banner[hidden] { display: none; }
.designer-banner__btn { appearance: none; cursor: pointer; border: 1px solid var(--brass);
  background: var(--brass); color: var(--surface-hi); font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.06em; padding: 4px 10px; }
.designer-banner__btn:hover { filter: brightness(0.95); }

/* ── Web Designer Wave B2 — pinned advisory strip (pool-barrier §305 + fence zoning).
   The pool banner ALWAYS renders first: nothing on the canvas outranks a pool barrier.
   Honesty invariant: field-verify renders amber, never the green pass treatment. ── */
.designer-advisories { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.designer-advisories[hidden] { display: none; }
.designer-advisory__banner { appearance: none; cursor: pointer; display: flex; align-items: center;
  justify-content: space-between; gap: 12px; width: 100%; text-align: left;
  border: 1px solid var(--border); border-left-width: 4px; background: var(--surface);
  padding: 8px 12px; color: var(--text-1); }
.designer-advisory__banner:hover { background: var(--surface-hi); }
.designer-advisory__banner.is-danger { border-color: var(--danger); }
.designer-advisory__banner.is-warning { border-color: var(--warning); }
.designer-advisory__banner.is-success { border-color: var(--success); }
.designer-advisory__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.designer-advisory__kicker { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-3); }
.designer-advisory__banner.is-danger .designer-advisory__kicker { color: var(--danger); }
.designer-advisory__banner.is-warning .designer-advisory__kicker { color: var(--warning); }
.designer-advisory__banner.is-success .designer-advisory__kicker { color: var(--success); }
.designer-advisory__summary { font-size: 13px; font-weight: 600; }
.designer-advisory__cta { flex: none; font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.06em; text-transform: uppercase; border: 1px solid var(--border);
  padding: 3px 10px; color: var(--text-2); }
.designer-advisory__card { border: 1px solid var(--border); border-top: 0; background: var(--surface);
  padding: 12px; display: flex; flex-direction: column; gap: 10px; }
.designer-advisory__note { margin: 0; font-size: 12px; color: var(--text-2); }
.designer-advisory__rules { list-style: none; margin: 0; padding: 0; display: flex;
  flex-direction: column; gap: 6px; }
.designer-advisory__rule { border: 1px solid var(--border-lo); border-left-width: 4px;
  padding: 8px 10px; display: flex; flex-direction: column; gap: 4px; background: var(--surface-hi); }
.designer-advisory__rule.is-danger { border-left-color: var(--danger); background: color-mix(in srgb, var(--danger) 8%, var(--surface-hi)); }
.designer-advisory__rule.is-warning { border-left-color: var(--warning); background: color-mix(in srgb, var(--warning) 8%, var(--surface-hi)); }
.designer-advisory__rule.is-success { border-left-color: transparent; }
.designer-advisory__rule-head { display: flex; align-items: baseline; gap: 8px; }
.designer-advisory__rule-num { font-family: var(--font-mono); font-size: 11px; font-weight: 700;
  color: var(--text-3); flex: none; }
.designer-advisory__rule-title { font-size: 12.5px; font-weight: 600; color: var(--text-1); }
.designer-advisory__rule-detail { margin: 0; font-size: 11.5px; color: var(--text-2); }
.designer-advisory__rule-meta { display: flex; align-items: center; gap: 8px; }
.designer-advisory__citation { font-family: var(--font-mono); font-size: 10px; color: var(--brass);
  background: var(--brass-soft); padding: 1px 6px; }
.designer-advisory__badge { font-family: var(--font-mono); font-size: 10px; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--surface-hi); padding: 2px 8px; }
.designer-advisory__badge.is-danger { background: var(--danger); }
.designer-advisory__badge.is-warning { background: var(--warning); }
.designer-advisory__badge.is-success { background: var(--success); }
.designer-advisory__basis { margin: 0; font-family: var(--font-mono); font-size: 10px; color: var(--text-3); }
/* Fence street-frontage rows in the inspector reuse addon-row spacing. */
.designer-inspector__frontage { margin-bottom: 4px; }

/* ── Web Designer Phase 2 slice 2 — the EDIT-mode tool palette (Select / Draw ▸ / Polygon):
   a floating BLUEPRINT rail pinned inside the canvas, above the drawing surface. ── */
.designer-palette { position: absolute; top: 12px; left: 12px; z-index: 2;
  display: flex; flex-direction: column; border: 1px solid var(--border); background: var(--surface);
  box-shadow: 0 1px 0 var(--border-lo); }
.designer-palette[hidden] { display: none; }
.designer-palette__btn { appearance: none; border: 0; background: transparent; cursor: pointer;
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-2); padding: 8px 12px; text-align: left; min-width: 84px; }
.designer-palette__btn + .designer-palette__btn { border-top: 1px solid var(--border-lo); }
.designer-palette__btn:hover { color: var(--text-1); background: var(--surface-hi); }
.designer-palette__btn.is-active { background: var(--brass); color: var(--surface-hi); }
.designer-palette__select { margin: 0; border: 0; border-top: 1px solid var(--border-lo);
  background: var(--surface); font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-2); padding: 7px 10px; cursor: pointer; }
.designer-palette__select[hidden] { display: none; }

/* ── Web Designer Phase 2 slice 3 — the config INSPECTOR (option-schema chips + stairs +
   per-structure lines) at the top of the rail; SOLD badges on locked work orders. ── */
.designer-inspector { border-bottom: 1px solid var(--border); padding: 0 0 12px; margin: 0 0 12px; }
.designer-inspector[hidden] { display: none; }
.designer-inspector__head { display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; margin: 0 0 4px; }
.designer-inspector__title { font-family: var(--font-display); font-weight: 700; font-size: 13.5px;
  text-transform: capitalize; }
.designer-inspector__badge, .designer-wo__badge { font-family: var(--font-mono); font-size: 9.5px;
  letter-spacing: 0.08em; color: var(--surface-hi); background: var(--text-1);
  padding: 2px 6px; white-space: nowrap; }
.designer-inspector__section { margin: 10px 0 0; }
.designer-inspector__label { margin: 0 0 5px; font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-3); font-weight: 600; }
.designer-inspector__chips { display: flex; flex-wrap: wrap; gap: 4px; }
.designer-chip { appearance: none; cursor: pointer; border: 1px solid var(--border);
  background: var(--surface); color: var(--text-2); font-family: var(--font-mono); font-size: 10.5px;
  letter-spacing: 0.04em; padding: 4px 8px; }
.designer-chip:hover:not(:disabled) { color: var(--text-1); background: var(--surface-hi); }
.designer-chip.is-active { background: var(--brass); border-color: var(--brass); color: var(--surface-hi); }
.designer-chip:disabled { cursor: default; opacity: 0.55; }
.designer-inspector__select { width: 100%; border: 1px solid var(--border); background: var(--surface);
  font-family: var(--font-mono); font-size: 11px; color: var(--text-1); padding: 5px 6px; }
.designer-inspector__stairs { list-style: none; margin: 0 0 6px; padding: 0; }
.designer-inspector__stair { display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; padding: 3px 0; font-size: 12px; color: var(--text-2); font-family: var(--font-mono); }
.designer-inspector__remove { appearance: none; border: 0; background: transparent; cursor: pointer;
  color: var(--danger); font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.04em;
  text-transform: uppercase; padding: 0; }
.designer-inspector__remove:hover { text-decoration: underline; }
.designer-inspector__add-stairs { width: 100%; text-align: center; }
.designer-inspector__hint { margin: 0; font-size: 12px; color: var(--text-3); }
/* Rich material picker + addons + height (Phase 3). Swatch dots carry catalog hexes (data). */
/* PP UX-B #9 — the "Browse materials" entry point (replaces the old brand/line <select> pair,
   which is why designer-inspector__select--line — that pair's line-select modifier — is gone). */
.designer-material-btn { display: flex; align-items: center; gap: 8px; width: 100%;
  appearance: none; cursor: pointer; text-align: left; border: 1px solid var(--border);
  background: var(--surface); padding: 6px 8px; margin-bottom: 6px; }
.designer-material-btn:hover:not(:disabled) { background: var(--surface-hi); }
.designer-material-btn:disabled { cursor: default; opacity: 0.55; }
.designer-material-btn__swatch { width: 28px; height: 28px; flex: none; border: 1px solid var(--border); }
.designer-material-btn__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.designer-material-btn__brand { font-size: 12px; font-weight: 600; color: var(--text-1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.designer-material-btn__line { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.designer-material-btn__chevron { flex: none; color: var(--text-3); font-size: 14px; }
.designer-chip--swatch { display: inline-flex; align-items: center; gap: 5px; }
.designer-chip__dot { width: 10px; height: 10px; border: 1px solid var(--border); flex: none; }
.designer-chip.is-active .designer-chip__dot { border-color: var(--surface-hi); }
.designer-inspector__field { display: flex; align-items: center; gap: 6px; }
.designer-inspector__number { width: 64px; border: 1px solid var(--border); background: var(--surface);
  font-family: var(--font-mono); font-size: 11px; color: var(--text-1); padding: 4px 6px; }
.designer-inspector__number--qty { width: 52px; }
.designer-inspector__unit { font-family: var(--font-mono); font-size: 10px; color: var(--text-3);
  letter-spacing: 0.04em; }
.designer-inspector__addons { display: flex; flex-direction: column; gap: 4px; }
.designer-inspector__addon { display: flex; align-items: center; gap: 6px; }
.designer-inspector__addon .designer-chip { flex: 1; text-align: left; }
/* Wave B1 — name/group fields, duplicate action, stair editor card, IRC advisory. */
.designer-inspector__text { width: 100%; border: 1px solid var(--border); background: var(--surface);
  font-family: var(--font-mono); font-size: 11px; color: var(--text-1); padding: 4px 6px; }
.designer-inspector__text + .designer-inspector__text { margin-top: 4px; }
.designer-inspector__duplicate { color: var(--text-3); }
.designer-inspector__duplicate:hover { color: var(--text-1); }
.designer-inspector__stair--editor { display: flex; flex-direction: column; align-items: stretch;
  gap: 5px; border: 1px solid var(--border-lo); padding: 6px; margin: 0 0 6px; }
.designer-inspector__stair-head { display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; }
.designer-inspector__hint--warn { color: var(--danger); }
/* Checkpoint history drawer + good/better/best variant chips (Phase 3, D-25). */
.designer-wo__history-btn { appearance: none; cursor: pointer; border: 1px solid var(--border);
  background: transparent; color: var(--text-3); font-family: var(--font-mono); font-size: 9.5px;
  letter-spacing: 0.06em; text-transform: uppercase; padding: 2px 6px; }
.designer-wo__history-btn:hover { color: var(--text-1); background: var(--surface-hi); }
.designer-wo__history-btn.is-active { background: var(--brass); border-color: var(--brass);
  color: var(--surface-hi); }
.designer-variants { display: flex; flex-wrap: wrap; gap: 4px; margin: 4px 0 6px; }
.designer-variants__chip:disabled { opacity: 1; }
.designer-variants__chip:disabled:not(.is-active) { opacity: 0.55; }
.designer-history { border-top: 1px dashed var(--border); margin-top: 8px; padding-top: 8px; }
.designer-history__create { display: flex; gap: 6px; margin-bottom: 8px; }
.designer-history__name { flex: 1; min-width: 0; border: 1px solid var(--border);
  background: var(--surface); font-family: var(--font-mono); font-size: 11px; color: var(--text-1);
  padding: 4px 6px; }
.designer-history__list { list-style: none; margin: 0; padding: 0; }
.designer-history__entry { padding: 5px 0; border-bottom: 1px dotted var(--border); }
.designer-history__entry:last-child { border-bottom: 0; }
.designer-history__line { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.designer-history__when { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-2); }
.designer-history__price { font-family: var(--font-mono); font-size: 11px; color: var(--text-1); }
.designer-history__meta { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; margin-top: 2px; }
.designer-history__badge { font-family: var(--font-mono); font-size: 8.5px; letter-spacing: 0.08em;
  border: 1px solid var(--border); color: var(--text-3); padding: 1px 4px; text-transform: uppercase; }
.designer-history__badge--current { border-color: var(--brass); color: var(--brass); }
.designer-history__badge--sent { border-color: var(--ok, var(--border)); color: var(--text-2); }
.designer-history__badge--name { color: var(--text-1); }
.designer-history__materials { font-family: var(--font-mono); font-size: 9.5px; color: var(--text-3); }
.designer-history__restore { margin-left: auto; color: var(--brass); }
.designer-history__wo-link { display: inline-block; margin-top: 6px; font-family: var(--font-mono);
  font-size: 10px; letter-spacing: 0.04em; color: var(--text-2); text-decoration: none;
  text-transform: uppercase; }
.designer-history__wo-link:hover { color: var(--brass); }

/* ── Designer: gate-review drawer (CAD-WEB-1 §6, Phase 4) ─────────────────── */
.designer-gates { border-top: 1px dashed var(--border); margin-top: 8px; padding-top: 8px; }
.designer-gates__ladder { list-style: none; margin: 0 0 8px; padding: 0; display: flex; flex-wrap: wrap; gap: 3px; }
.designer-gates__rung { font-family: var(--font-mono); font-size: 8.5px; letter-spacing: 0.06em;
  text-transform: uppercase; border: 1px solid var(--border); color: var(--text-3); padding: 2px 5px;
  background: var(--surface-lo); }
.designer-gates__rung.is-granted { border-color: var(--success); color: var(--success); background: var(--surface); }
.designer-gates__rung.is-current { border-color: var(--brass); color: var(--brass); font-weight: 600; }
/* PP P-B follow-up — the "Permit packet" row (download / generate / not-yet-approved states). */
.designer-gates__packet { margin-bottom: 8px; }
.designer-gates__packet-row { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.designer-gates__packet-meta { font-family: var(--font-mono); font-size: 9.5px; color: var(--text-3); }
.designer-gates__run { display: flex; gap: 6px; margin-bottom: 8px; align-items: center; }
.designer-gates__level { border: 1px solid var(--border); background: var(--surface);
  font-family: var(--font-mono); font-size: 11px; color: var(--text-1); padding: 3px 4px; flex: 1; min-width: 0; }
.designer-gates__group { margin-bottom: 6px; }
.designer-gates__group-title { margin: 0 0 3px; font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-2); }
.designer-gates__list { list-style: none; margin: 0; padding: 0; }
.designer-gates__evaluation { padding: 4px 0; border-bottom: 1px dotted var(--border); }
.designer-gates__evaluation:last-child { border-bottom: 0; }
.designer-gates__evaluation-head { display: flex; width: 100%; align-items: baseline; gap: 8px;
  justify-content: space-between; background: none; border: 0; padding: 0; cursor: pointer; text-align: left; }
.designer-gates__chip { font-family: var(--font-mono); font-size: 8.5px; letter-spacing: 0.08em;
  border: 1px solid var(--border); color: var(--text-3); padding: 1px 4px; text-transform: uppercase; }
.designer-gates__chip--pass { border-color: var(--success); color: var(--success); }
.designer-gates__chip--warn { border-color: var(--warning); color: var(--warning); }
.designer-gates__chip--fail { border-color: var(--danger); color: var(--danger); }
.designer-gates__decision { margin: 2px 0 0; font-family: var(--font-mono); font-size: 10px; color: var(--text-2); }
.designer-gates__evidence { list-style: none; margin: 6px 0 0; padding: 0 0 0 8px; border-left: 2px solid var(--border-lo); }
.designer-gates__evidence-row { padding: 4px 0; }
.designer-gates__evidence-row--fail { background: rgba(194,54,43,0.06); }
.designer-gates__evidence-head { display: flex; align-items: baseline; gap: 6px; justify-content: space-between; }
.designer-gates__req { font-family: var(--font-mono); font-size: 10px; color: var(--text-1);
  overflow-wrap: anywhere; }
.designer-gates__message { margin: 2px 0 0; font-size: 11px; color: var(--text-2); }
.designer-gates__evidence-meta { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 2px;
  font-family: var(--font-mono); font-size: 9.5px; color: var(--text-3); }
.designer-gates__evidence-meta a { color: var(--brass); text-decoration: none; }
.designer-gates__evidence-meta a:hover { text-decoration: underline; }
.designer-gates__actions { display: flex; gap: 6px; margin-top: 6px; align-items: center; }
.designer-gates__approve { border-color: var(--success); color: var(--success); }
.designer-gates__reject { border-color: var(--danger); color: var(--danger); }
.designer-gates__role-note { font-family: var(--font-mono); font-size: 9.5px; color: var(--text-3);
  text-transform: uppercase; letter-spacing: 0.06em; }

/* ── Designer: material-trace drawer (CAD-WEB-1 §7, Phase 4) ──────────────── */
.designer-trace { border-top: 1px dashed var(--border); margin-top: 8px; padding-top: 8px; }
.designer-trace__chain { display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; margin-bottom: 6px; }
.designer-trace__product { font-family: var(--font-mono); font-size: 11px; color: var(--text-1); font-weight: 600; }
.designer-trace__rule { font-family: var(--font-mono); font-size: 9.5px; color: var(--text-3); }
.designer-trace__rule--manual { color: var(--warning); }
.designer-trace__table { width: 100%; border-collapse: collapse; font-size: 11px; }
.designer-trace__table th { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-3); text-align: left; padding: 2px 4px;
  border-bottom: 1px solid var(--border); }
.designer-trace__table td { padding: 3px 4px; border-bottom: 1px dotted var(--border-lo); color: var(--text-2); }
.designer-trace__table td:first-child { color: var(--text-1); }
.designer-trace__table .num { text-align: right; font-family: var(--font-mono); }
.designer-trace__bom { margin-top: 10px; }
/* POL-12/20 — the 3D pending/failed notice pinned over the scene (BLUEPRINT parchment card). */
.designer-3d-note { position: absolute; top: 12px; left: 50%; transform: translateX(-50%);
  max-width: min(520px, calc(100% - 24px)); padding: 6px 10px; z-index: 4;
  background: var(--surface-hi); border: 1px solid var(--border); box-shadow: var(--shadow-lift);
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.02em; color: var(--text-2);
  text-align: center; pointer-events: none; }
.designer-trace__bom-total td { border-top: 1px solid var(--border); border-bottom: 0; color: var(--text-1); font-weight: 600; }

/* ── PP UX-C (POL-15 Phase 2) — the canvas ACCESSIBILITY overlay (iPad structureAccessibilityLayer):
   invisible, focusable per-structure/per-marker proxies positioned over their screen boxes. The whole
   layer is pointer-events:none so the raw canvas keeps the mouse; the proxies stay keyboard-focusable
   (pointer-events doesn't remove them from the tab order). A keyboard focus ring is the only visible
   trace — drawn via :focus-visible so a programmatic focus-follow after a mouse click stays quiet. ── */
.designer-a11y { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.designer-a11y[hidden] { display: none; }
.designer-a11y__target { position: absolute; top: 0; left: 0; margin: 0; padding: 0; border: 0;
  background: transparent; -webkit-appearance: none; appearance: none; color: transparent;
  font: inherit; cursor: default; }
.designer-a11y__target:focus { outline: none; }
.designer-a11y__target:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
/* Help text + polite live region — in the a11y tree, off the visible sheet (shared sr-only recipe). */
.designer-a11y__hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ── Web Designer Wave B3 — the LAYERS drawer (structures + nested items + annotations):
   a floating BLUEPRINT panel pinned inside the canvas, opposite the tool palette. ── */
.designer-layers { position: absolute; top: 12px; right: 12px; z-index: 2; width: 240px;
  max-height: calc(100% - 24px); overflow-y: auto; border: 1px solid var(--border);
  background: var(--surface); box-shadow: 0 1px 0 var(--border-lo); padding: 10px 12px; }
.designer-layers[hidden] { display: none; }
.designer-layers__title { margin: 0 0 6px; font-family: var(--font-mono); font-size: 10.5px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-3); font-weight: 600; }
.designer-layers__group { margin: 8px 0 0; }
.designer-layers__row { display: flex; align-items: baseline; gap: 6px; padding: 2px 0; }
.designer-layers__row--sub { padding-left: 14px; }
.designer-layers__row.is-selected .designer-layers__name { color: var(--brass); font-weight: 700; }
.designer-layers__name { appearance: none; border: 0; background: transparent; cursor: pointer;
  flex: 1; text-align: left; font-family: var(--font-mono); font-size: 11px; color: var(--text-2);
  padding: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.designer-layers__name:hover { color: var(--text-1); }

/* ── Web Designer Wave C2 — in-designer Send Estimate (brass CTA + confirm sheet) ── */
.designer-send-cta { appearance: none; cursor: pointer; border: 1px solid var(--brass-lo);
  background: var(--brass-cta); color: #fff;
  font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; padding: 7px 14px; box-shadow: 3px 3px 0 rgba(22,32,43,0.18); }
.designer-send-cta:hover { filter: brightness(1.05); }
.designer-send-cta:active { transform: translate(1px,1px); box-shadow: 2px 2px 0 rgba(22,32,43,0.12); }
.designer-send[hidden] { display: none; }
.designer-send__backdrop { position: fixed; inset: 0; z-index: 60; background: rgba(22,32,43,0.35); }
.designer-send__card { position: fixed; z-index: 61; top: 50%; left: 50%;
  transform: translate(-50%, -50%); width: min(440px, calc(100vw - 32px));
  max-height: min(80vh, 640px); overflow-y: auto;
  border: 1.5px solid var(--text-1); background: var(--surface); padding: 16px 18px;
  box-shadow: 6px 6px 0 rgba(22,32,43,0.22); }
.designer-send__title { margin: 0 0 10px; font-family: var(--font-display); font-weight: 700;
  font-size: 16px; }
.designer-send__sections { list-style: none; margin: 0; padding: 0; }
.designer-send__section { border-top: 1px solid var(--border-lo); padding: 8px 0; }
.designer-send__section:first-child { border-top: 0; padding-top: 0; }
.designer-send__section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.designer-send__trade { font-family: var(--font-display); font-weight: 700; font-size: 13.5px; }
.designer-send__price { font-family: var(--font-mono); font-weight: 600; white-space: nowrap; }
.designer-send__note { margin: 3px 0 0; font-size: 12px; color: var(--text-2); }
.designer-send__note--minimum { color: var(--brass); font-family: var(--font-mono); font-size: 11px; }
.designer-send__total-row { display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; border-top: 1.5px solid var(--text-1); margin-top: 8px; padding-top: 8px; }
.designer-send__total-label { font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-3); font-weight: 600; }
.designer-send__total { margin: 0; font-family: var(--font-mono); font-weight: 700; font-size: 16px; }
.designer-send__customer { margin: 8px 0 0; font-size: 12.5px; color: var(--text-2); }
.designer-send__warn { margin: 8px 0 0; font-size: 12px; color: var(--warning);
  border: 1px solid var(--warning); padding: 6px 8px; }
.designer-send__error { margin: 8px 0 0; font-size: 12px; color: var(--danger);
  border: 1px solid var(--danger); padding: 6px 8px; }
.designer-send__actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }
.designer-send__btn { appearance: none; cursor: pointer; border: 1px solid var(--border);
  background: var(--surface); color: var(--text-1); font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.06em; text-transform: uppercase; padding: 7px 12px; text-decoration: none;
  display: inline-flex; align-items: center; }
.designer-send__btn:hover:not(:disabled) { background: var(--surface-hi); }
.designer-send__btn:disabled { color: var(--text-3); cursor: default; }
.designer-send__btn--primary { background: var(--brass-cta); color: #fff;
  border-color: var(--brass-lo); font-weight: 700; box-shadow: 3px 3px 0 rgba(22,32,43,0.18); }
.designer-send__btn--primary:hover:not(:disabled) { filter: brightness(1.05); background: var(--brass-cta); }
.designer-send__btn--primary:disabled { opacity: 0.5; box-shadow: none; }

/* ── PP UX-B #9 — the searchable material browser sheet (iPad MaterialBrowserSheet parity).
   Same modal discipline as designer-send (backdrop + fixed card); a taller/wider card since
   it's a browse-and-search surface, not a confirm dialog. ── */
.designer-material[hidden] { display: none; }
.designer-material__backdrop { position: fixed; inset: 0; z-index: 70; background: rgba(22,32,43,0.35); }
.designer-material__card { position: fixed; z-index: 71; top: 50%; left: 50%;
  transform: translate(-50%, -50%); width: min(420px, calc(100vw - 32px));
  max-height: min(78vh, 620px); overflow-y: auto; display: flex; flex-direction: column;
  border: 1.5px solid var(--text-1); background: var(--surface); padding: 16px 18px;
  box-shadow: 6px 6px 0 rgba(22,32,43,0.22); }
.designer-material__header { display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 10px; }
.designer-material__title { margin: 0; font-family: var(--font-display); font-weight: 700; font-size: 16px; }
.designer-material__close { appearance: none; cursor: pointer; border: 1px solid var(--border);
  background: var(--surface); color: var(--text-2); font-size: 16px; line-height: 1;
  width: 28px; height: 28px; flex: none; }
.designer-material__close:hover { background: var(--surface-hi); color: var(--text-1); }
.designer-material__search { border: 1px solid var(--border); background: var(--surface-hi);
  font-family: var(--font-mono); font-size: 12px; color: var(--text-1); padding: 7px 8px;
  margin-bottom: 10px; }
.designer-material__list { flex: 1; min-height: 0; overflow-y: auto; }
.designer-material__brand + .designer-material__brand { margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--border-lo); }
.designer-material__brand-name { margin: 0 0 4px; font-family: var(--font-mono); font-size: 10.5px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-3); font-weight: 600; }
.designer-material__brand-name[hidden], .designer-material__brand[hidden] { display: none; }
.designer-material__line { display: flex; align-items: center; gap: 10px; width: 100%;
  appearance: none; cursor: pointer; text-align: left; border: 0; border-radius: var(--r-sm);
  background: transparent; padding: 6px 4px; color: var(--text-1); font-size: 13px; }
.designer-material__line:hover { background: var(--surface-hi); }
.designer-material__line.is-current { color: var(--brass); font-weight: 600; }
.designer-material__line[hidden] { display: none; }
.designer-material__swatches { display: inline-flex; flex: none; }
.designer-material__swatch { width: 22px; height: 22px; border-radius: 50%;
  border: 1.5px solid var(--surface); margin-left: -6px; }
.designer-material__swatch:first-child { margin-left: 0; }
.designer-material__line-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.designer-material__check { flex: none; color: var(--brass); font-weight: 700; }

/* ── Web Designer Wave C2 — custom line items in the rail (add form + per-line remove) ── */
.designer-wo__line-remove { appearance: none; border: 0; background: transparent; cursor: pointer;
  color: var(--danger); font-size: 13px; line-height: 1; padding: 0 0 0 2px; flex: none; }
.designer-wo__line-remove:hover { transform: scale(1.2); }
.designer-wo__custom-toggle { margin-top: 6px; }
.designer-wo__custom-form { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.designer-wo__custom-input { flex: 1 1 100%; border: 1px solid var(--border); background: var(--surface);
  font-family: var(--font-mono); font-size: 11px; color: var(--text-1); padding: 5px 6px; }
.designer-wo__custom-amount { flex: 0 1 84px; }
.designer-wo__custom-scope { flex: 1 1 auto; min-width: 0; border: 1px solid var(--border);
  background: var(--surface); font-family: var(--font-mono); font-size: 11px; color: var(--text-1);
  padding: 4px 5px; }
.designer-wo__custom-add { flex: none; }

/* ═══════════════════════════════════════════════════════════════════════
   Web Designer Wave D1 — FULL MOBILE (owner decision 2026-07-11, POL-11).
   Three tiers: desktop >1100px (layout unchanged; the header just wraps
   BETWEEN control groups instead of mid-chip), tablet 768–1100px (full-width
   canvas, rail = right slide-over), phone <768px (app frame: compact top
   bar, full-bleed canvas, rail = bottom sheet with peek/half/full snaps,
   reduced palette, session bar). BLUEPRINT tokens only.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Base (all widths): new chrome idle on desktop + wrap-safe header ──── */
.designer__back { display: none; }
.designer-rail-toggle { display: none; }
.designer__rail-close { display: none; }
.designer-sheet-grip { display: none; }
.designer-palette__more { display: none; }
.designer-overflow { display: none; position: relative; }
/* POL-11 (desktop half): at 1280px in EDIT the head used to wrap mid-chip —
   let the groups wrap whole, keep the title from shoving the tools around. */
.designer__head { flex-wrap: wrap; row-gap: 8px; }
.designer__id { min-width: 0; }
.designer__title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.designer__tools { flex-wrap: wrap; row-gap: 8px; justify-content: flex-end; }
.designer__status { max-width: 340px; }

/* The touch session bar (v2 MobileSessionBar): shown by the controller only on
   coarse-pointer devices during a draw/placement session — Done / Undo point /
   Cancel replace Enter / Backspace / Esc. Dark HUD so it reads as transient. */
.designer-session { position: fixed; z-index: 29; display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; background: var(--nav-bg); border: 1px solid var(--nav-border);
  color: var(--nav-text-hi); left: 50%; transform: translateX(-50%); bottom: 16px;
  max-width: min(560px, calc(100vw - 24px)); box-shadow: 4px 4px 0 rgba(22,32,43,0.18); }
.designer-session[hidden] { display: none; }
.designer-session__dot { width: 8px; height: 8px; flex: none; background: var(--brass); }
.designer-session__hint { flex: 1; min-width: 0; font-family: var(--font-mono); font-size: 11px;
  color: var(--nav-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.designer-session__btn { appearance: none; cursor: pointer; flex: none;
  border: 1px solid var(--nav-border); background: var(--nav-mid); color: var(--nav-text-hi);
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 10px 12px; min-height: 44px; }
.designer-session__btn--primary { background: var(--brass-cta); border-color: var(--brass-lo);
  color: #fff; font-weight: 700; }

/* The overflow menu (phone top bar): Framing / Fit / Layers / Export / Send /
   sheet-full. Popover under the ⋯ button, BLUEPRINT card treatment. */
.designer-overflow__btn { font-size: 16px; line-height: 1; min-height: 40px;
  border: 1px solid var(--border); background: var(--surface); }
.designer-overflow__btn[aria-expanded="true"] { background: var(--brass); color: var(--surface-hi); }
.designer-overflow__menu { position: absolute; right: 0; top: calc(100% + 6px); z-index: 50;
  min-width: 210px; border: 1.5px solid var(--text-1); background: var(--surface);
  box-shadow: 4px 4px 0 rgba(22,32,43,0.18); display: flex; flex-direction: column; }
.designer-overflow__menu[hidden] { display: none; }
.designer-overflow__item { appearance: none; text-align: left; border: 0; background: transparent;
  cursor: pointer; font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text-1); padding: 13px 14px; min-height: 44px; }
.designer-overflow__item + .designer-overflow__item { border-top: 1px solid var(--border-lo); }
.designer-overflow__item:hover { background: var(--surface-hi); }
.designer-overflow__item.is-active { color: var(--brass); font-weight: 700; }

/* The Layers drawer's close row — rendered by the controller on phone only. */
.designer-layers__close { appearance: none; cursor: pointer; width: 100%; margin: 0 0 8px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-2);
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 11px 12px; min-height: 44px; }
.designer-layers__close:hover { background: var(--surface-hi); color: var(--text-1); }

/* ── Tablet 768–1100px: full-width canvas, rail = right slide-over ─────── */
@media (min-width: 768px) and (max-width: 1100px) {
  .designer__body { grid-template-columns: minmax(0, 1fr); }
  .designer__rail { position: fixed; top: 0; right: 0; bottom: 0; z-index: 40;
    width: min(380px, 92vw); height: 100vh; border-radius: 0;
    border-top: 0; border-bottom: 0; border-right: 0;
    display: flex; flex-direction: column; overflow: hidden;
    transform: translateX(100%); transition: transform .18s ease; }
  .designer__rail.is-open { transform: none; box-shadow: -6px 0 0 rgba(22,32,43,0.14); }
  .designer__rail-scroll { flex: 1; min-height: 0; overflow-y: auto; }
  .designer__rail-close { display: grid; place-items: center; position: absolute;
    top: 8px; right: 10px; width: 32px; height: 32px; z-index: 1; appearance: none; cursor: pointer;
    border: 1px solid var(--border); background: var(--surface); color: var(--text-2);
    font-size: 16px; line-height: 1; }
  .designer__rail-close:hover { background: var(--surface-hi); color: var(--text-1); }
  /* Keep the inspector head clear of the close button. */
  .designer__rail-scroll { padding-right: 4px; }
  .designer-inspector__head { padding-right: 34px; }
  .designer-rail-toggle { display: inline-block; }
  .designer-rail-toggle[aria-pressed="true"] { border-color: var(--brass); color: var(--brass); }
}

/* ── Phone <768px: the designer becomes an app frame ───────────────────── */
@media (max-width: 767px) {
  /* The designer page owns the viewport — office chrome stands down (scoped:
     every other office page keeps the responsive shell it already has). */
  .office-shell:has(.designer) .office-side,
  .office-shell:has(.designer) .office-topbar { display: none; }
  .office-shell:has(.designer) .office-content { padding: 0; }
  .office-shell:has(.designer) .backlink { display: none; }
  /* Toasts span the top of the phone frame (right-pinned cards overflowed). */
  body:has(.designer) .toast-stack { left: 12px; right: 12px; top: 12px; }

  .designer { --dh-sheet-peek: 96px;
    position: fixed; inset: 0; z-index: 20; display: flex; flex-direction: column;
    gap: 0; background: var(--bg); overscroll-behavior: contain; }

  /* Compact top bar: back · P-code · name · save — then the control row. */
  .designer__head { flex: none; flex-direction: column; align-items: stretch; gap: 8px;
    padding: 8px 10px; border-bottom: 1px solid var(--border); background: var(--surface); }
  .designer__id { display: flex; align-items: center; gap: 8px; }
  .designer__back { display: inline-flex; align-items: center; color: var(--text-2);
    padding: 6px; margin: -6px 0 -6px -6px; }
  .designer__back:hover { color: var(--text-1); }
  .designer__title { font-size: 15px; flex: 0 1 auto; }
  .designer__mode { display: none; } /* the Edit button carries the state */
  .designer-save { margin-left: auto; }
  .designer__status { display: none; } /* the session bar carries tool hints */
  .designer__tools { display: flex; justify-content: flex-start; gap: 8px; }
  /* The undo/redo seg is an empty 2px sliver outside edit mode — hide the shell too. */
  .designer-seg--history:not(:has(.designer-seg__btn:not([hidden]))) { display: none; }
  .designer__tools .designer-seg__btn { min-height: 40px; padding: 8px 12px; }
  .designer-overflow { display: block; margin-left: auto; }
  .designer-seg--scene, .designer-seg--viewport, .designer-send-cta { display: none; }
  .designer-dims { order: 10; flex: 1 1 100%; justify-content: center; }
  .designer-dims__input { width: 64px; min-height: 36px; font-size: 14px; }

  .designer-banner { flex-wrap: wrap; margin: 6px 8px 0; }
  .designer-advisories { margin: 6px 8px 0; }

  /* Full-bleed canvas above the sheet's peek strip. */
  .designer__body { flex: 1; min-height: 0; display: block; }
  .designer__canvas { height: calc(100% - var(--dh-sheet-peek)); min-height: 0;
    border: 0; border-bottom: 1px solid var(--border); border-radius: 0; box-shadow: none; }

  /* The estimate rail presents as the bottom sheet (peek / half / full). The
     resting snaps are classes; the drag sets an inline transform (JS). */
  .designer__rail { position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: 30;
    height: 88dvh; width: auto; padding: 0; border-radius: 0;
    border: 1px solid var(--border); border-bottom: 0;
    display: flex; flex-direction: column; overflow: hidden;
    box-shadow: 0 -4px 0 rgba(22,32,43,0.10);
    transform: translateY(calc(100% - var(--dh-sheet-peek)));
    transition: transform .2s ease; }
  .designer__rail.is-half { transform: translateY(48%); } /* 52% visible — mobile_sheet.ts */
  .designer__rail.is-full { transform: translateY(0); }
  .designer__rail.is-dragging { transition: none; }
  .designer-sheet-grip { display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 8px; flex: none; width: 100%; height: var(--dh-sheet-peek); appearance: none; border: 0;
    border-bottom: 1px solid var(--border-lo); background: transparent; cursor: grab;
    padding: 10px 14px; touch-action: none; }
  .designer-sheet-grip__bar { width: 44px; height: 4px; background: var(--border); }
  .designer-sheet-grip__peek { font-family: var(--font-mono); font-size: 12px; color: var(--text-1);
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .designer__rail-scroll { flex: 1; min-height: 0; overflow-y: auto;
    padding: 10px 14px calc(24px + env(safe-area-inset-bottom)); }

  /* Session bar rides just above the peek strip, full width. */
  .designer-session { left: 0; right: 0; bottom: var(--dh-sheet-peek); transform: none;
    max-width: none; border-left: 0; border-right: 0; }

  /* Reduced palette: Select / Draw ▾ / Measure — the Draw menu expands the rest. */
  .designer-palette { top: 8px; left: 8px; max-height: calc(100% - 16px); overflow-y: auto; }
  .designer-palette__btn { min-height: 44px; min-width: 100px; font-size: 11.5px; }
  .designer-palette__select { min-height: 44px; font-size: 11.5px; }
  .designer-palette__more { display: block; }
  .designer-palette:not(.is-open)
    .designer-palette__btn[data-cad-designer-tool-param]:not([data-cad-designer-tool-param="select"]):not([data-cad-designer-tool-param="measure"]) {
    display: none; }

  /* Finger-sized widgets in the sheet (44px targets). */
  .designer-chip { min-height: 44px; padding: 8px 12px; font-size: 12px; }
  .designer-inspector__select, .designer-inspector__select--line,
  .designer-wo__custom-scope, .designer-gates__level { min-height: 44px; font-size: 12px; }
  .designer-inspector__number, .designer-inspector__text, .designer-history__name,
  .designer-wo__custom-input { min-height: 40px; font-size: 13px; }
  .designer-inspector__remove, .designer-wo__line-remove { padding: 8px; }
  .designer-wo__history-btn { padding: 6px 8px; }
  .designer-layers__row { min-height: 44px; align-items: center; }

  /* Drawers that float over the canvas go full-screen sheets on phone. */
  .designer-layers { position: fixed; inset: 0; width: auto; max-height: none; z-index: 45;
    padding: 14px; }

  /* The send-estimate confirm presents as a bottom sheet. */
  .designer-send__card { top: auto; bottom: 0; left: 0; right: 0; transform: none;
    width: 100%; max-height: 82dvh; border-left: 0; border-right: 0; border-bottom: 0;
    padding-bottom: calc(16px + env(safe-area-inset-bottom)); }
  .designer-send__btn { min-height: 44px; }

  /* PP UX-B #9 — the material browser is a browse-and-search surface (needs the room a bottom
     sheet doesn't give), so it goes full-screen like the Layers drawer rather than half-height. */
  .designer-material__card { position: fixed; inset: 0; z-index: 71; width: auto; max-height: none;
    transform: none; border: 0; padding: 14px 14px calc(14px + env(safe-area-inset-bottom)); }
  .designer-material__line { min-height: 44px; }
  .designer-material__close { width: 44px; height: 44px; }
}

@media (prefers-reduced-motion: reduce) {
  .designer__rail { transition: none; }
}
