/* UI-02-B: Inter variable, self-hosted. Variable axis gives us every
   weight 100-900 from a single ~344KB file (vs. 4-6 individual files
   for static cuts). font-display:swap so we never block first paint
   waiting on the font — system font shows first, Inter swaps in.
   Files live under /fonts/, served by express.static. Source: rsms.me/inter. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/InterVariable.woff2") format("woff2-variations"),
       url("/fonts/InterVariable.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/InterVariable-Italic.woff2") format("woff2-variations"),
       url("/fonts/InterVariable-Italic.woff2") format("woff2");
}

* { box-sizing: border-box; }
:root {
  /* Signarama brand */
  --brand-red: #E11B22;        /* UI-02-A: brighter Signarama red (was #C8102E) */
  --brand-red-dark: #B0151B;
  --brand-ink: #1F2937;        /* UI-02-A: charcoal — better contrast on slate bg */
  /* Action color stays blue so it doesn't collide with PRIORITY red */
  --action-blue: #16C7C9;
  --action-blue-dark: #12B6B8;

  /* UI-02-A: semantic palette — use these for status meaning, not the
     brand red. Brand red is reserved for active nav / primary actions. */
  --semantic-green:   #10B981;  /* success, completed, on-track */
  --semantic-amber:   #F59E0B;  /* warning, in-progress, attention */
  --semantic-purple:  #8B5CF6;  /* scheduled, future-looking */
  --semantic-rose:    #F43F5E;  /* overdue, critical */

  /* UI-02-A: surface + text tokens. Page is slate-50, surfaces are pure
     white. Headings/body/muted form a 3-step text ladder. */
  --bg-page:      #F8FAFC;       /* slate-50 — app background */
  --bg-surface:   #FFFFFF;       /* cards, panels, modals */
  --bg-elevated:  #FFFFFF;       /* alias — explicit "this is raised" */
  --border-soft:  #E2E8F0;       /* slate-200 — default card borders */
  --border-strong: #CBD5E1;      /* slate-300 — emphasized borders */
  --text-heading: #0F172A;       /* slate-900 — h1/h2 */
  --text-body:    #1F2937;       /* charcoal — paragraph + values */
  --text-muted:   #64748B;       /* slate-500 — labels, meta, captions */
  --text-faint:   #94A3B8;       /* slate-400 — placeholder, empty */

  /* POLISH-01: design tokens (font / radius / shadow scales).
     Goal — one consistent ladder across the app. Pre-existing
     hardcoded values can migrate to these over time; new code
     should consume the tokens. See UI-REVIEW.md for the rationale. */

  /* Font scale — 6 steps. Anything outside this scale is an orphan. */
  --fs-xs:  11px;  /* labels, meta, badges, table headers */
  --fs-sm:  13px;  /* body small, controls, secondary text */
  --fs-md:  14px;  /* body, inputs, default button text */
  --fs-lg:  18px;  /* section headers */
  --fs-xl:  22px;  /* modal hero title + amount */
  --fs-2xl: 26px;  /* dashboard metric numbers */

  /* Radius scale — 4 steps + pill. UI-02-A added --r-xl for hero cards
     (KPI tiles, calendar surface) — distinct from --r-lg modal chrome. */
  --r-sm:   4px;   /* chips, dots, mini elements */
  --r-md:   8px;   /* default — cards, panels, inputs, buttons */
  --r-lg:   12px;  /* modal surfaces, larger panels */
  --r-xl:   16px;  /* hero cards — KPI tiles, calendar surface */
  --r-pill: 999px;

  /* Shadow scale — 4 steps. UI-02-A softened md/lg for the modern SaaS
     "barely there, but present" elevation look. */
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04);
  --shadow-md: 0 4px 12px rgba(15, 23, 42, 0.06);
  --shadow-lg: 0 8px 24px rgba(15, 23, 42, 0.08);
  --shadow-xl: 0 20px 60px rgba(15, 23, 42, 0.22);

  /* Empty-state color — for "no value yet" cells. */
  --cell-empty: #94a3b8;
}
body {
  /* UI-02-B: Inter is the primary face; system fallback covers the
     swap window. cv11/ss01 are stylistic-set features Inter ships —
     cv11 picks the single-storey 'a' that scans better on dashboards. */
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-feature-settings: "cv11", "ss01", "ss03";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  margin: 0;
  background: var(--bg-page);   /* UI-02-A: slate-50 (was #f5f6f8) */
  color: var(--text-body);
  /* Prevent any inner grid/table from pushing the page wider than the
     viewport on phones. Each scrollable region handles its own
     overflow internally instead. */
  overflow-x: hidden;
}
/* ============================================================
   UI-03-A: app shell — sidebar + main column layout.
   The whole app lives inside .app-shell. On desktop the sidebar
   sits left at 240px; on tablet collapses to icon-only (72px);
   on mobile hides entirely and reveals via #mobile-nav-toggle.
   ============================================================ */
.app-shell {
  display: flex;
  min-height: 100vh;
  width: 100%;
}
.app-main {
  flex: 1;
  min-width: 0;          /* prevents flex children from forcing horizontal scroll */
  display: flex;
  flex-direction: column;
}

/* ============================================================
   Sidebar
   ============================================================ */
.sidebar {
  width: 240px;
  flex-shrink: 0;
  background: var(--bg-surface);
  border-right: 1px solid var(--border-soft);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  padding: 0;
  z-index: 50;
}
.sidebar-brand {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px 16px;
  border-bottom: 1px solid var(--border-soft);
  text-decoration: none;
}
.sidebar-brand .brand-logo {
  height: 36px;
  width: auto;
  display: block;
}
.sidebar-nav {
  flex: 1;
  overflow-y: auto;
  padding: 12px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sidebar-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 12px;
  border: 0;
  background: transparent;
  border-radius: var(--r-md);
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--text-body);
  cursor: pointer;
  text-align: left;
  transition: background 0.12s ease, color 0.12s ease;
}
.sidebar-item:hover {
  background: var(--bg-page);
  color: var(--text-heading);
}
.sidebar-item.active {
  background: rgba(225, 27, 34, 0.08);  /* brand red 8% */
  color: var(--brand-red);
  font-weight: 600;
}
.sidebar-icon {
  width: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
}
.sidebar-label { flex: 1; }
.sidebar-tenant {
  padding: 14px 16px;
  border-top: 1px solid var(--border-soft);
}
.sidebar-tenant-name {
  font-size: var(--fs-md);
  font-weight: 700;
  color: var(--brand-red);
  line-height: 1.2;
}
.sidebar-tenant-loc {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  margin-bottom: 10px;
}
.sidebar-switch {
  width: 100%;
  border: 1px solid var(--border-soft);
  background: transparent;
  border-radius: var(--r-md);
  padding: 7px 10px;
  font-size: var(--fs-xs);
  color: var(--text-muted);
  cursor: pointer;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.sidebar-switch:hover {
  background: var(--bg-page);
  color: var(--text-heading);
  border-color: var(--border-strong);
}

/* BRAND: segmented Signarama / Fully Promoted switch in the sidebar. */
.brand-switch {
  display: flex;
  width: 100%;
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
  overflow: hidden;
}
.brand-switch .brand-opt {
  flex: 1;
  border: none;
  background: transparent;
  padding: 7px 8px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  white-space: nowrap;
}
.brand-switch .brand-opt + .brand-opt { border-left: 1px solid var(--border-soft); }
.brand-switch .brand-opt:hover { background: var(--bg-page); color: var(--text-heading); }
.brand-switch .brand-opt.active { background: var(--brand-red); color: #fff; }

/* BRAND-THEME: Fully Promoted turns the whole site blue so it's obvious which
   side you're on. Overriding the brand-accent variables recolors active nav,
   primary buttons, headers, the brand switch, etc.; a light-blue wash on the
   topbar reinforces it. (Exact blue can match the FP logo once it's provided.)
   The sidebar is NOT included here — it's a fixed dark Midnight shell shared
   by both brands (see the Signmetry design system below); its text colors
   assume that dark background, so tinting it light here would make sidebar
   text unreadable. */
body.brand-fp {
  --brand-red: #0E76BC;       /* Fully Promoted deep blue (matches the logo) */
  --brand-red-dark: #0A5A8F;
}
body.brand-fp .topbar { background: #eef6fc; border-bottom: 3px solid #29ABE2; } /* bright azure accent */
/* FP-INTAKE: on the Fully Promoted brand, focus the nav on job-process
   tracking — hide the calendar/install/stats/survey surfaces. Signarama is
   unaffected because the rule is scoped to body.brand-fp. */
body.brand-fp .fp-nav-hidden { display: none !important; }
/* FP-INTAKE: install/delivery SCHEDULING fields tagged .fp-hide-field are
   hidden on Fully Promoted job forms. We hide via this dedicated .fp-hidden
   marker (toggled by syncBrandFields) rather than the shared .hidden class,
   because several tagged elements (#job-ics-link, #linked-install-panel,
   #spawn-install-panel) carry their own independent .hidden logic — reusing
   .hidden would force-show them on the Signarama form. .fp-hidden is only ever
   present on FP, so Signarama's markup/behaviour is untouched. */
.fp-hidden { display: none !important; }

/* ============================================================
   Top bar — segmented tabs + search + actions
   Replaces the old body > header chrome. Wider, lighter, cleaner.
   ============================================================ */
.topbar {
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border-soft);
  padding: 12px 24px;
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 16px;
}
.topbar-nav {
  display: flex;
  align-items: center;
  gap: 16px;
  flex: 1;
  min-width: 0;
}
.topbar-tabs {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
}
.topbar-tabs .tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 0;
  padding: 8px 14px;
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: var(--r-md);
  position: relative;
  transition: color 0.12s ease, background 0.12s ease;
}
.topbar-tabs .tab:hover {
  color: var(--text-heading);
  background: var(--bg-page);
}
/* UI-03-A5: topbar active-tab treatment — clean Linear/GitHub/Notion
   style. No background block (the legacy POLISH-04 rule at line ~885
   tried to paint the whole tab red, which looked heavy). Instead:
   - Brand-red text, bolder weight
   - Brand-red icon tint
   - Slim 2px underline indicator flush with the topbar's bottom border
   Explicit !important on background + border because the legacy
   `button.tab.active` rule below is co-specific. */
.topbar-tabs .tab.active {
  color: var(--brand-red) !important;
  font-weight: 600;
  background: transparent !important;
  border: 0 !important;
}
.topbar-tabs .tab.active .tab-icon {
  opacity: 1;
}
/* The underline indicator — sits flush with the topbar's bottom border. */
.topbar-tabs .tab.active::after {
  content: '';
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: -13px;
  height: 2px;
  background: var(--brand-red);
  border-radius: 2px;
}
/* Hover for inactive tabs gets a soft slate pill so there's still
   a visible "I'm clickable" affordance without competing with
   the active red treatment. */
.topbar-tabs .tab:not(.active):hover {
  background: var(--bg-page);
}
.topbar-tabs .tab .tab-icon {
  font-size: 14px;
  opacity: 0.85;
}


/* UI-03-A13: honeypot fields — Chrome/Safari/1Password autofill these
   instead of the real search input. They must be in-tree (not
   display:none) so password managers see them as fillable, but
   positioned off-screen and zero-size so users never see them. */
.autofill-honeypot {
  position: absolute;
  left: -9999px;
  top: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
  z-index: -1;
}

/* Right-side action cluster */
.topbar-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  /* Used to ride the removed .topbar-search's flex:1 to the right edge —
     now the only child of .topbar-nav, so push it there directly. */
  margin-left: auto;
}
.topbar-manage-btn,
.topbar-new-btn {
  font-size: var(--fs-sm);
}
.topbar-new-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
}

/* User chip — avatar + name stacked */
.topbar-user {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-left: 10px;
  margin-left: 4px;
  border-left: 1px solid var(--border-soft);
}
.topbar-user-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--action-blue), var(--brand-red));
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-md);
  font-weight: 700;
  text-transform: uppercase;
  flex-shrink: 0;
}
.topbar-user-name {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
  font-size: var(--fs-sm);
}
.topbar-user-name .current-user {
  font-weight: 600;
  color: var(--text-heading);
}
.topbar-user-name .topbar-signout {
  background: transparent;
  border: 0;
  padding: 0;
  font-size: var(--fs-xs);
  color: var(--text-muted);
  cursor: pointer;
  text-align: left;
}
.topbar-user-name .topbar-signout:hover {
  color: var(--brand-red);
  text-decoration: underline;
}
.topbar-user-links { display: flex; align-items: center; gap: 5px; }
.topbar-user-sep { color: var(--text-muted); font-size: var(--fs-xs); }

/* Hide the legacy bottom red bar — the active tab's red underline now
   carries the brand accent. */
body > header {
  background: transparent;
  border: 0;
  box-shadow: none;
  padding: 0;
  display: block;
}

/* ============================================================
   Responsive — collapse the sidebar on narrow viewports
   ============================================================ */
@media (max-width: 1024px) {
  .sidebar {
    width: 72px;
  }
  .sidebar-label,
  .sidebar-tenant-name,
  .sidebar-tenant-loc,
  .sidebar-switch span:not([aria-hidden]) {
    display: none;
  }
  .sidebar-item {
    justify-content: center;
    padding: 12px 8px;
  }
  .sidebar-icon { width: auto; }
  .sidebar-tenant {
    padding: 10px 8px;
    text-align: center;
  }
  .sidebar-switch {
    padding: 6px 8px;
  }
  .ai-insights-btn-label { display: none; }
  .ai-insights-btn { width: 36px; justify-content: center; padding: 6px; }
  .topbar-user-name .current-user { display: none; }
  /* Dropdowns are viewport-anchored at this breakpoint so neither the
     collapsed sidebar nor a narrow top bar can clip them. The phone rule
     below expands them to near full width. */
  .topbar-actions .dropdown-menu {
    position: fixed;
    top: 64px;
    right: 16px;
    left: auto;
    max-height: min(70vh, 480px);
    overflow-y: auto;
  }
}
/* Secondary views (Jobs/Tasks/Materials/Time Off) live in the topbar
   "More ▾" on desktop — their drawer rows only exist on phones. */
.sidebar-item.sidebar-mobile-only { display: none; }
@media (max-width: 720px) {
  .sidebar-item.sidebar-mobile-only { display: flex; }
  .sidebar {
    position: fixed;
    left: -100%;
    width: 240px;
    transition: left 0.18s ease;
  }
  .sidebar.open {
    left: 0;
    /* A later, unscoped `@media (max-width: 1024px) { .sidebar { width:
       72px } }` rule (meant for the tablet collapsed-rail state) also
       matches phone widths and otherwise wins the cascade on `width` since
       plain `.sidebar` there has the same specificity but comes later in
       the file. Re-assert the full drawer width here at higher specificity
       so the open drawer isn't squeezed into the 72px rail. */
    width: 240px;
  }
  .sidebar.open .sidebar-label,
  .sidebar.open .sidebar-tenant-name,
  .sidebar.open .sidebar-tenant-loc,
  .sidebar.open .sidebar-switch span:not([aria-hidden]) {
    display: inline;
  }
  /* Same cascade trap as the width note above, for the section headings: the
     <=1024px rail rule blanks them to bare dividers (font-size 0) because a
     label does not fit a 72px rail — but the OPEN PHONE DRAWER is 240px and
     has room for the words. Re-assert them here, including the first one,
     which the rail rule hides outright. */
  .sidebar.open .sidebar-section-label {
    font-size: 11px;
    margin: 14px 12px 4px;
    padding-top: 12px;
  }
  .sidebar.open .sidebar-workspace-label {
    display: block;
    margin-top: 0;
    padding-top: 3px;
  }
  .sidebar.open .sidebar-item {
    justify-content: flex-start;
    padding: 10px 12px;
  }
  .sidebar.open .sidebar-icon { width: 20px; }
  .topbar {
    padding: 10px 16px;
  }
}

/* Mobile nav toggle button — only shows on narrow viewports. */
.mobile-nav-toggle {
  display: none;
  background: transparent;
  border: 0;
  font-size: 22px;
  color: var(--text-heading);
  cursor: pointer;
  padding: 4px 8px;
}
@media (max-width: 720px) {
  .mobile-nav-toggle { display: inline-flex; }
}

/* ── Field Mode ────────────────────────────────────────────────────────
   Phones open the field workflow in the same calendar app.  JobShot remains
   a self-contained capture surface so its camera, offline queue and PWA
   caching continue to work exactly as they do when opened directly. */
.field-mode[hidden] { display: none; }
.field-mode {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  flex-direction: column;
  background: #f8fafc;
}
.field-mode-bar {
  flex: 0 0 auto;
  min-height: 54px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: calc(env(safe-area-inset-top, 0px) + 8px) 12px 8px;
  background: #172033;
  color: #fff;
}
.field-mode-title { display: flex; flex: 1; min-width: 0; flex-direction: column; line-height: 1.1; }
.field-mode-title strong { font-size: 14px; }
.field-mode-title span { margin-top: 3px; color: #b9c3d2; font-size: 11px; }
.field-mode-back, .field-mode-jobs {
  border: 1px solid rgba(255,255,255,.28);
  border-radius: 8px;
  background: rgba(255,255,255,.1);
  color: #fff;
  padding: 8px 10px;
  font: inherit;
  font-size: 13px;
  white-space: nowrap;
}
.field-mode-jobshot { flex: 1 1 auto; width: 100%; border: 0; background: #fff; }
#field-mode-notif { position: relative; }

/* The bell/Manage buttons in Field Mode's bar forward clicks to the real
   topbar buttons underneath (see app.js). The real notif panel / manage
   menu live inside .topbar, which is its own stacking context (position:
   sticky + z-index:40) — a fixed-position descendant can't out-rank Field
   Mode's overlay (z-index:10000) via its own z-index alone, because it's
   confined to .topbar's context first. Lift .topbar itself above Field
   Mode, but only while one of its menus is actually open, and only paint
   that menu — everything else in the bar stays invisible so the real
   topbar doesn't flash on top of Field Mode's own header.
   Scoped to the same breakpoint Field Mode itself uses (not just the
   body.field-mode-open class) — that class can outlive an actual viewport
   change (e.g. resizing past 720px without tapping "Calendar" first), and
   without this guard these rules would blank out the desktop topbar too. */
@media (max-width: 720px) {
  body.field-mode-open .topbar:has(.dropdown-menu:not(.hidden)) {
    z-index: 10001;
    background: transparent;
    border-bottom: none;
    box-shadow: none;
    pointer-events: none;
  }
  body.field-mode-open .topbar:has(.dropdown-menu:not(.hidden)) > * {
    visibility: hidden;
  }
  body.field-mode-open .dropdown-menu:not(.hidden) {
    visibility: visible;
    pointer-events: auto;
    z-index: 10001;
  }
  /* Manage-menu items (Team, Users & logins, Audit log, Scan for
     duplicates, Import .ics, Corebridge...) each open their own top-level
     .modal — those are plain children of <body>, not nested in .topbar,
     so they only need a z-index bump above Field Mode to become visible. */
  body.field-mode-open .modal:not(.hidden) {
    z-index: 10001;
  }
}

@media (min-width: 721px) {
  .field-mode { display: none !important; }
}

/* ============================================================
   DASH-02: Week in Review block.
   Two side-by-side stat cards inside one hero surface — new sales
   and completed jobs, each with a primary "this week" tier and a
   secondary "month to date" line.
   ============================================================ */
.week-in-review {
  background: var(--bg-surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-md);
  padding: 20px 22px;
  margin-bottom: 20px;
}
.wir-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 16px;
}
/* DASH-10: title + date chip live side-by-side so the week being
   reviewed is immediately obvious without a second eye-sweep. */
.wir-title-wrap {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.wir-title {
  margin: 0;
  font-size: var(--fs-lg);
  font-weight: 700;
  color: var(--text-heading);
}
.wir-date-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(225, 27, 34, 0.08);   /* brand-red 8% */
  color: var(--brand-red);
  font-size: var(--fs-sm);
  font-weight: 600;
  padding: 4px 12px;
  border-radius: var(--r-pill);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.wir-date-chip > span[aria-hidden="true"] { font-size: 13px; }
.wir-sub {  /* legacy fallback — keep so nothing else that selects on it breaks */
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.wir-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
.wir-stat {
  background: var(--bg-page);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-lg);
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  position: relative;
  overflow: hidden;
}
/* Per-card accent stripe along the top */
.wir-stat::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
}
#wir-new-sales::before  { background: var(--action-blue); }
#wir-completed::before  { background: var(--semantic-green); }

.wir-stat-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.wir-stat-icon {
  font-size: 16px;
  display: inline-flex;
}
.wir-stat-label {
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}
.wir-stat-week {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.wir-stat-num {
  font-size: 32px;
  font-weight: 700;
  color: var(--text-heading);
  line-height: 1;
}
.wir-stat-meta {
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.wir-stat-mtd {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding-top: 8px;
  border-top: 1px dashed var(--border-soft);
}
.wir-stat-mtd-label {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}
.wir-stat-mtd-num {
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--text-body);
}
@media (max-width: 720px) {
  .wir-grid { grid-template-columns: 1fr; }
}

/* DASH-17: source badge under the New Sales card — tells Mark whether
   the number came from live Corebridge, the 5-min cache, or local DB
   fallback. Empty when no source info available so it doesn't show. */
.wir-source-badge {
  margin-top: 8px;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--text-muted);
  line-height: 1.2;
}
.wir-source-badge:empty { display: none; }
.wir-source-badge.wir-source-pipeline { color: var(--text-muted); font-style: italic; }
.wir-source-badge.wir-source-live   { color: var(--semantic-green); }
.wir-source-badge.wir-source-cached { color: var(--text-muted); }
.wir-source-badge.wir-source-local  { color: var(--semantic-amber); }
.wir-source-badge.wir-source-error  { color: var(--semantic-rose); }

/* DASH-04: drill-down — the big numbers are now buttons that open
   the underlying job list when clicked. Subtle hover so it reads as
   interactive without competing with the giant numeric value. */
button.wir-drilldown {
  border: 0;
  background: transparent;
  padding: 0;
  cursor: pointer;
  font: inherit;
  color: inherit;
  text-align: left;
  border-radius: var(--r-sm);
  transition: background 0.12s ease;
}
button.wir-drilldown:hover { background: rgba(225, 27, 34, 0.06); }
button.wir-drilldown:focus-visible { outline: 2px solid var(--action-blue); outline-offset: 2px; }
button.wir-stat-num.wir-drilldown { padding: 4px 8px; margin: -4px -8px; }
button.wir-stat-mtd-num.wir-drilldown { padding: 2px 6px; margin: -2px -6px; }

/* Drill-down modal */
#wir-drill-modal {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.45);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 10500;
  padding: 16px;
}
#wir-drill-modal.active { display: flex; }
#wir-drill-modal .wir-drill-card {
  background: var(--bg-surface);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-xl);
  width: 100%;
  max-width: 640px;
  max-height: 80vh;
  padding: 24px 28px 20px;
  position: relative;
  display: flex;
  flex-direction: column;
}
#wir-drill-modal .wir-drill-close {
  position: absolute;
  top: 10px;
  right: 12px;
  border: 0;
  background: transparent;
  font-size: 22px;
  line-height: 1;
  color: var(--text-muted);
  cursor: pointer;
  width: 32px;
  height: 32px;
  border-radius: 50%;
}
#wir-drill-modal .wir-drill-close:hover { background: var(--bg-page); color: var(--text-heading); }
#wir-drill-modal .wir-drill-title {
  margin: 0;
  font-size: var(--fs-lg);
  font-weight: 700;
  color: var(--text-heading);
}
#wir-drill-modal .wir-drill-sub {
  margin: 4px 0 16px;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
#wir-drill-modal .wir-drill-list {
  flex: 1;
  overflow-y: auto;
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
}
#wir-drill-modal .wir-drill-empty {
  padding: 24px;
  text-align: center;
  color: var(--text-muted);
  font-size: var(--fs-sm);
}
#wir-drill-modal .wir-drill-row {
  display: grid;
  grid-template-columns: 100px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border-soft);
  cursor: pointer;
  transition: background 0.12s ease;
}
#wir-drill-modal .wir-drill-row:last-child { border-bottom: 0; }
#wir-drill-modal .wir-drill-row:hover { background: var(--bg-page); }
#wir-drill-modal .wir-drill-row-when {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
#wir-drill-modal .wir-drill-row-co {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-heading);
  min-width: 0;
}
#wir-drill-modal .wir-drill-src {
  background: var(--action-blue);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  padding: 1px 5px;
  border-radius: var(--r-sm);
  margin-right: 6px;
  vertical-align: middle;
}
#wir-drill-modal .wir-drill-inv {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  margin-left: 6px;
}
#wir-drill-modal .wir-drill-row-amt {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-body);
  font-variant-numeric: tabular-nums;
}

/* ============================================================
   UI-03-A3: Upcoming Installs panel.
   ============================================================ */
.installs-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
.installs-title {
  margin: 0;
  font-size: var(--fs-xl);
  font-weight: 700;
  color: var(--text-heading);
}
.installs-sub {
  margin: 4px 0 0;
  color: var(--text-muted);
  font-size: var(--fs-sm);
}
.installs-filters {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}
.installs-filters select {
  font: inherit;
  font-size: var(--fs-sm);
  padding: 7px 10px;
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
  background: var(--bg-surface);
  color: var(--text-body);
}
.installs-show-done {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}
.installs-list { display: flex; flex-direction: column; gap: 20px; }
.installs-empty {
  background: var(--bg-surface);
  border: 1px dashed var(--border-soft);
  border-radius: var(--r-xl);
  padding: 32px;
  text-align: center;
  color: var(--text-muted);
  font-size: var(--fs-md);
}
.installs-group {
  background: var(--bg-surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.installs-group-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 20px;
  background: var(--bg-page);
  border-bottom: 1px solid var(--border-soft);
}
.installs-group-name {
  font-size: var(--fs-md);
  font-weight: 700;
  color: var(--text-heading);
}
.installs-group-count {
  background: var(--brand-red);
  color: #fff;
  font-size: var(--fs-xs);
  font-weight: 700;
  padding: 2px 10px;
  border-radius: var(--r-pill);
}
.installs-rows { display: flex; flex-direction: column; }
.install-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--border-soft);
  cursor: pointer;
  transition: background 0.12s ease;
}
.install-row:last-child { border-bottom: 0; }
.install-row:hover { background: var(--bg-page); }
.install-row.is-done { opacity: 0.62; }
.install-row.is-done .install-row-company { text-decoration: line-through; }

.install-row-when {
  flex-shrink: 0;
  width: 92px;
  display: flex;
  flex-direction: column;
  line-height: 1.2;
}
.install-row-date {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-heading);
}
.install-row-time {
  font-size: var(--fs-xs);
  color: var(--text-muted);
}
.install-row-meta {
  flex: 1;
  min-width: 0;
}
.install-row-title {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.install-row-verb {
  font-size: var(--fs-xs);
  font-weight: 700;
  padding: 2px 10px;
  border-radius: var(--r-pill);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.install-row-verb.verb-install { background: #e3f2fd; color: #16C7C9; }
.install-row-verb.verb-removal { background: #efebe9; color: #5d4037; }
.install-row-verb.verb-pickup  { background: #fff8e1; color: #ef6c00; }
.install-row-daychip {
  font-size: var(--fs-xs);
  font-weight: 600;
  background: var(--bg-page);
  color: var(--text-muted);
  padding: 2px 8px;
  border-radius: var(--r-pill);
}
.install-row-company {
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--text-heading);
}
.install-row-addr {
  margin-top: 4px;
  font-size: var(--fs-xs);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.install-row-done {
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--semantic-green);
}
.install-row-side {
  flex-shrink: 0;
}
.install-row-assignee {
  font-size: var(--fs-xs);
  font-weight: 600;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  white-space: nowrap;
}
.install-row-assignee.unassigned {
  background: var(--bg-page);
  color: var(--text-muted);
  font-style: italic;
}

@media (max-width: 720px) {
  .install-row-when { width: 76px; }
  .install-row-addr { white-space: normal; }
}

/* ============================================================
   UI-03-A2: desktop sidebar collapse toggle.
   Click the chevron to hide the sidebar entirely; click again to
   bring it back. Preference persists in localStorage so it
   survives reloads. On mobile the existing mobile-nav-toggle
   handles the drawer pattern, so this button hides below 720px.
   ============================================================ */
.sidebar-collapse-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
  width: 32px;
  height: 32px;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.sidebar-collapse-btn:hover {
  background: var(--bg-page);
  color: var(--text-heading);
  border-color: var(--border-strong);
}
.sidebar-collapse-icon {
  font-size: 11px;
  line-height: 1;
  transition: transform 0.18s ease;
}
/* When the sidebar is hidden, flip the chevron so it reads as
   "click to bring it back". */
.app-shell.sidebar-hidden .sidebar-collapse-icon {
  transform: rotate(180deg);
}
/* When the sidebar is hidden, drop it from the layout entirely so the
   main column claims the full width. */
.app-shell.sidebar-hidden .sidebar {
  display: none;
}
/* On mobile the dedicated mobile-nav-toggle owns the drawer pattern —
   no need to also show the desktop collapse button. */
@media (max-width: 720px) {
  .sidebar-collapse-btn { display: none; }
}

/* ============================================================
   END UI-03-A. The block below is the LEGACY body > header rule —
   kept so the modal <header> elements don't get the page-header
   treatment. (Modals use plain <header> tags internally.)
   ============================================================ */
body > header h1 {
  margin: 0;
  font-size: 20px;
  font-weight: 600;
}
.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  color: inherit;
  flex-shrink: 0;
}
.brand-logo {
  height: 40px;
  width: auto;
  display: block;
}
.brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.1;
}
.brand-mark {
  font-size: 18px;
  font-weight: 700;
  color: var(--brand-red);
  letter-spacing: 0.2px;
}
.brand-loc {
  font-size: 11px;
  font-weight: 500;
  color: #6b7280;
  text-transform: uppercase;
  letter-spacing: 0.6px;
}
/* Default nav layout (desktop). Mobile @media query later overrides these. */
nav {
  display: flex;
  gap: 8px;
  flex: 1;
  align-items: center;
}
.nav-items {
  display: flex;
  gap: 8px;
  align-items: center;
}
.mobile-nav-toggle {
  display: none;
  background: #fff;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  font-size: 22px;
  line-height: 1;
  padding: 6px 12px;
  cursor: pointer;
  margin-right: 4px;
}
.mobile-nav-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 90;
}
.mobile-nav-backdrop.hidden { display: none; }

@media (max-width: 768px) {
  .brand-loc { display: none; }
  .brand-logo { height: 32px; }
  header {
    padding: 8px 14px;
    gap: 10px;
    flex-wrap: wrap; /* allow drawer below */
    position: relative;
  }
  .brand-mark { font-size: 15px; }
  /* Hamburger appears on mobile */
  .mobile-nav-toggle { display: inline-block; order: -1; }
  /* Nav layout: top row stays compact, drawer drops below the header
     row when open. No fixed-position fanciness — just a plain inline
     block, more reliable on touch. */
  nav#main-nav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    width: 100%;
  }
  nav#main-nav .nav-items {
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    width: 100%;
    order: 99; /* push below + New / sign out row */
    margin-top: 8px;
    padding: 10px 0 4px;
    border-top: 1px solid #e1e4e8;
  }
  nav#main-nav .nav-items.open { display: flex; }
  nav#main-nav .nav-items > .tab,
  nav#main-nav .nav-items > .dropdown > .tab-dropdown-btn,
  nav#main-nav .nav-items > .dropdown > #manage-btn,
  nav#main-nav .nav-items .dropdown-menu button {
    width: 100%;
    text-align: left;
    font-size: 15px;
    padding: 13px 16px;
    background: #fff;
    border: 1px solid #d0d4da;
    border-radius: var(--r-md);
    cursor: pointer;
  }
  nav#main-nav .nav-items > .tab.active {
    background: #16C7C9;
    color: #fff;
    border-color: #16C7C9;
  }
  /* Views / Manage become non-interactive section headers */
  nav#main-nav .nav-items #views-btn,
  nav#main-nav .nav-items #manage-btn {
    pointer-events: none;
    font-size: 11px !important;
    font-weight: 700;
    color: #6b7280;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    background: transparent !important;
    border: none !important;
    padding: 14px 6px 4px !important;
    cursor: default;
  }
  /* Sub-menus auto-expand as a list of full-width tappable buttons */
  nav#main-nav .nav-items .dropdown { width: 100%; }
  nav#main-nav .nav-items .dropdown-menu {
    position: static;
    display: block !important;
    box-shadow: none;
    border: none;
    background: transparent;
    border-radius: 0;
    padding: 0;
    margin: 0;
    min-width: 0;
    z-index: auto;
  }
  nav#main-nav .nav-items .dropdown-menu button {
    background: #f8f9fa;
    margin-bottom: 4px;
  }
  /* + New stays compact in the top row */
  nav#main-nav .nav-new { margin-left: auto; order: 1; }
  nav#main-nav .nav-new .primary { margin-left: 0; padding: 8px 12px; font-size: 13px; }
  /* User pill / sign-out compact in the top row */
  .header-user {
    border-left: none;
    margin-left: 4px;
    padding-left: 0;
    gap: 4px;
    order: 2;
  }
  .current-user { display: none; }
  #logout-btn { padding: 8px 10px; font-size: 12px; }
}
button {
  font-family: inherit;
  font-size: 14px;
  padding: 8px 14px;
  border-radius: var(--r-md);
  border: 1px solid #d0d4da;
  background: #fff;
  cursor: pointer;
}
button:hover { background: #f0f1f3; }
/* POLISH-05: brand red on active state + primary CTAs. The default
   action-blue stays for non-active interactive surfaces — we just
   need the brand color to be present where the eye lands most. */
button.tab.active {
  background: var(--brand-red);
  color: #fff;
  border-color: var(--brand-red);
}
/* POLISH-11 (M12): Calendar button is the most-used view — keep the
   subtle accent, but soften it so the active state (brand-red) is
   clearly distinct. Was a saturated blue tint that competed with the
   active state; now it's a quiet gray-blue. */
button.tab-calendar:not(.active) {
  background: #f5f7fa;
  border-color: #d8e0ea;
  color: var(--action-blue);
  font-weight: 600;
}
button.tab-calendar:not(.active):hover { background: #ebf0f6; }
button.primary {
  background: var(--brand-red);
  color: #fff;
  border-color: var(--brand-red);
  margin-left: auto;
}
button.primary:hover { background: var(--brand-red-dark); }
button.danger {
  background: #d93025;
  color: #fff;
  border-color: #d93025;
}
button.danger:hover { background: #b2271f; }

main { padding: 24px; }
.tab-panel { display: none; }
.tab-panel.active { display: block; }

/* Dashboard metric strip (above calendar) */
.dashboard-metrics {
  /* UI-02-C: a touch more breathing room between hero cards. */
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 20px;
}
.metric-card {
  /* UI-02-C: hero card chrome — pure white surface, 16px radius, soft
     elevated shadow. Border drops to slate-200 for less visual noise
     since the shadow now does the "lift" job. Padding bumped to read
     more "spacious dashboard" than "compact tile". */
  background: var(--bg-surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-xl);
  padding: 20px 22px;
  border-top: 3px solid #d0d4da;
  box-shadow: var(--shadow-md);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
/* POLISH-12 (M1): remove the hover lift on metric cards since clicking
   them doesn't navigate anywhere — the lift was hinting clickability
   that doesn't exist. Keep the cards visually static. */
.metric-card:hover {
  box-shadow: var(--shadow-lg);
}
.metric-card.metric-installs { border-top-color: #16C7C9; }
.metric-card.metric-in-prod { border-top-color: #212121; }
.metric-card.metric-scheduled { border-top-color: #ffa000; }
.metric-card.metric-completed { border-top-color: #ab47bc; }
.metric-label {
  font-size: 11px;
  font-weight: 700;
  color: #56606b;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 8px;
}
.metric-value {
  font-size: 26px;
  font-weight: 700;
  color: #1f2329;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.metric-sub {
  font-size: 12px;
  color: #56606b;
  margin-top: 6px;
}
@media (max-width: 768px) {
  .dashboard-metrics { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .metric-value { font-size: 22px; }
}
@media (max-width: 480px) {
  .dashboard-metrics { grid-template-columns: 1fr; }
}

.last-sync-line {
  font-size: 12px;
  color: #56606b;
  margin-bottom: 8px;
  text-align: right;
}
.last-sync-line.hidden { display: none; }
.last-sync-line .auto-on { color: #2e7d32; font-weight: 600; }

/* JobShot quick-access banner on the dashboard */
.jobshot-dash-banner {
  display: flex;
  align-items: center;
  gap: 14px;
  background: #0f172a;
  color: #e2e8f0;
  border-radius: 12px;
  padding: 14px 18px;
  margin-bottom: 16px;
  text-decoration: none;
  transition: background 0.15s;
}
.jobshot-dash-banner:hover { background: #1e293b; }
.jobshot-dash-icon { font-size: 1.6rem; flex-shrink: 0; }
.jobshot-dash-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.jobshot-dash-text strong { font-size: 0.95rem; color: #fff; }
.jobshot-dash-text span { font-size: 0.8rem; color: #94a3b8; }
.jobshot-dash-arrow { margin-left: auto; font-size: 1.3rem; color: #60a5fa; flex-shrink: 0; }
.pulse-banner { background: #14532d; }
.pulse-banner:hover { background: #166534; }
.pulse-banner .jobshot-dash-arrow { color: #86efac; }

/* Pending Review banner */
/* Pending-review banner + modal removed — see .pending-sidebar below
   for the single source of truth. */

/* Dashboard mini-calendar — shows time off and surveys at a glance */
.mini-cal-card {
  background: #fff;
  border: 1px solid #e1e4e8;
  border-radius: var(--r-lg);
  padding: 14px 16px;
  margin-bottom: 16px;
  box-shadow: 0 1px 2px rgba(0,0,0,0.03);
}
.mini-cal-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}
.mini-cal-header h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  flex: 1;
  text-align: center;
}
.mini-cal-nav {
  width: 28px;
  height: 28px;
  border-radius: var(--r-md);
  background: #fff;
  border: 1px solid #d0d4da;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
}
.mini-cal-nav:hover { background: #eef0f3; }
.mini-cal-legend {
  font-size: 11px;
  color: #6b7280;
  display: flex;
  align-items: center;
  gap: 10px;
}
.mini-cal-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  vertical-align: middle;
  margin-right: 3px;
}
.mini-cal-dot-timeoff { background: #ef6c00; }
.mini-cal-dot-survey { background: #6a1b9a; }
.mini-cal {
  display: grid;
  /* minmax(0, 1fr) lets the cells shrink below their content's intrinsic
     width — required so chip text inside doesn't push the cells (and
     the whole page) wider than the viewport on phones. */
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 2px;
  font-size: 12px;
}
.mini-cal-dow {
  text-align: center;
  font-size: 10px;
  font-weight: 700;
  color: #6b7280;
  text-transform: uppercase;
  padding: 4px 0;
  min-width: 0;
}
.mini-cal-day {
  background: #fafbfc;
  border: 1px solid #eef0f3;
  border-radius: var(--r-sm);
  padding: 4px 5px;
  min-height: 56px;
  min-width: 0; /* allow cell to shrink with the column */
  overflow: hidden; /* clip overflowing chip text */
  position: relative;
  cursor: pointer;
}
.mini-cal-day:hover { background: #f0f6ff; border-color: #16C7C9; }
.mini-cal-day.other-month { background: #fff; color: #c4c8cd; }
.mini-cal-day.today { background: #fff8dc; border-color: #f9a825; }
.mini-cal-daynum {
  font-size: 11px;
  font-weight: 600;
  color: #1f2329;
}
.mini-cal-day.other-month .mini-cal-daynum { color: #c4c8cd; }
.mini-cal-events {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 3px;
  min-width: 0;
}
.mini-cal-evt {
  font-size: 10px;
  padding: 1px 5px;
  border-radius: var(--r-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: #fff;
  font-weight: 500;
  min-width: 0;
  max-width: 100%;
}
.mini-cal-evt-timeoff { background: #ef6c00; }
.mini-cal-evt-survey { background: #6a1b9a; }

/* Dashboard "Today" and "Coming up" lists */
.dashboard-lists {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-bottom: 16px;
}
.dashboard-lists.three-col { grid-template-columns: 1fr 1fr 1fr; }
.dashboard-list-card {
  /* UI-02-C: dashboard list cards get the same hero chrome — 16px
     radius, slate-200 border, soft elevation. */
  background: var(--bg-surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-md);
  padding: 20px 22px;
  position: relative;
}
/* POLISH-10 (M10): "Today" card gets a brand-red accent stripe so it
   reads as the most important of the three cards. The "Today" card is
   identified by being the first card in the .dashboard-lists row. */
.dashboard-lists .dashboard-list-card:first-child {
  border-top: 3px solid var(--brand-red);
  padding-top: 16px;  /* compensate for thicker top border */
}
/* PIPE-INSTALL: at-risk install alert card (install scheduled, prod not done) */
.dashboard-alert-card {
  background: var(--bg-surface);
  border: 1px solid #f3c2c2;
  border-left: 4px solid #dc2626;
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-md);
  padding: 16px 20px;
  margin-bottom: 16px;
}
.dashboard-alert-card h3 { margin: 0 0 10px 0; font-size: 15px; color: #991b1b; }
.dashboard-alert-card .alert-count { color: #dc2626; font-weight: 700; }
.dashboard-alert-card .dl-date { min-width: 84px; display: inline-block; }
.dashboard-alert-card .dl-date.due-now { color: #fff; background: #dc2626; border-radius: 4px; padding: 0 6px; font-weight: 700; }
.dashboard-alert-card .dl-date.due-3 { color: #9a3412; font-weight: 700; }
/* PIPE-INSTALL: install countdown badge on Project Pipeline cards */
.kanban-card-countdown {
  display: inline-block;
  margin-top: 5px;
  font-size: 10px;
  font-weight: 600;
  color: #1e40af;
  background: #e0ecff;
  border-radius: 4px;
  padding: 1px 6px;
}
.kanban-card-countdown.due-7  { color: #92700e; background: #fef3c7; }
.kanban-card-countdown.due-3  { color: #9a3412; background: #ffedd5; }
.kanban-card-countdown.due-now { color: #fff;    background: #dc2626; }
/* REWORK: calendar chip */
.cal-event.rework { background: #ede9fe; color: #5b21b6; border-left: 3px solid #7c3aed; }
.cal-event.rework.install { background: #f3e8ff; }
/* REWORK: dashboard tally card */
.rework-card {
  background: var(--bg-surface); border: 1px solid var(--border-soft);
  border-left: 4px solid #7c3aed; border-radius: var(--r-xl);
  box-shadow: var(--shadow-md); padding: 16px 20px; margin-bottom: 16px;
}
.rework-card-head { display: flex; align-items: baseline; justify-content: space-between; }
.rework-card-head h3 { margin: 0; font-size: 15px; color: #5b21b6; }
.rework-card-hint { font-size: 11px; color: #94a3b8; }
.rework-card-periods { display: flex; gap: 10px; margin: 12px 0 6px; }
.rework-period {
  flex: 1; background: #faf8ff; border: 1px solid #e9e2fb; border-radius: 10px;
  padding: 10px; cursor: pointer; text-align: center; transition: background .12s;
}
.rework-period:hover { background: #f1ebfe; }
.rework-period .rp-num { display: block; font-size: 24px; font-weight: 700; color: #6d28d9; font-variant-numeric: tabular-nums; }
.rework-period .rp-lbl { display: block; font-size: 11px; color: #64748b; margin-top: 2px; }
.rework-card-depts { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 6px; }
.rcd-label { font-size: 11px; color: #64748b; }
.rcd-chip { font-size: 11px; background: #ede9fe; color: #5b21b6; border-radius: 4px; padding: 1px 7px; }
.rcd-chip b { font-weight: 700; }
.rcd-empty { font-size: 12px; color: #94a3b8; }
.rework-install-field.hidden { display: none; }
.rework-list-row { cursor: pointer; }
.rework-list-row:hover { background: #faf8ff; }
/* REWORK: "+ Log rework" button + open-reworks list + job picker */
.log-rework-btn {
  border: 1px solid #c4b5fd; background: #f5f3ff; color: #6d28d9;
  font-weight: 600; font-size: 12px; border-radius: 8px; padding: 5px 12px; cursor: pointer;
}
.log-rework-btn:hover { background: #ede9fe; }
.rework-open-wrap { margin-top: 10px; }
.rework-open-head { font-size: 12px; font-weight: 600; color: #5b21b6; margin-bottom: 4px; }
.rework-open-list { display: flex; flex-direction: column; gap: 1px; }
.rework-open-row {
  display: grid; grid-template-columns: 1fr auto auto; gap: 10px; align-items: center;
  padding: 5px 8px; font-size: 13px; border-radius: 6px; cursor: pointer;
}
.rework-open-row:hover { background: #faf8ff; }
.rework-open-row .ror-co { font-weight: 600; color: #1f2329; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rework-open-row .ror-dept { font-size: 11px; background: #ede9fe; color: #5b21b6; border-radius: 4px; padding: 1px 7px; }
.rework-open-row .ror-sched { font-size: 12px; color: #64748b; font-variant-numeric: tabular-nums; }
.rework-pick-body { padding: 6px 2px; }
#rework-pick-search { width: 100%; padding: 9px 12px; font-size: 14px; box-sizing: border-box; }
.rework-pick-results { margin-top: 8px; max-height: 320px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.rework-pick-hint { font-size: 13px; color: #94a3b8; padding: 10px 4px; }
.rework-pick-item {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  text-align: left; width: 100%; background: #fff; border: 1px solid #eef1f4;
  border-radius: 8px; padding: 8px 12px; cursor: pointer;
}
.rework-pick-item:hover { background: #f5f3ff; border-color: #c4b5fd; }
.rework-pick-item .rpi-co { font-weight: 600; color: #1f2329; }
.rework-pick-item .rpi-meta { font-size: 11px; color: #64748b; }
/* REWORK: the job-modal padding rules are scoped to #modal/#job-form, so these
   rework modals were rendering tight against the edges. Give them the same
   comfortable margins. */
#rework-modal .modal-content > header.modal-hero,
#rework-list-modal .modal-content > header.modal-hero {
  padding: 22px 28px 16px;
}
#rework-form .form-section { padding: 22px 28px; border-bottom: none; }
#rework-form .form-section .grid { gap: 18px 22px; }
#rework-form > footer { padding: 18px 28px 24px; margin-top: 0; }
.rework-pick-body { padding: 18px 26px 24px; }
#rework-list-modal .modal-content { width: min(1040px, 95vw); }
#rework-list-modal .table-wrap { padding: 8px 24px 24px; border: none; }
/* Fixed layout so the long Job/Needs columns truncate instead of pushing the
   Scheduled/Status columns off the right edge. */
#rework-list-table { table-layout: fixed; width: 100%; }
#rework-list-table th, #rework-list-table td {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#rework-list-table th:nth-child(1), #rework-list-table td:nth-child(1) { width: 104px; }  /* Logged */
#rework-list-table th:nth-child(2), #rework-list-table td:nth-child(2) { width: 26%; }     /* Job */
#rework-list-table th:nth-child(3), #rework-list-table td:nth-child(3) { width: 116px; }   /* Department */
#rework-list-table th:nth-child(4), #rework-list-table td:nth-child(4) { width: auto; }     /* Needs */
#rework-list-table th:nth-child(5), #rework-list-table td:nth-child(5) { width: 130px; }   /* Scheduled */
#rework-list-table th:nth-child(6), #rework-list-table td:nth-child(6) { width: 78px; }     /* Status */
.dashboard-list-card h3 {
  margin: 0 0 12px 0;
  font-size: 15px;
  font-weight: 700;
  color: #1f2329;
}
.dashboard-list { display: flex; flex-direction: column; gap: 6px; }
.dashboard-list .empty { color: #888; font-size: 13px; font-style: italic; }
.dashboard-list .dl-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--r-md);
  cursor: pointer;
  font-size: 13px;
}
.dashboard-list .dl-item:hover { background: #f5f7fa; }
.dashboard-list .dl-date {
  font-weight: 600;
  color: #56606b;
  font-size: 12px;
  min-width: 56px;
  font-variant-numeric: tabular-nums;
}
.dashboard-list .dl-label { flex: 1; font-weight: 500; }
.dashboard-list .dl-meta { color: #888; font-size: 12px; }
.dashboard-list-card h3 .dl-count {
  font-weight: 400;
  color: #888;
  font-size: 13px;
  margin-left: 4px;
}

/* Views dropdown trigger styling */
.tab-dropdown-btn {
  font-family: inherit;
  font-size: 14px;
  padding: 8px 14px;
  border-radius: var(--r-md);
  border: 1px solid #d0d4da;
  background: #fff;
  cursor: pointer;
}
.tab-dropdown-btn:hover { background: #f0f1f3; }
.tab-dropdown-btn.active {
  background: #16C7C9;
  color: #fff;
  border-color: #16C7C9;
}

@media (max-width: 1024px) {
  .dashboard-lists.three-col { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 768px) {
  .dashboard-lists,
  .dashboard-lists.three-col { grid-template-columns: 1fr; }
}

/* Calendar */
.cal-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}
.cal-toolbar {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 18px;
  padding: 10px 14px;
  background: #f8f9fa;
  border: 1px solid #e1e4e8;
  border-radius: var(--r-md);
  flex-wrap: wrap;
  font-size: 13px;
}
.cal-toolbar-label {
  font-weight: 600;
  color: #56606b;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-right: -4px;
}
.cal-search-wrap {
  position: relative;
  display: flex;
  align-items: center;
}
/* POLISH-08 (H5): unified search-input chrome. All three search
   inputs (calendar / kanban / jobs-controls) now share base
   dimensions; only the right-padding (for #cal-search's clear button)
   and width differ per usage. */
#cal-search,
#kanban-search,
.kanban-controls input[type="search"],
.jobs-controls input[type="search"] {
  padding: 7px 12px;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  font-family: inherit;
  background: #fff;
}
/* #kanban-search is a contenteditable div standing in for an <input>
   (autofill defense) — mimic single-line input behavior, like #cal-search. */
#kanban-search {
  min-width: 220px;
  cursor: text;
  white-space: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  line-height: 1.4;
}
#kanban-search:empty::before {
  content: attr(data-placeholder);
  color: var(--text-muted);
  pointer-events: none;
}
#cal-search {
  width: 280px;
  padding-right: 30px;   /* extra room for the clear button */
  /* Contenteditable div standing in for an <input> (autofill defense) —
     mimic single-line input behavior. */
  cursor: text;
  white-space: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  line-height: 1.4;
}
#cal-search:empty::before {
  content: attr(data-placeholder);
  color: var(--text-muted);
  pointer-events: none;
}
#cal-search:focus,
#kanban-search:focus,
.kanban-controls input[type="search"]:focus,
.jobs-controls input[type="search"]:focus {
  outline: none;
  border-color: var(--action-blue);
  box-shadow: 0 0 0 2px rgba(22,199,201, 0.15);
}
.cal-search-count {
  position: absolute;
  right: 32px;
  font-size: 11px;
  font-weight: 600;
  color: #56606b;
  background: #fff3e0;
  padding: 1px 7px;
  border-radius: var(--r-pill);
  pointer-events: none;
}
.cal-search-count.clickable {
  pointer-events: auto;
  cursor: pointer;
}
.cal-search-count.clickable:hover {
  background: #ffe0b2;
  color: #1f2937;
}
.cal-search-clear {
  position: absolute;
  right: 6px;
  background: transparent;
  border: none;
  color: #6b7280;
  font-size: 14px;
  line-height: 1;
  padding: 4px 6px;
  cursor: pointer;
  border-radius: var(--r-sm);
}
.cal-search-clear:hover { color: #1f2329; background: #eef0f3; }
.cal-mode-toggle {
  display: inline-flex;
  background: #fff;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  overflow: hidden;
}
.cal-mode-btn {
  border: none;
  background: #fff;
  padding: 6px 14px;
  font-size: 12px;
  font-weight: 600;
  color: #56606b;
  cursor: pointer;
  font-family: inherit;
  border-right: 1px solid #e1e4e8;
}
.cal-mode-btn:last-child { border-right: none; }
.cal-mode-btn:hover { background: #f0f1f3; }
.cal-mode-btn.active {
  background: #16C7C9;
  color: #fff;
}
.cal-mode-btn.active:hover { background: #12B6B8; }
/* When a search is active, dim the toolbar's other toggles to draw the
   eye to the search box — but keep them clickable. */
.cal-toolbar.searching .toggle { opacity: 0.45; }
@media (max-width: 768px) {
  #cal-search { width: 200px; }
}
.legend-toggle {
  margin-left: auto;
  padding: 4px 10px;
  font-size: 12px;
  color: #56606b;
  background: #fff;
  border: 1px solid #d0d4da;
  border-radius: var(--r-sm);
  cursor: pointer;
}
.legend-toggle:hover { border-color: #16C7C9; color: #16C7C9; }
.legend.hidden { display: none; }
.legend {
  width: 100%;
  margin-top: 6px;
  padding-top: 10px;
  border-top: 1px dashed #e1e4e8;
  margin-left: 0 !important;
}
.cal-controls h2 {
  margin: 0;
  font-size: 18px;
  min-width: 200px;
  text-align: center;
}
.cal-views {
  display: inline-flex;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  overflow: hidden;
  margin-left: 12px;
}
.cal-view-btn {
  padding: 6px 12px;
  border: none;
  border-radius: 0;
  background: #fff;
  font-size: 13px;
  border-right: 1px solid #d0d4da;
}
.cal-view-btn:last-child { border-right: none; }
.cal-view-btn.active { background: #16C7C9; color: #fff; }
.cal-view-btn:hover:not(.active) { background: #f0f1f3; }
.toggle {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  color: #56606b;
  cursor: pointer;
  user-select: none;
}
.toggle input { margin: 0; cursor: pointer; }
.legend {
  margin-left: auto;
  font-size: 13px;
  color: #56606b;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin-right: 4px;
  vertical-align: middle;
}
.dot.prod-due { background: #56606b; }
.dot.install { background: #16C7C9; }
.dot.pickup { background: #ffa000; }
.dot.completed { background: #ab47bc; }
.dot.priority { background: #e53935; }

#calendar {
  /* UI-02-C: calendar is the hero surface — bump to 16px radius,
     elevated shadow, slate-200 border. */
  background: var(--bg-surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.cal-header {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
}
.cal-week {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  position: relative;
}
.cal-header > div {
  padding: 8px;
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  color: #56606b;
  background: #f8f9fa;
  border-bottom: 1px solid #e1e4e8;
  text-align: center;
}
.cal-day {
  padding: 4px 4px 6px 4px;
  padding-top: calc(30px + var(--lanes, 0) * 22px);
  border-right: 1px solid #e1e4e8;
  border-bottom: 1px solid #e1e4e8;
  position: relative;
  background: #fff;
  overflow: hidden;
  cursor: cell;
}
.cal-day:hover { background: #f8fafe; }
.cal-day.today:hover { background: #fff4c4; }
.cal-day.other-month:hover { background: #f0f1f3; }
.cal-day::after {
  content: "+";
  position: absolute;
  top: 4px;
  right: 6px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #16C7C9;
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  line-height: 18px;
  text-align: center;
  opacity: 0;
  transition: opacity 0.1s;
  pointer-events: none;
}
.cal-day:hover::after { opacity: 1; }
/* Per-view fixed week heights */
/* Row heights chosen so the per-cell chip limit (15 / 20 / 30 in
   VIEW_CHIP_LIMIT) actually fits without needing the "+N more" overflow
   button until you exceed the limit. Each chip is ~17px tall + 3px gap,
   so 15 chips need ~300px plus header. Cells overflow-y:auto so busy
   days scroll inside the cell — calendar layout stays grid-aligned. */
#calendar.view-month .cal-week { height: 320px; overflow: hidden; }
#calendar.view-2week .cal-week { height: 440px; overflow: hidden; }
#calendar.view-week .cal-week { height: 700px; overflow: hidden; }
#calendar .cal-day { height: 100%; overflow-y: auto; overflow-x: hidden; }
/* Hide scrollbars unless hovering, so quiet days look clean */
#calendar .cal-day::-webkit-scrollbar { width: 6px; }
#calendar .cal-day::-webkit-scrollbar-thumb { background: transparent; border-radius: var(--r-sm); }
#calendar .cal-day:hover::-webkit-scrollbar-thumb { background: #c4c8cd; }
.cal-day:nth-child(7n) { border-right: none; }
.cal-day.other-month { background: #fafbfc; color: #aaa; }
.cal-day.today { background: #fff8dc; }
.cal-day .day-number {
  position: absolute;
  top: 6px;
  left: 6px;
  font-size: 12px;
  font-weight: 600;
  color: #56606b;
}
.cal-day.today .day-number {
  background: #16C7C9;
  color: #fff;
  border-radius: 50%;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  top: 4px;
  left: 4px;
}
.cal-event {
  display: block;
  font-size: 11px;
  padding: 2px 6px;
  margin-top: 3px;
  border-radius: var(--r-sm);
  background: #e8f0fe;
  color: #16C7C9;
  cursor: grab;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cal-event:active, .span-bar:active { cursor: grabbing; }
.cal-event.dragging, .span-bar.dragging { opacity: 0.4; }
.cal-day.drag-over { background: #e3f2fd !important; outline: 2px solid #16C7C9; outline-offset: -2px; }
.cal-event.prod-due { background: #eceff1; color: #1f2329; border-left: 3px solid #1f2329; font-weight: 600; }
.cal-event.in-prod { background: #212121; color: #fff; border-left: 3px solid #000; font-weight: 600; cursor: default; }
.cal-event.install { background: #16C7C9; color: #fff; border-left: 3px solid #0E9799; font-weight: 600; }
.cal-event.removal { background: #6d4c41; color: #fff; border-left: 3px solid #4e342e; font-weight: 600; }
.cal-event.pickup { background: #fff8e1; color: #e65100; border-left: 3px solid #ffa000; font-weight: 600; }
.cal-event.completed { background: #f3e5f5; color: #6a1b9a; border-left: 3px solid #ab47bc; font-weight: 600; text-decoration: line-through; }
.cal-event.priority, .span-bar.priority-chip {
  background: #ffebee; color: #b71c1c; border-left: 3px solid #e53935; font-weight: 600;
}
/* Parked + priority: still red so it's obviously flagged, but with a
   dashed border and slight dim so you can see it's been set aside. */
.cal-event.priority.parked {
  border-left-style: dashed;
  background: repeating-linear-gradient(
    -45deg,
    #ffebee, #ffebee 6px,
    #fff5f5 6px, #fff5f5 12px
  );
  opacity: 0.92;
}
/* CAL-24: install/pickup/removal chip for a job that's OFF-CALENDAR (parked).
   The install still shows, but a dashed border + faint stripe signals the
   production side is set aside. */
.cal-event.install.parked,
.cal-event.pickup.parked,
.cal-event.removal.parked {
  border-style: dashed;
  opacity: 0.9;
}
.cal-event.install.parked::before,
.cal-event.pickup.parked::before,
.cal-event.removal.parked::before {
  content: "⏸ ";
  opacity: 0.8;
}
.cal-event.install.done, .cal-event.pickup.done {
  text-decoration: line-through;
  opacity: 0.7;
  border-left-color: #2e7d32;
}
.cal-event.install.done::before, .cal-event.pickup.done::before {
  content: "✓ ";
  color: #2e7d32;
  text-decoration: none;
  display: inline-block;
  font-weight: 700;
}

/* Production span bars (Gantt-style) */
.bars-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
}
.span-bar {
  position: absolute;
  height: 19px;
  font-size: 11px;
  font-weight: 600;
  padding: 0 8px;
  border-radius: var(--r-sm);
  cursor: grab;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: auto;
  display: flex;
  align-items: center;
  margin-left: 2px;
  box-shadow: 0 1px 1px rgba(0,0,0,0.08);
}
.span-bar.in-prod { background: #212121; color: #fff; }
.span-bar.in-prod:hover { background: #000; }
.span-bar.completed { background: #ab47bc; color: #fff; }
.span-bar.completed:hover { background: #9c27b0; }
.span-bar.priority { background: #e53935; color: #fff; }
.span-bar.priority:hover { background: #c62828; }

/* Subtle marker: jobs not linked to a Corebridge order */
.span-bar.not-cb {
  border-bottom: 2px dashed rgba(255, 255, 255, 0.65);
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}
.cal-event.not-cb {
  border-bottom: 1px dashed currentColor;
}
/* Highlight mode (when toggle is on) makes them pop */
.cal-highlight-not-cb .span-bar.not-cb {
  outline: 2px dashed #ffeb3b;
  outline-offset: -2px;
}
.cal-highlight-not-cb .cal-event.not-cb {
  outline: 1px dashed #f57f17;
}
.span-bar.custom { color: #fff; }
.span-bar.time-off {
  background: repeating-linear-gradient(
    45deg,
    rgba(120, 130, 145, 0.85),
    rgba(120, 130, 145, 0.85) 6px,
    rgba(160, 170, 180, 0.85) 6px,
    rgba(160, 170, 180, 0.85) 12px
  );
  color: #fff;
  font-style: italic;
}
.span-bar.time-off:hover { filter: brightness(0.95); }
.span-bar.pending {
  background: repeating-linear-gradient(45deg, #e8eaed, #e8eaed 4px, #f5f6f8 4px, #f5f6f8 8px);
  color: #56606b;
  border: 1px dashed #aaa;
}
.span-bar.continues-left { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.span-bar.continues-right { border-top-right-radius: 0; border-bottom-right-radius: 0; }

.bar-legend {
  display: inline-block;
  width: 22px;
  height: 8px;
  border-radius: 2px;
  margin-right: 4px;
  vertical-align: middle;
}
.bar-legend.in-prod { background: #212121; }
.bar-legend.completed { background: #ab47bc; }
.bar-legend.priority { background: #e53935; }
.bar-legend.pending {
  background: repeating-linear-gradient(45deg, #e8eaed, #e8eaed 3px, #fff 3px, #fff 6px);
  border: 1px dashed #aaa;
  height: 6px;
}

/* Tables */
.table-wrap {
  background: #fff;
  border: 1px solid #e1e4e8;
  border-radius: var(--r-md);
  overflow: auto;
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
th, td {
  text-align: left;
  padding: 10px 12px;
  border-bottom: 1px solid #f0f1f3;
  white-space: nowrap;
}
th {
  background: #f8f9fa;
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  color: #56606b;
  cursor: pointer;
  user-select: none;
  position: sticky;
  top: 0;
}
th[data-sort]:hover { background: #eef0f2; }
tbody tr { cursor: pointer; }
tbody tr:hover { background: #f5f7fa; }
.status-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--r-lg);
  font-size: 12px;
  font-weight: 600;
}
.status-parked { background: #fff3e0; color: #e65100; border: 1px dashed #ef6c00; padding: 1px 7px; }
.status-pending { background: #f0f1f3; color: #56606b; }
.status-in_production { background: #212121; color: #fff; }
.status-ready_for_pickup { background: #fff8e1; color: #e65100; }
.status-ready_for_install { background: #16C7C9; color: #fff; }
.status-delivered { background: #f3e5f5; color: #6a1b9a; }
.status-completed { background: #f3e5f5; color: #6a1b9a; }
.status-cancelled { background: #eef0f2; color: #667085; text-decoration: line-through; }

.jobs-controls, .weekly-controls {
  display: flex;
  gap: 12px;
  margin-bottom: 16px;
  flex-wrap: wrap;
  align-items: center;
}
.jobs-view-title { width: 100%; margin: 0 0 2px; font-size: 1.2rem; color: var(--text-heading); }
.filter-count {
  font-size: 12px;
  color: #56606b;
  margin-left: 6px;
  white-space: nowrap;
}
/* POLISH-08: search-input chrome shared with #cal-search above. */
.jobs-controls input[type="search"] {
  flex: 1;
  min-width: 240px;
}
.jobs-controls select, .weekly-controls select, .weekly-controls input {
  padding: 8px 10px;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  font-size: 14px;
  background: #fff;
}

/* Weekly summary */
/* WEEKLY-HEADERS: `table-layout: fixed` hands every column an equal share of
   whatever width it is given, and the headers are nowrap — so on a phone all
   seven columns collapsed to 49px and the labels were sliced mid-word
   ("SCHEDULED TO COMI"). Measured at 375px: "Scheduled to Complete" wanted
   199px and got 49.

   The wrapper (.table-wrap) already has overflow-x: auto, so the scroll was
   there all along; what was missing is a reason for the table to exceed it.
   min-width gives the columns room and hands the overflow to that scroller.

   Paired with letting the headers wrap: a min-width wide enough to keep every
   label on one line would be ~960px, which is a lot of sideways dragging on a
   phone for a table you read top-to-bottom. Two short lines is the better
   trade — full words, much less scrolling. */
#weekly-table { table-layout: fixed; width: 100%; min-width: 560px; }
#weekly-table th { white-space: normal; overflow-wrap: anywhere; }
#weekly-table .col-week { width: 18%; }
#weekly-table th.num, #weekly-table td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  padding-right: 16px;
  width: 16.4%;
}
#weekly-table th, #weekly-table td { vertical-align: middle; }
#weekly-table td small { color: #888; font-weight: 400; margin-left: 2px; }
#weekly-table .variance-pos { color: #2e7d32; }
#weekly-table .variance-neg { color: #d93025; }
#weekly-table tfoot td { font-weight: 600; background: #f8f9fa; border-top: 2px solid #d0d4da; }
#weekly-table tr.month-subtotal td {
  background: #f0f4f8;
  font-weight: 600;
  border-top: 1px solid #d0d4da;
  border-bottom: 1px solid #d0d4da;
}

#weekly-table tr.partial-week td:first-child { color: #555; }
/* Week rows are clickable to drill into the scheduled jobs */
#weekly-table tbody tr:not(.month-subtotal) { cursor: pointer; }
#weekly-table tbody tr:not(.month-subtotal):hover td { background: #f0f6ff; }
#weekly-table tbody tr.month-subtotal { cursor: default; }
.week-jobs-summary {
  padding: 10px 14px;
  background: #f8f9fa;
  border: 1px solid #e1e4e8;
  border-radius: var(--r-md);
  margin-bottom: 14px;
  font-size: 14px;
}
#week-jobs-table tbody tr { cursor: pointer; }
#week-jobs-table tbody tr:hover td { background: #f0f6ff; }
#week-jobs-table tr.flagged td { opacity: 0.6; }
#week-jobs-table .wjt-flag { width: 18px; height: 18px; cursor: pointer; }
#week-jobs-table .wjt-open {
  font-size: 12px; padding: 4px 10px;
}
#weekly-table .partial-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  font-size: 11px;
  font-weight: 500;
  background: #fff3e0;
  color: #e65100;
  border-radius: var(--r-sm);
}

/* Modal */
.modal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}
.modal.hidden { display: none; }
.modal-content {
  background: #fff;
  border-radius: var(--r-lg);
  width: min(900px, 92vw);
  max-height: 92vh;
  overflow: auto;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
}
.modal-content.small { width: min(560px, 92vw); }
#task-modal .modal-content { width: min(860px, 92vw); }
#material-price-modal .modal-content { width: min(860px, 92vw); }
#survey-modal .modal-content { width: min(860px, 92vw); }
#timeoff-modal .modal-content { width: min(820px, 92vw); }
#statuses-modal .modal-content,
#import-modal .modal-content { width: min(860px, 92vw); }
/* POLISH-06: shared modal header chrome — was 32px 56px (huge), now
   matches the CAL-14 hero rhythm (22px 32px). Quieter, more SaaS-like.
   The CAL-14 #modal hero overrides this with its own padding. */
#task-modal .modal-content > header,
#material-price-modal .modal-content > header,
#survey-modal .modal-content > header,
#timeoff-modal .modal-content > header,
#statuses-modal .modal-content > header,
#import-modal .modal-content > header,
#day-modal .modal-content > header,
#modal .modal-content > header {
  padding: 22px 32px;
}
/* Unified modal close × button — applies wherever a modal close
   button has the .modal-close-x class. Replaces the per-modal
   close button sizing variance. */
.modal-close-x {
  background: transparent;
  border: none;
  color: #6b7280;
  font-size: 24px;
  line-height: 1;
  padding: 4px 8px;
  cursor: pointer;
  border-radius: var(--r-sm);
  transition: background 0.1s, color 0.1s;
}
.modal-close-x:hover {
  background: #f1f3f5;
  color: var(--brand-ink);
}
/* Hover preview card for jobs */
.hover-popup {
  position: fixed;
  z-index: 200;
  background: #fff;
  border: 1px solid #d0d4da;
  border-radius: var(--r-lg);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
  padding: 14px 18px;
  width: 340px;
  /* Cap the height so a job with a long description/notes scrolls
     inside the card instead of sprawling over the whole calendar. */
  max-height: 70vh;
  overflow-y: auto;
  font-size: 13px;
  line-height: 1.45;
  pointer-events: none;
  color: #1f2329;
}
/* Long imported notes get a sensible cap inside the card */
.hover-popup .hp-notes {
  max-height: 160px;
  overflow-y: auto;
  font-size: 12px;
}
.hover-popup.hidden { display: none; }
.hover-popup .hp-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.hover-popup .hp-amount {
  margin-left: auto;
  font-weight: 700;
  font-size: 15px;
}
.hover-popup .hp-priority {
  background: #d93025;
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 6px;
  border-radius: var(--r-sm);
  letter-spacing: 0.05em;
}
.hover-popup h3 {
  margin: 0 0 4px 0;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.3;
}
.hover-popup .hp-meta { color: #56606b; font-size: 12px; margin-bottom: 8px; }
.hover-popup .hp-description {
  font-style: italic;
  color: #56606b;
  margin-bottom: 8px;
  border-left: 3px solid #e1e4e8;
  padding-left: 10px;
}
.hover-popup .hp-section {
  border-top: 1px solid #f0f1f3;
  padding-top: 8px;
  margin-top: 8px;
}
.hover-popup .hp-row { display: flex; gap: 6px; margin-bottom: 2px; }
.hover-popup .hp-row strong { color: #56606b; font-weight: 600; min-width: 78px; }
.hover-popup .hp-assignee {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: #f0f1f3;
  padding: 3px 10px 3px 6px;
  border-radius: var(--r-lg);
  font-weight: 600;
  font-size: 12px;
}

.day-list { padding: 18px 24px 24px; display: flex; flex-direction: column; gap: 6px; }
.day-list .cal-event { font-size: 13px; padding: 6px 10px; }
.cal-more {
  display: block;
  font-size: 11px;
  margin-top: 3px;
  padding: 2px 6px;
  color: #16C7C9;
  cursor: pointer;
  font-weight: 600;
  background: none;
  border: none;
  text-align: left;
}
.cal-more:hover { background: #f0f1f3; border-radius: var(--r-sm); }
.modal-content > header {
  background: #fff;
  /* Soft divider that doesn't extend to the absolute edges — looks
     consistent with the inset form padding below. */
  border-bottom: 1px solid #eef0f3;
  padding: 16px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.modal-content > header h2 { margin: 0; font-size: 18px; flex: 1; }
/* Modal bodies had no padding at all, so their content ran flush to the
   modal's edges while the header above sat inset by 20px — which reads as
   cut off. Several bodies contain rounded, bordered summary cards
   (.week-jobs-summary, .duplicates-summary) that were clearly authored
   expecting this inset. Matches the header's 20px.
   #users-modal and #proof-checklist-modal set their own padding and win on
   specificity, so they are unaffected. */
.modal-body { padding: 18px 20px 20px; }
.header-action-btn {
  font-size: 13px;
  padding: 7px 14px;
  background: #16C7C9;
  color: #fff;
  border: 1px solid #16C7C9;
  border-radius: var(--r-md);
  cursor: pointer;
  font-weight: 600;
  margin-right: 4px;
}
.header-action-btn:hover { background: #12B6B8; border-color: #12B6B8; }

/* Quick-action button cluster in the job form header — green tones
   for "mark complete" semantics. Always visible (view + edit modes). */
.quick-actions {
  display: flex;
  gap: 6px;
  margin-right: 8px;
}
/* POLISH-07 (H4): quick-action chrome now uses design tokens for
   consistent dimensions across all 5 buttons. Semantic accent colors
   are preserved (production = purple, install = blue, job-complete =
   green-filled, pending = orange, waiting = red dashed) — the report
   noted these carry meaning. Only the dimensions/font/radius are
   unified, so they no longer look hand-styled. */
.quick-action-btn {
  font-size: var(--fs-sm);
  padding: 6px 12px;
  border-radius: var(--r-md);
  border: 1px solid;
  cursor: pointer;
  font-weight: 600;
  font-family: inherit;
  white-space: nowrap;
  transition: all 0.1s;
}
.quick-action-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.quick-action-btn.quick-prod {
  background: #fff;
  border-color: #ab47bc;
  color: #6a1b9a;
}
.quick-action-btn.quick-prod:hover:not(:disabled) { background: #ab47bc; color: #fff; }
.quick-action-btn.quick-install {
  background: #fff;
  border-color: #16C7C9;
  color: #0E9799;
}
.quick-action-btn.quick-install:hover:not(:disabled) { background: #16C7C9; color: #fff; }
.quick-action-btn.quick-job {
  background: #137333;
  border-color: #137333;
  color: #fff;
}
.quick-action-btn.quick-job:hover:not(:disabled) { background: #0e5e29; border-color: #0e5e29; }
.quick-action-btn.quick-pending {
  background: #fff;
  border-color: #ef6c00;
  color: #8d3b00;
}
.quick-action-btn.quick-pending:hover:not(:disabled) { background: #ef6c00; color: #fff; }
/* CAL-13: + $ Waiting quick action — red theme matching the
   Kanban-card +$ button. Dashed border like its Kanban cousin to
   signal "tag this state" vs the solid-border "complete this work"
   buttons. */
.quick-action-btn.quick-waiting {
  background: #fff;
  border: 1px dashed #c62828;
  color: #c62828;
}
.quick-action-btn.quick-waiting:hover:not(:disabled) {
  background: #c62828;
  color: #fff;
  border-style: solid;
}
/* Already done — show a check + dim */
.quick-action-btn.done {
  background: #e6f4ea;
  border-color: #2e7d32;
  color: #2e7d32;
  cursor: default;
}
.quick-action-btn.done:hover { background: #e6f4ea; }
@media (max-width: 768px) {
  .quick-actions { flex-wrap: wrap; }
  .quick-action-btn { font-size: 11px; padding: 5px 8px; }
}

/* Address row: input + "In Shop" shortcut button side by side */
.address-row {
  display: flex;
  gap: 8px;
  align-items: stretch;
}
.address-row input {
  flex: 1;
  min-width: 0;
}
/* ADDRESS-TRUST: the shop's own address on a job where a crew travels. Amber,
   not red — this is "look at this before dispatch", not "you cannot save".
   Sits directly under the address field so the warning and the thing it is
   about are never separated. */
.addr-warn {
  display: flex; align-items: flex-start; gap: 7px;
  margin-top: 6px; padding: 8px 10px;
  background: #fef6e4; border: 1px solid #f0d08a; border-radius: 8px;
  font-size: .78rem; line-height: 1.35; color: #6b4e12; font-weight: 400;
}
/* The candidate site address. Sits inside the warning on its own line, because
   it is the answer to the question the line above asks. The button is small and
   secondary — accepting it is a judgement, not the obvious default. */
.addr-warn-sugg { margin-top: 6px; padding-top: 6px; border-top: 1px solid rgba(183,121,31,.25); }
.addr-warn-sugg strong { font-weight: 650; }
#addr-use-sugg {
  margin-left: 4px; padding: 2px 8px; border-radius: 5px; cursor: pointer;
  border: 1px solid #d9b25e; background: #fff; color: #6b4e12;
  font-size: .72rem; font-weight: 650;
}
#addr-use-sugg:hover { background: #fffaf0; border-color: #b7791f; }
.addr-warn .ic { flex: none; width: 15px; height: 15px; margin-top: 1px; color: #b7791f; }

.address-shortcut {
  flex-shrink: 0;
  padding: 0 12px;
  border: 1px solid #d0d4da;
  background: #fff;
  border-radius: var(--r-md);
  font-size: 12px;
  font-weight: 600;
  color: #1f2329;
  cursor: pointer;
  font-family: inherit;
  white-space: nowrap;
}
.address-shortcut:hover { background: #eef0f3; border-color: #16C7C9; color: #16C7C9; }
.address-shortcut.active {
  background: #e8f0fe;
  border-color: #16C7C9;
  color: #16C7C9;
}
/* In view mode the button is irrelevant — hide it */
#job-form.view-mode .address-shortcut { display: none; }

/* === Job form: view mode (read-only display) === */
#job-form.view-mode .grid input:not([type="checkbox"]):not([type="file"]),
#job-form.view-mode .grid select,
#job-form.view-mode .grid textarea {
  border-color: transparent !important;
  background: #f5f7fa !important;
  pointer-events: none;
  box-shadow: none !important;
}
#job-form.view-mode .grid input[type="checkbox"] { pointer-events: none; opacity: 0.7; }
/* CREW: view mode — chips stay visible, editing controls hide */
#job-form.view-mode .crew-chip .crew-remove,
#job-form.view-mode #crew-add-select { display: none !important; }
/* Hide everything that's an explicit edit-only action */
#job-form.view-mode #save-btn,
#job-form.view-mode #delete-btn,
#job-form.view-mode #mark-not-complete-btn,
#job-form.view-mode #add-install-2-section,
#job-form.view-mode .install-2-field:has(#remove-install-2-btn),
#job-form.view-mode #spawn-install-panel,
#job-form.view-mode .upload-btn,
#job-form.view-mode #upload-btn-label,
#job-form.view-mode #has-install-toggle {
  display: none !important;
}
#modal-close {
  background: none;
  border: none;
  font-size: 28px;
  line-height: 1;
  cursor: pointer;
  color: #56606b;
  padding: 0 8px;
}
/* CAL-14: job-form padding is now handled per form-section + per
   trailing block (extra-installs / attachments / footer) because the
   form is divided into discrete sections rather than one big padded
   block. The non-job forms keep their original padding. */
#job-form { padding: 0 0 28px 0; }
/* POLISH-06: form padding aligned to CAL-14 rhythm. */
#task-form, #material-price-form, #survey-form, #timeoff-form, #permit-office-form { padding: 24px 32px; }
#job-form > .extra-installs-section,
#job-form > .linked-panel,
#job-form > .attachments-section,
#job-form > .status-history-section {
  margin-left: 32px;
  margin-right: 32px;
}
#job-form > footer { padding-left: 32px; padding-right: 32px; }
@media (max-width: 760px) {
  #job-form > .extra-installs-section,
  #job-form > .linked-panel,
  #job-form > .attachments-section,
  #job-form > .status-history-section { margin-left: 22px; margin-right: 22px; }
  #job-form > footer { padding-left: 22px; padding-right: 22px; }
}

/* Additional install days (INST-04) */
.extra-installs-section {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid #e1e4e8;
}
.extra-installs-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
  gap: 12px;
}
.extra-installs-header h3 {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
}
.extra-installs-hint { font-size: 12px; color: #888; }
.extra-installs-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 8px;
}
.extra-install-row {
  display: grid;
  grid-template-columns: 110px 110px 110px 1fr 130px 30px;
  gap: 8px;
  align-items: center;
  padding: 8px;
  border: 1px solid #e1e4e8;
  border-radius: var(--r-md);
  background: #fafbfc;
}
.extra-install-row.completed { background: #f0f6f0; border-color: #bcdcbc; }
.extra-install-row label {
  display: flex;
  flex-direction: column;
  font-size: 11px;
  font-weight: 600;
  color: #56606b;
  gap: 2px;
  margin: 0;
}
.extra-install-row input,
.extra-install-row select {
  width: 100%;
  padding: 5px 6px;
  font-size: 12px;
  border: 1px solid #d0d4da;
  border-radius: var(--r-sm);
  background: #fff;
}
.extra-install-row .install-day-num {
  font-weight: 700;
  font-size: 13px;
  color: #16C7C9;
  align-self: center;
  text-align: center;
}
.extra-install-row .remove-day {
  background: transparent;
  border: 0;
  font-size: 18px;
  color: #888;
  cursor: pointer;
  padding: 4px;
  line-height: 1;
  border-radius: var(--r-sm);
}
.extra-install-row .remove-day:hover { background: #ffe5e5; color: #C8102E; }
.extra-install-row .install-notes-row {
  grid-column: 1 / -1;
}
.extra-install-row .install-notes-row input {
  font-size: 12px;
}

/* Attachments */
.attachments-section {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid #e1e4e8;
}
/* PIPE-AGE: pipeline status history timeline inside the job modal. */
.status-history-section {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid #e1e4e8;
}
.status-history-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 10px;
}
.status-history-header h3 { margin: 0; font-size: 15px; }
.status-history-hint { font-size: 12px; color: #64748b; }
.status-history-list { display: flex; flex-direction: column; gap: 2px; }
.status-history-empty { font-size: 13px; color: #94a3b8; padding: 4px 0; }
.status-history-item {
  display: grid;
  grid-template-columns: 14px 1fr auto auto;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  border-bottom: 1px dashed #eef1f4;
  font-size: 13px;
}
.status-history-item:last-child { border-bottom: none; }
/* AUDIT-TRAIL: the 5th visible row isn't :last-child once the collapsed
   .audit-trail-rest + toggle button follow it — strip its border too. */
.status-history-item:has(+ .audit-trail-rest) { border-bottom: none; }
/* BRIEF-STAGE-COLLAPSE: same border fix — a row immediately followed by a
   collapsed-run toggle button isn't :last-child either. */
.status-history-item:has(+ .status-history-toggle) { border-bottom: none; }
.audit-trail-toggle, .status-history-toggle {
  display: block;
  margin-top: 6px;
  padding: 0;
  background: none;
  border: none;
  color: #16C7C9;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.audit-trail-toggle:hover, .status-history-toggle:hover { text-decoration: underline; }
.status-history-brief:not(.hidden) { margin-top: 2px; }
.shi-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: #cbd5e1; justify-self: center;
}
.status-history-item.current .shi-dot { background: #16C7C9; box-shadow: 0 0 0 3px rgba(22,199,201,0.15); }
.shi-label { font-weight: 600; color: #1f2329; }
.status-history-item.current .shi-label { color: #16C7C9; }
.shi-span { color: #475569; font-variant-numeric: tabular-nums; }
.shi-date { color: #94a3b8; font-size: 11px; font-variant-numeric: tabular-nums; }
/* Optional note attached to a backward-move entry (see confirmBackwardMove
   in app.js) — sits on its own row under the label, spanning the rest of
   the grid so it wraps naturally instead of squeezing into one column. */
.shi-note {
  grid-column: 2 / -1;
  color: #64748b;
  font-size: 12px;
  font-style: italic;
}
.attachments-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.attachments-header h3 {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
}
.upload-btn {
  font-size: 13px;
  padding: 7px 12px;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  background: #fff;
  cursor: pointer;
  font-weight: 500;
}
.upload-btn:hover { background: #f0f1f3; border-color: #16C7C9; color: #16C7C9; }
.jobshot-open-btn {
  font-size: 13px;
  padding: 7px 12px;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  background: #fff;
  cursor: pointer;
  font-weight: 500;
  text-decoration: none;
  display: inline-block;
  color: #1f2329;
}
.jobshot-open-btn:hover { background: #f0f1f3; border-color: #16C7C9; color: #16C7C9; }
.ics-link { float: right; font-size: 12px; font-weight: 600; color: #16C7C9; text-decoration: none; }
.ics-link:hover { text-decoration: underline; }
.attachments-hint { font-size: 12px; color: #888; margin: 0; }
.attachments-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 10px;
  margin-top: 6px;
}
.attachment-card {
  position: relative;
  border: 1px solid #e1e4e8;
  border-radius: var(--r-md);
  padding: 8px;
  background: #fafbfc;
  text-align: center;
  font-size: 11px;
  cursor: pointer;
  word-break: break-word;
  line-height: 1.3;
  overflow: hidden;
}
.attachment-card:hover { border-color: #16C7C9; background: #fff; }
.attachment-thumb {
  width: 100%;
  height: 80px;
  object-fit: cover;
  border-radius: var(--r-sm);
  margin-bottom: 6px;
  display: block;
}
.attachment-icon {
  width: 100%;
  height: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 32px;
  color: #d93025;
  background: #fff;
  border: 1px dashed #e1e4e8;
  border-radius: var(--r-sm);
  margin-bottom: 6px;
}
.attachment-name {
  font-weight: 500;
  color: #1f2329;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.attachment-size { color: #888; font-size: 10px; margin-top: 1px; }
.attachment-date-header {
  grid-column: 1 / -1;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #888;
  margin: 10px 0 -2px;
  padding-top: 8px;
  border-top: 1px solid #e1e4e8;
}
.attachment-date-header:first-child { margin-top: 0; padding-top: 0; border-top: none; }
.attachment-delete {
  position: absolute;
  top: 4px;
  right: 4px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid #d0d4da;
  border-radius: 50%;
  width: 22px;
  height: 22px;
  font-size: 14px;
  line-height: 18px;
  cursor: pointer;
  padding: 0;
  color: #56606b;
  opacity: 1;
  transition: background 0.1s, border-color 0.1s;
}
.attachment-delete:hover { background: #d93025; color: #fff; border-color: #d93025; }
.reminder-row {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid #e1e4e8;
  border-radius: var(--r-md);
  padding: 8px 10px;
  background: #fafbfc;
  font-size: 12px;
  margin-bottom: 6px;
}
.reminder-row.is-sent { opacity: 0.55; }
.reminder-row-main { flex: 1; min-width: 0; }
.reminder-row-when { font-weight: 600; color: #1f2329; }
.reminder-row-note { color: #56606b; margin-top: 1px; word-break: break-word; }
.reminder-delete {
  background: #fff;
  border: 1px solid #d0d4da;
  border-radius: 50%;
  width: 22px;
  height: 22px;
  font-size: 14px;
  line-height: 18px;
  cursor: pointer;
  padding: 0;
  color: #56606b;
  flex: none;
}
.reminder-delete:hover { background: #d93025; color: #fff; border-color: #d93025; }
.reminder-form {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 6px;
}
.reminder-form select,
.reminder-form input[type="datetime-local"] {
  padding: 6px 8px;
  border: 1px solid #d0d4da;
  border-radius: var(--r-sm);
  font-size: 12px;
}
.reminder-form input[type="text"] {
  flex: 1;
  min-width: 140px;
  padding: 6px 8px;
  border: 1px solid #d0d4da;
  border-radius: var(--r-sm);
  font-size: 12px;
}
.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 26px 22px;
}
#change-password-form .grid { padding: 22px 24px 4px; }
#change-password-form footer {
  display: flex; gap: 10px; align-items: center;
  margin: 22px 0 0; padding: 16px 24px;
  border-top: 1px solid #eef0f3;
}
/* QC-GATE: Pending QC card widget — shows who requested the move and
   where it's headed, plus the only two valid next actions. Always
   visible (unlike ⇄ Move, which is mobile-only) since dragging a
   Pending QC card is a no-op on any device — Confirm/Send back are the
   only way off this column. */
.kanban-card-qc-pending {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed #cfe0fb;
}
.kanban-card-qc-requested {
  font-size: 11px;
  color: #56606b;
  margin-bottom: 6px;
}
/* QC-READINESS: what a reviewer needs before signing a job off. Blockers are
   amber and disable Confirm; notes are quiet and only inform. Both sit between
   "requested by" and the buttons, so they're read on the way to the click. */
.kanban-card-qc-blockers {
  display: flex; align-items: flex-start; gap: 5px;
  margin-top: 5px; padding: 4px 6px;
  background: #fef6e4; border: 1px solid #f0d08a; border-radius: 6px;
  font-size: .68rem; line-height: 1.3; color: #6b4e12;
}
.kanban-card-qc-blockers .ic { flex: none; width: 12px; height: 12px; margin-top: 1px; color: #b7791f; }
.kanban-card-qc-notes { margin-top: 4px; font-size: .67rem; color: var(--text-muted); line-height: 1.3; }
.kanban-card-qc-confirm:disabled { opacity: .45; cursor: not-allowed; }
.kanban-card-qc-actions {
  display: flex;
  gap: 6px;
}
.kanban-card-qc-confirm,
.kanban-card-qc-cancel {
  flex: 1;
  padding: 6px 0;
  font-size: 11px;
  font-weight: 600;
  border-radius: var(--r-md);
  cursor: pointer;
  font-family: inherit;
}
.kanban-card-qc-confirm {
  color: #fff;
  background: #16C7C9;
  border: 1px solid #16C7C9;
}
.kanban-card-qc-confirm:hover { background: #10a3a5; }
.kanban-card-qc-cancel {
  color: #56606b;
  background: #fff;
  border: 1px solid #d7dde3;
}
.kanban-card-qc-cancel:hover { background: #f4f6f8; }

/* PROOF-CHECKLIST: not a <form>, so modal-body/footer need explicit
   chrome (this app only styles those scoped to a specific modal ID). */
#proof-checklist-modal .modal-content { max-width: 640px; }
#proof-checklist-modal .modal-body {
  padding: 20px 24px;
  max-height: 60vh;
  overflow-y: auto;
}
#proof-checklist-modal .modal-body h4 {
  margin: 18px 0 8px;
  font-size: var(--fs-sm);
  color: #56606b;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
#proof-checklist-modal .modal-body h4:first-of-type { margin-top: 0; }
#proof-checklist-modal footer {
  display: flex; gap: 10px; align-items: center;
  padding: 16px 24px;
  border-top: 1px solid #eef0f3;
}
.proof-progress {
  display: inline-block;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--action-blue);
  background: #f0f9ff;
  border: 1px solid #cfe0fb;
  border-radius: var(--r-md);
  padding: 4px 10px;
}
.proof-module-hint {
  font-size: var(--fs-xs);
  color: #94a3b8;
  margin: 0 0 8px;
}
.proof-check-item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 6px 0;
  font-size: var(--fs-sm);
  color: var(--text-body);
  cursor: pointer;
}
.proof-check-item input { margin-top: 2px; }
.proof-module-toggles {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  padding-bottom: 4px;
}
.proof-module-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-sm);
  color: var(--text-body);
  cursor: pointer;
}
.proof-module-section {
  margin-top: 10px;
  padding: 10px 12px;
  background: #fafbfc;
  border: 1px solid #eef0f3;
  border-radius: var(--r-md);
}
.proof-module-section h4 { margin-top: 0; }
.proof-line-qty {
  font-weight: 400;
  color: #94a3b8;
  font-size: var(--fs-xs);
}
.proof-line-category {
  font-size: var(--fs-xs);
  color: #94a3b8;
  margin: -4px 0 8px;
}
.proof-line-module-select {
  display: block;
  width: 100%;
  max-width: 280px;
  margin-bottom: 8px;
  padding: 6px 8px;
  font-size: var(--fs-sm);
  border: 1px solid #d7dde3;
  border-radius: var(--r-md);
  background: #fff;
  color: var(--text-body);
  font-family: inherit;
}
.proof-loading {
  color: #94a3b8;
  font-size: var(--fs-sm);
  padding: 20px 0;
  text-align: center;
}
.proof-invoice-recap {
  margin: 0 0 12px;
  padding: 6px 14px;
  background: #f0f9ff;
  border: 1px solid #cfe0fb;
  border-radius: var(--r-md);
  list-style: none;
  font-size: var(--fs-sm);
  color: var(--text-body);
}
.proof-invoice-recap li { padding: 0; }
.proof-invoice-recap .proof-check-item { padding: 6px 0; }

/* DESIGN-THROUGHPUT: weekly goal row on the "Out of Design" admin card. */
.admin-design-goal-row {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  font-size: var(--fs-sm);
  color: #56606b;
  margin: 4px 0 14px;
}
.admin-design-goal-row label {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.admin-design-goal-row input[type="number"] {
  width: 70px;
  padding: 4px 6px;
  border: 1px solid #d7dde3;
  border-radius: var(--r-sm);
  font-family: inherit;
  font-size: inherit;
}
.admin-design-goal-row button {
  font-size: var(--fs-sm);
  font-weight: 600;
  padding: 4px 12px;
  border-radius: var(--r-sm);
  border: 1px solid var(--action-blue);
  background: var(--action-blue);
  color: #fff;
  cursor: pointer;
  font-family: inherit;
}
.admin-design-goal-row button:hover { background: var(--action-blue-dark); }
.admin-design-goal-saved {
  color: #137333;
  font-weight: 600;
}
.admin-goal-hit { color: #137333; font-weight: 600; }
.admin-goal-miss { color: #94a3b8; }
.admin-design-week-row { cursor: pointer; }
#design-week-table tr.design-drilldown-row { cursor: pointer; }
#design-week-table tr.design-drilldown-row:hover { background: #f5f7fa; }
.grid .full { grid-column: 1 / -1; }
.grid label {
  display: flex;
  flex-direction: column;
  font-size: 13px;
  font-weight: 600;
  color: #56606b;
  gap: 4px;
}
.grid input, .grid select, .grid textarea {
  font-family: inherit;
  font-size: 14px;
  padding: 11px 14px;
  border: 1px solid #b8bec8;
  border-radius: var(--r-md);
  background: #fff;
  font-weight: normal;
  color: #1f2329;
  transition: border-color 0.1s, box-shadow 0.1s;
  /* Constrain to the grid column — without these, native form
     controls (especially <select> and <input type="date">) size
     themselves by content/user-agent and can spill past the column
     boundary, making the dropdown popup render absurdly wide. */
  width: 100%;
  max-width: 100%;
  min-width: 0;
  box-sizing: border-box;
}
/* Long option text (job company names run 80+ characters) shouldn't be
   able to widen the closed box past the column above — truncate instead. */
.grid select { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grid input:focus, .grid select:focus, .grid textarea:focus {
  outline: none;
  border-color: #16C7C9;
  /* Softer focus indicator — was 3px @ 18% alpha which read as a hard
     blue stripe across full-width inputs and made the form look
     unbalanced when the field auto-focused on open. */
  box-shadow: 0 0 0 2px rgba(22,199,201, 0.10);
}
.grid input:hover:not(:focus), .grid select:hover:not(:focus), .grid textarea:hover:not(:focus) {
  border-color: #8a92a0;
}
.grid textarea { resize: vertical; }
.grid input[type="checkbox"] {
  width: 16px;
  height: 16px;
  padding: 0;
  margin: 0;
}
.checkbox-row {
  flex-direction: row !important;
  align-items: center;
  gap: 8px !important;
  font-weight: 600;
  color: #1f2329 !important;
}
#job-form.no-install .install-field { display: none; }
#job-form.no-production .production-field { display: none; }
.hint-inline { font-size: 11px; color: #6b7280; margin-left: 8px; font-weight: 400; }

/* PROD-BTN: button-driven production-completed control */
.prod-complete-control { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
.prod-complete-control .pcc-label { font-size: 12px; font-weight: 600; color: #56606b; width: 100%; }
.pcc-mark-btn {
  border: 1px solid #16C7C9; background: #16C7C9; color: #fff;
  font-weight: 600; font-size: 13px; border-radius: 8px; padding: 7px 14px; cursor: pointer;
}
.pcc-mark-btn:hover { background: #0E9799; border-color: #0E9799; }
.pcc-done { font-size: 13px; font-weight: 600; color: #1b7a1b; display: inline-flex; align-items: center; gap: 8px; }
.pcc-done strong { color: #1f2329; }
.pcc-none { font-size: 13px; color: #94a3b8; }
.pcc-pick { font-size: 12px; color: #56606b; display: inline-flex; align-items: center; gap: 6px; }
.pcc-pick input[type="date"] { padding: 4px 6px; }

/* Inline action button (e.g. "Mark not complete" next to a date input) */
.input-with-action {
  display: flex;
  align-items: center;
  gap: 8px;
}
.input-with-action input { flex: 1; }
.link-btn {
  background: none;
  border: none;
  color: #16C7C9;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  padding: 4px 6px;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.link-btn:hover { color: #0E9799; background: #f0f1f3; border-radius: var(--r-sm); }
.link-btn-danger { color: #d93025; }
.link-btn-danger:hover { color: #b71c1c; }

/* Linked-job panel (production ↔ install) */
/* POLISH-13 (M3): linked-panel chrome now uses the same blue family
   as the rest of the app (action-blue) instead of Google Material's
   light-blue-100/300 palette. */
.linked-panel {
  grid-column: 1 / -1;
  background: #eef4fc;
  border: 1px solid #c9dcf3;
  border-radius: var(--r-md);
  padding: 12px 14px;
  margin-top: 4px;
  font-size: var(--fs-sm);
}
.linked-panel-header {
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--action-blue);
  margin-bottom: 6px;
}
.linked-panel-info { margin-bottom: 6px; line-height: 1.5; }
#parent-panel { background: #f3e5f5; border-color: #ce93d8; }
#parent-panel .linked-panel-header { color: #6a1b9a; }

.checkpoint-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
  font-size: 13px;
}
.check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  font-size: 13px;
  font-weight: 700;
  flex-shrink: 0;
}
.check-done { background: #2e7d32; color: #fff; }
.check-pending { background: #fff; color: #56606b; border: 2px solid #b8bec8; font-weight: 400; }
.money-note {
  margin-top: 8px;
  padding: 6px 10px;
  border-radius: var(--r-sm);
  font-size: 12px;
  font-weight: 600;
}
.money-counted { background: #e8f5e9; color: #1b5e20; }
.money-pending { background: #fff8e1; color: #856404; }
#job-form footer, #task-form footer, #material-price-form footer, #survey-form footer, #timeoff-form footer, #rework-form footer, #permit-office-form footer {
  display: flex;
  gap: 10px;
  margin-top: 28px;
  padding-top: 22px;
  /* Soft divider — matches the header style above */
  border-top: 1px solid #eef0f3;
  align-items: center;
}
.spacer { flex: 1; }
.hidden { display: none !important; }

/* Dropdown */
.dropdown { position: relative; }
.dropdown-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  background: #fff;
  border: 1px solid #e1e4e8;
  border-radius: var(--r-md);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
  min-width: 160px;
  padding: 4px;
  z-index: 50;
}
.dropdown-menu button {
  display: block;
  width: 100%;
  padding: 9px 14px;
  text-align: left;
  border: none;
  border-radius: var(--r-sm);
  background: transparent;
  font-size: 14px;
  font-weight: 500;
}
.dropdown-menu button:hover { background: #f0f1f3; }
.dropdown-menu button.menu-danger { color: #d93025; border-top: 1px solid #f0f1f3; margin-top: 4px; padding-top: 12px; }
.dropdown-menu button.menu-danger:hover { background: #fce8e6; }

/* CREW: "Also assigned" picker in the job modal */
.crew-picker {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.crew-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.crew-chips:empty { display: none; }
.crew-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  padding: 2px 6px 2px 6px;
  border-radius: var(--r-lg);
  background: #f0f1f3;
  color: #1f2329;
}
.crew-chip .crew-remove {
  border: none;
  background: none;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0 2px;
  color: #6b7280;
}
.crew-chip .crew-remove:hover { color: #d93025; }

/* Assignee badges */
.assignee-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  padding: 2px 8px 2px 4px;
  border-radius: var(--r-lg);
  background: #f0f1f3;
  color: #1f2329;
}
.assignee-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #888;
  flex-shrink: 0;
}
.assignee-stripe {
  display: inline-block;
  width: 6px;
  height: 14px;
  border-radius: 2px;
  margin-right: 4px;
  vertical-align: middle;
}
.span-bar .assignee-stripe {
  height: 100%;
  width: 4px;
  border-radius: var(--r-sm) 0 0 4px;
  margin-right: 6px;
  margin-left: -8px;
}

/* Task chips on calendar */
.cal-event.material-ordered {
  background: #ffe0b2;
  color: #e65100;
  border-left: 3px solid #fb8c00;
  font-weight: 600;
}
.cal-event.material-delivery {
  background: #b2dfdb;
  color: #004d40;
  border-left: 3px solid #00897b;
  font-weight: 600;
}
.cal-event.material-cancelled {
  text-decoration: line-through;
  opacity: 0.6;
}
.cal-event.survey {
  background: #fce4ec;
  color: #880e4f;
  border-left: 3px solid #ec407a;
  font-weight: 600;
}
.cal-event.survey.cancelled, .cal-event.survey.completed {
  text-decoration: line-through;
  opacity: 0.7;
}

/* Surveys weekly view */
.surv-day {
  background: #fff;
  border: 1px solid #e1e4e8;
  border-radius: var(--r-md);
  margin-bottom: 12px;
  overflow: hidden;
}
.surv-day-header {
  background: #f8f9fa;
  padding: 10px 16px;
  font-weight: 600;
  font-size: 13px;
  display: flex;
  justify-content: space-between;
  border-bottom: 1px solid #e1e4e8;
}
.surv-day-header .surv-day-count {
  font-weight: 400;
  color: #56606b;
}
.surv-day.today .surv-day-header { background: #fff8dc; }
.surv-day-empty { padding: 14px 16px; color: #888; font-style: italic; font-size: 13px; }
.surv-row {
  display: grid;
  grid-template-columns: 90px 1fr 180px 120px 110px 1fr;
  gap: 12px;
  padding: 10px 16px;
  border-bottom: 1px solid #f0f1f3;
  font-size: 13px;
  cursor: pointer;
  align-items: center;
}
.surv-row:last-child { border-bottom: none; }
.surv-row:hover { background: #f5f7fa; }
.surv-row .surv-time { font-weight: 600; }
.surv-row .surv-customer { font-weight: 600; }
.surv-row .surv-address { color: #56606b; font-size: 12px; }
.surv-row .surv-assignee {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
}
.cal-event.task {
  background: #f1f5fb;
  color: #1f2329;
  border-left: 3px solid #888;
  display: flex;
  align-items: center;
  gap: 4px;
}
.cal-event.task::before {
  content: "☐";
  font-size: 11px;
  color: #56606b;
}
.cal-event.task.completed::before { content: "☑"; }
.cal-event.task.completed { text-decoration: line-through; opacity: 0.7; }

/* Tasks table */
#tasks-table .task-checkbox {
  width: 18px;
  height: 18px;
  cursor: pointer;
}
#tasks-table tr.completed .task-title { text-decoration: line-through; color: #888; }

/* Team roster (now a section within the Settings modal, not its own modal) */
.team-table { width: 100%; border-collapse: collapse; margin-bottom: 16px; }
.team-table th { background: #f8f9fa; padding: 8px 10px; text-align: left; font-size: 11px; text-transform: uppercase; color: #56606b; border-bottom: 1px solid #e1e4e8; }
.team-table td { padding: 8px 10px; border-bottom: 1px solid #f0f1f3; }
.team-color-input {
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid #d0d4da;
  border-radius: 50%;
  cursor: pointer;
  background: none;
}
.team-name-input {
  border: 1px solid transparent;
  background: transparent;
  font-size: 14px;
  padding: 4px 6px;
  width: 100%;
  font-family: inherit;
}
.team-name-input:hover, .team-name-input:focus {
  border-color: #d0d4da;
  background: #fff;
  outline: none;
}
.team-type-select,
.team-position-select {
  border: 1px solid #d0d4da;
  border-radius: var(--r-sm);
  padding: 4px 6px;
  font-size: 13px;
  background: #fff;
}
.team-add {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}
.team-add input { flex: 1; padding: 8px 10px; border: 1px solid #d0d4da; border-radius: var(--r-md); font-size: 14px; font-family: inherit; }
.team-add select { padding: 8px 10px; border: 1px solid #d0d4da; border-radius: var(--r-md); font-size: 14px; background: #fff; }
.add-heading { font-size: 13px; text-transform: uppercase; color: #56606b; margin: 24px 0 4px; letter-spacing: 0.04em; }
#statuses-modal footer { display: flex; padding: 16px 28px; border-top: 1px solid #e1e4e8; }

/* Corebridge tool modals (dated import, audit-by-invoice, WIP reconcile)
   share .person-body, which had no padding at all — content ran edge to
   edge. Matches the .import-body rhythm used elsewhere. */
.person-body { padding: 24px 28px; }
#dated-import-modal footer,
#audit-modal footer,
#wip-reconcile-modal footer {
  display: flex; align-items: center; gap: 10px;
  padding: 16px 28px; border-top: 1px solid #e1e4e8;
}
/* WIP reconcile has the widest table (7 columns) and is the tool people
   spend the most time in — give it more room on a large screen instead
   of capping at the same 900px as a simple form modal. */
#wip-reconcile-modal .modal-content.modal-wide { width: min(1200px, 94vw); max-height: 88vh; }
#wip-reconcile-modal .preview-table th,
#wip-reconcile-modal .preview-table td { padding: 8px 12px; }
/* Users & logins table grew to 10 columns (FP/QC alerts, Hide $, Admin
   dash, actions) — even the 1100px .modal-wide cap forced a horizontal
   scrollbar on typical laptop screens. Wider cap + tighter cells (below)
   fit every column without scrolling on anything but a narrow window,
   where .table-wrap's own overflow: auto still kicks in as a fallback. */
#users-modal .modal-content.modal-wide { width: min(1300px, 96vw); max-height: 88vh; }
#users-table th, #users-table td { padding: 8px 8px; white-space: nowrap; }
#users-table td:nth-child(2) { max-width: 220px; overflow: hidden; text-overflow: ellipsis; }
/* modal-body has no padding by default — every section here relied on its
   own box (.users-add's card) for breathing room. The My Account section
   has no such box, so it sat flush against the header/edges. Padding the
   whole body fixes that consistently for every section, not just this one. */
#users-modal .modal-body { padding: 20px 24px 24px; }

/* Import modal */
.import-body { padding: 24px 28px; }
.import-body p { margin: 0 0 14px 0; line-height: 1.5; }
.import-body code { background: #f0f1f3; padding: 1px 5px; border-radius: var(--r-sm); font-size: 12px; }
.file-drop {
  display: block;
  border: 2px dashed #d0d4da;
  border-radius: var(--r-md);
  padding: 24px;
  text-align: center;
  cursor: pointer;
  background: #fafbfc;
  font-weight: 600;
  color: #56606b;
}
.file-drop:hover { background: #f0f1f3; border-color: #16C7C9; color: #16C7C9; }
.error { color: #d93025; font-size: 13px; min-height: 18px; margin-top: 10px; }
.hint { font-size: 12px; color: #56606b; }
.preview-wrap {
  max-height: 320px;
  overflow: auto;
  border: 1px solid #e1e4e8;
  border-radius: var(--r-md);
  margin-top: 10px;
}
.preview-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.preview-table th, .preview-table td { padding: 6px 10px; border-bottom: 1px solid #f0f1f3; text-align: left; }
.preview-table th { background: #f8f9fa; position: sticky; top: 0; font-size: 11px; text-transform: uppercase; }
.preview-table td:first-child, .preview-table th:first-child { width: 30px; text-align: center; }
#import-modal footer {
  display: flex;
  gap: 10px;
  padding: 16px 28px;
  border-top: 1px solid #e1e4e8;
  align-items: center;
}

/* Action button cell */
td.actions { width: 1%; }
.icon-btn {
  background: none;
  border: none;
  font-size: 16px;
  cursor: pointer;
  color: #56606b;
  padding: 4px 8px;
}
.icon-btn:hover { color: #16C7C9; background: #f0f1f3; border-radius: var(--r-sm); }

/* ====================================================================
   Mobile / responsive
   ==================================================================== */
@media (max-width: 768px) {
  body { font-size: 14px; }

  /* Header — wraps; nav becomes a horizontal-scroll strip */
  header {
    padding: 10px 14px;
    flex-wrap: wrap;
    gap: 8px;
  }
  header h1 { font-size: 16px; flex: 0 0 auto; }
  nav {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    flex-wrap: nowrap;
    gap: 6px;
    padding-bottom: 4px;
    scrollbar-width: thin;
  }
  nav button, nav .tab {
    font-size: 13px;
    padding: 7px 12px;
    flex-shrink: 0;
    min-height: 40px;  /* touch-target */
  }

  /* The nav's overflow-x:auto scroll strip clips absolutely-positioned
     children, so the bell / Manage / + New dropdowns opened invisibly.
     Fixed positioning escapes the scroll box — pin them just under the
     header row, near full-width. */
  .topbar-actions .dropdown-menu {
    position: fixed;
    top: 72px;
    left: 10px;
    right: 10px;
    width: auto;
    max-height: min(70vh, 480px);
    overflow-y: auto;
  }
  /* The notif panel is itself a .dropdown-menu, so its small head
     buttons (⚙ / + Send / Mark all read) inherit width:100% from
     .dropdown-menu button and flex-shrink:0 from the nav touch-target
     rule above — each ballooning to full width and forcing the panel
     to scroll sideways. Restore their compact inline size. */
  .notif-panel-head button {
    width: auto;
    flex-shrink: 1;
    min-height: 0;
    padding: 4px 8px;
    font-size: 12px;
    white-space: nowrap;
  }

  main { padding: 12px; }

  /* Calendar controls */
  .cal-controls { flex-wrap: wrap; gap: 8px; }
  .cal-controls h2 { font-size: 16px; min-width: 0; flex: 1; text-align: center; }
  .cal-views { margin-left: 0; }
  .cal-view-btn { padding: 8px 14px; min-height: 38px; }
  .legend { width: 100%; margin-left: 0; font-size: 11px; gap: 8px; }
  .toggle { font-size: 12px; }

  /* Calendar cells on small screens — shorter than desktop but tall
     enough to show several events. Each cell still scrolls internally
     when it has more, and the overflow button takes over past 15. */
  #calendar.view-month .cal-week { height: 200px; }
  #calendar.view-2week .cal-week { height: 320px; }
  #calendar.view-week .cal-week { height: 70vh; min-height: 420px; }
  .cal-header > div { padding: 6px 2px; font-size: 10px; }
  .cal-day {
    padding: 2px;
    padding-top: calc(22px + var(--lanes, 0) * 18px);
  }
  .cal-day .day-number { font-size: 11px; top: 3px; left: 4px; }
  .cal-day.today .day-number { width: 20px; height: 20px; font-size: 10px; }
  .cal-event { font-size: 10px; padding: 1px 4px; line-height: 1.25; }
  .span-bar { height: 16px; font-size: 10px; padding: 0 6px; }
  /* No hover affordance on touch */
  .cal-day::after { display: none; }
  .cal-day { cursor: default; }

  /* Hover popup is desktop-only */
  .hover-popup { display: none !important; }

  /* Squeezing 7 columns into a phone width left each ~50px wide — event
     chips truncated to 3-4 characters ("291...", "Co...") and were
     unreadable without opening every job. Give each day a real minimum
     width instead and let the whole grid scroll horizontally; the header
     row and every week row are siblings inside #calendar, so scrolling
     that one container keeps them all in sync. Span-bar positions are
     percentages of the row's own width (see renderCalendar in app.js), so
     they stay correct at any column width without JS changes. */
  /* Without an explicit cap, the fixed 924px-wide grid below pulls both
     #calendar and .cal-main out to its own min-content width instead of
     clipping/scrolling — overflow:auto alone didn't stop it in testing. */
  .cal-main { max-width: 100%; }
  #calendar { overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; max-width: 100%; }
  .cal-header, .cal-week { grid-template-columns: repeat(7, 132px); width: max-content; }

  /* Modals: keep them centered with breathing room on narrow desktop
     / split-screen windows. Only true phones (<480px below) go
     full-screen. Padding matches the desktop look (40/56 split) so a
     narrow-window user still gets the same visual breathing room. */
  .modal-content > header { padding: 32px 56px; }
  /* CAL-14: keep the per-section model on narrow screens too —
     restore only the non-job-form padding here. */
  /* POLISH-06: form padding aligned to CAL-14 rhythm. */
#task-form, #material-price-form, #survey-form, #timeoff-form, #permit-office-form { padding: 24px 32px; }
  .import-body { padding: 28px 36px; }
  #modal-close,
  #task-modal-close, #material-price-modal-close, #survey-modal-close,
  #timeoff-modal-close,
  #statuses-modal-close, #day-modal-close, #import-close {
    font-size: 32px; padding: 4px 12px;
  }
  .grid { grid-template-columns: 1fr; gap: 14px; }
  /* iOS zooms inputs when font-size < 16px — bump to prevent that jolt */
  .grid input, .grid select, .grid textarea { font-size: 16px; }

  /* Form footer buttons: bigger touch targets */
  #job-form footer button,
  #task-form footer button,
  #material-price-form footer button,
  #survey-form footer button,
  #timeoff-form footer button { min-height: 42px; padding: 10px 18px; }

  /* Tables become horizontally scrollable; slimmer rows */
  .table-wrap { overflow-x: auto; }
  table { font-size: 12px; }
  th, td { padding: 8px 10px; }

  /* Surveys: stack the row layout into label / value pairs */
  .surv-row {
    grid-template-columns: 80px 1fr;
    gap: 4px 12px;
  }
  .surv-row > div:nth-child(1) { grid-column: 1; }
  .surv-row > div:nth-child(2) { grid-column: 2; grid-row: 1 / span 5; }
  .surv-row > div:nth-child(n+3) { grid-column: 1 / -1; }
}

/* Tighter still for phones */
@media (max-width: 480px) {
  header h1 { display: none; } /* save horizontal space; tabs are clear enough */
  .cal-controls h2 { font-size: 14px; }
  #calendar.view-month .cal-week { height: 80px; }
  .cal-event { font-size: 9px; }
  .legend { gap: 6px; }
  .legend > * { font-size: 10px; }
  /* True phones: modals go full-screen (the centered card pattern
     doesn't have room to breathe at this size). */
  .modal { padding: 0; align-items: stretch; justify-content: stretch; }
  .modal-content,
  #task-modal .modal-content,
  #material-price-modal .modal-content,
  #survey-modal .modal-content,
  #timeoff-modal .modal-content,
  #statuses-modal .modal-content,
  #import-modal .modal-content,
  .modal-content.small {
    width: 100% !important;
    height: 100vh;
    max-height: 100vh;
    border-radius: 0;
  }
  .modal-content > header { padding: 18px 22px; }
  #job-form, #task-form, #material-price-form, #survey-form, #timeoff-form, #permit-office-form { padding: 22px; }
}

/* ---------- Calendar layout with pending sidebar ---------- */
.cal-layout {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}
.cal-main { flex: 1; min-width: 0; }
/* Right column that holds both the Pending and Parked sidebars,
   stacked vertically. The column sticks; each sidebar scrolls
   internally. */
.cal-side-column {
  width: 300px;
  flex-shrink: 0;
  position: sticky;
  top: 16px;
  max-height: calc(100vh - 32px);
  display: flex;
  flex-direction: column;
  gap: 14px;
  overflow-y: auto;
}
.pending-sidebar {
  /* UI-02-C: match calendar chrome — 16px radius, soft shadow, slate
     border. Keeps the pending rail feeling like a sibling surface
     rather than a flat utility panel. */
  width: 100%;
  flex-shrink: 0;
  background: var(--bg-surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-md);
  display: flex;
  flex-direction: column;
  min-height: 0;
}
/* Parked sidebar = same shape, orange accent so it's visually distinct */
.pending-sidebar.parked-sidebar > header {
  background: #fff8e1;
  border-bottom-color: #ffe0b2;
}
.parked-side-count {
  background: #fff3e0 !important;
  color: #e65100 !important;
}
.parked-side-count.zero { background: #eef0f3 !important; color: #6b7280 !important; }

/* Pending-install-schedule sidebar — green accent (ready-for-install vibe) */
.pending-sidebar.schedule-sidebar > header {
  background: #e6f4ea;
  border-bottom-color: #b7dfbf;
}
.schedule-side-count {
  background: #e6f4ea !important;
  color: #137333 !important;
}
.schedule-side-count.zero { background: #eef0f3 !important; color: #6b7280 !important; }
.show-schedule-sidebar-btn {
  font-size: 13px;
  font-weight: 500;
  padding: 4px 10px;
  border-radius: var(--r-md);
  border: 1px solid #137333;
  background: #e6f4ea;
  color: #0e5e29;
  cursor: pointer;
  font-family: inherit;
}
.show-schedule-sidebar-btn:hover { background: #c8e6c9; }
.show-schedule-sidebar-btn #show-schedule-sidebar-count {
  display: inline-block;
  background: #137333;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  margin-left: 4px;
}

/* Install-whenever sidebar — blue accent (ready, but no committed date) */
.pending-sidebar.anytime-sidebar > header {
  background: #e8f0fe;
  border-bottom-color: #c6dafc;
}
.anytime-side-count {
  background: #e8f0fe !important;
  color: #1a56c4 !important;
}
.anytime-side-count.zero { background: #eef0f3 !important; color: #6b7280 !important; }
.show-anytime-sidebar-btn {
  font-size: 13px;
  font-weight: 500;
  padding: 4px 10px;
  border-radius: var(--r-md);
  border: 1px solid #16C7C9;
  background: #e8f0fe;
  color: #174ea6;
  cursor: pointer;
  font-family: inherit;
}
.show-anytime-sidebar-btn:hover { background: #d2e3fc; }
.show-anytime-sidebar-btn #show-anytime-sidebar-count {
  display: inline-block;
  background: #16C7C9;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  margin-left: 4px;
}
/* "Waiting Nd" age on the install-whenever card — neutral by default,
   amber past a week, red past a month so stale jobs stand out. */
.psc-wait {
  display: inline-block;
  margin: 4px 0 2px;
  font-size: 11px;
  font-weight: 600;
  padding: 1px 7px;
  border-radius: var(--r-pill);
  background: #e8f0fe;
  color: #174ea6;
}
.psc-wait.psc-wait-aging { background: #fef3d7; color: #96590a; }
.psc-wait.psc-wait-old { background: #fce8e6; color: #b3261e; }
.pending-sidebar > header {
  padding: 12px 14px;
  border-bottom: 1px solid #eef0f3;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  background: #fafbfc;
  border-radius: var(--r-lg) 10px 0 0;
}
.pending-sidebar h3 { margin: 0; font-size: 14px; font-weight: 600; flex: 1; }
/* Drag-to-reorder: the header is the grab handle. A grip glyph hints it, and
   the panel dims while it's being dragged. */
.pending-sidebar > header.panel-drag-handle { cursor: grab; }
.pending-sidebar > header.panel-drag-handle:active { cursor: grabbing; }
.pending-sidebar > header.panel-drag-handle::before {
  content: "⠿";
  color: #b0b6be;
  font-size: 15px;
  line-height: 1;
  cursor: grab;
  flex: 0 0 auto;
}
.pending-sidebar.panel-dragging { opacity: 0.45; }
.pending-sidebar-hide {
  background: none;
  border: none;
  font-size: 16px;
  line-height: 1;
  color: #6b7280;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: var(--r-sm);
}
.pending-sidebar-hide:hover { background: #eef0f3; color: #1f2329; }
/* Per-sidebar hide. When BOTH are hidden, drop the whole column so the
   calendar gets the full width. */
.cal-layout.pending-hidden #pending-sidebar { display: none; }
.cal-layout.parked-hidden #parked-sidebar { display: none; }
.cal-layout.schedule-hidden #schedule-sidebar { display: none; }
.cal-layout.anytime-hidden #anytime-sidebar { display: none; }
.cal-layout.qc-hidden #qc-sidebar { display: none; }
/* BRAND: QC is Signarama-only — force-hide independent of the manual
   show/hide preference above (see renderQcSidebar/updateQcBadge). */
#show-qc-sidebar-btn.brand-hidden { display: none !important; }
.cal-layout.pending-hidden.parked-hidden.schedule-hidden.anytime-hidden.qc-hidden .cal-side-column { display: none; }
.show-qc-sidebar-btn {
  font-size: 13px;
  font-weight: 500;
  padding: 4px 10px;
  border-radius: var(--r-md);
  border: 1px solid #16C7C9;
  background: #e6fbfb;
  color: #0d6e6f;
  cursor: pointer;
  font-family: inherit;
}
.show-qc-sidebar-btn:hover { background: #ccf5f5; }
.show-qc-sidebar-btn #show-qc-sidebar-count {
  display: inline-block;
  background: #16C7C9;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  margin-left: 4px;
}
.show-pending-sidebar-btn {
  font-size: 13px;
  font-weight: 500;
  padding: 4px 10px;
  border-radius: var(--r-md);
  border: 1px solid #f0c869;
  background: #fff8e1;
  color: #8d6708;
  cursor: pointer;
  font-family: inherit;
}
.show-pending-sidebar-btn:hover { background: #ffecb3; }
.show-pending-sidebar-btn #show-pending-sidebar-count {
  display: inline-block;
  background: #f9a825;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  margin-left: 4px;
}
.show-parked-sidebar-btn {
  font-size: 13px;
  font-weight: 500;
  padding: 4px 10px;
  border-radius: var(--r-md);
  border: 1px solid #ef6c00;
  background: #fff3e0;
  color: #8d3b00;
  cursor: pointer;
  font-family: inherit;
}
.show-parked-sidebar-btn:hover { background: #ffe0b2; }
.show-parked-sidebar-btn #show-parked-sidebar-count {
  display: inline-block;
  background: #ef6c00;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  margin-left: 4px;
}
.pending-sidebar-count {
  background: #fff3e0;
  color: #e65100;
  font-size: 11px;
  font-weight: 700;
  padding: 2px 9px;
  border-radius: var(--r-pill);
}
.pending-sidebar-count.zero { background: #eef0f3; color: #6b7280; }
.pending-sidebar-empty {
  padding: 18px 16px;
  color: #6b7280;
  font-size: 13px;
  text-align: center;
}
.pending-sidebar-empty p { margin: 0 0 6px 0; }
.pending-sidebar-list {
  overflow-y: auto;
  padding: 8px;
  flex: 1;
}
.pending-sidebar-card {
  background: #fff8e1;
  border: 1px solid #f0c869;
  border-left: 3px solid #f9a825;
  border-radius: var(--r-md);
  padding: 10px 12px;
  margin-bottom: 8px;
  font-size: 13px;
}
.pending-sidebar-card.from-corebridge {
  background: #e3f2fd;
  border-color: #90caf9;
  border-left-color: #16C7C9;
}
.psc-company {
  font-weight: 600;
  color: #1f2329;
  margin-bottom: 4px;
  line-height: 1.25;
  word-break: break-word;
}
.psc-meta {
  font-size: 11px;
  color: #56606b;
  margin-bottom: 8px;
}
.psc-meta .dot-sep { margin: 0 4px; color: #b0b6bd; }
.psc-source {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  padding: 1px 6px;
  border-radius: var(--r-sm);
  background: #16C7C9;
  color: #fff;
  margin-left: 6px;
}
.psc-actions {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
}
.psc-actions button {
  font-size: 12px;
  padding: 4px 8px;
  border-radius: var(--r-sm);
  border: 1px solid #d0d4da;
  background: #fff;
  cursor: pointer;
  font-family: inherit;
}
.psc-confirm {
  background: #137333 !important;
  color: #fff !important;
  border-color: #137333 !important;
}
.psc-confirm:hover { background: #0e5e29 !important; }
.psc-edit:hover { background: #f0f1f3; }
.psc-to-estimate { color: #1a56c4; border-color: #cddffb !important; }
.psc-to-estimate:hover { background: #eef6fc; }
.psc-discard {
  color: #c5221f;
  margin-left: auto;
}
.psc-discard:hover { background: #fce8e6; }

@media (max-width: 900px) {
  .cal-layout { flex-direction: column; }
  .pending-sidebar {
    width: 100%;
    position: static;
    max-height: 400px;
  }
}

/* ---------- Parked-jobs toolbar button + modal ---------- */
.parked-list-btn {
  font-size: 13px;
  font-weight: 500;
  padding: 4px 10px;
  border-radius: var(--r-md);
  border: 1px solid #ef6c00;
  background: #fff3e0;
  color: #e65100;
  cursor: pointer;
  font-family: inherit;
}
.parked-list-btn:hover { background: #ffe0b2; }
.parked-list-btn #parked-list-count {
  display: inline-block;
  background: #ef6c00;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  margin-left: 4px;
}
.parked-list-count-pill {
  display: inline-block;
  background: #fff3e0;
  color: #e65100;
  font-size: 12px;
  font-weight: 700;
  padding: 2px 9px;
  border-radius: var(--r-pill);
  margin-left: 8px;
  vertical-align: middle;
}
#parked-table .parked-reason { color: #6b7280; font-style: italic; }
#parked-table .parked-row-actions { white-space: nowrap; text-align: right; }
.parked-promote-btn {
  background: #137333; color: #fff; border-color: #137333;
  font-size: 12px; padding: 4px 10px;
}
.parked-promote-btn:hover { background: #0e5e29; border-color: #0e5e29; }

/* ---------- Parked kanban (below the calendar grid) ---------- */
.parked-kanban {
  /* UI-02-C: hero surface chrome to match calendar + dashboard cards. */
  margin-top: 20px;
  padding: 18px 20px;
  background: var(--bg-surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-md);
}
.parked-kanban.hidden { display: none; }
.parked-kanban.collapsed .kanban-columns { display: none; }
.kanban-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}
.kanban-header h3 { margin: 0; font-size: 15px; font-weight: 600; }
.kanban-total {
  display: inline-block;
  background: #fff3e0;
  color: #e65100;
  font-size: 12px;
  font-weight: 700;
  padding: 2px 9px;
  border-radius: var(--r-pill);
  margin-left: 8px;
}
/* CAL-17: switch from a fixed 6-column grid to a horizontal flex row
   so all parked columns stay in ONE row regardless of how many we
   have (7 after CAL-16: Awaiting Payment + 6 workflow stages). Wider
   screens stretch the columns; narrower screens scroll horizontally
   inside the card. */
.kanban-columns {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  gap: 10px;
  overflow-x: auto;
}
.kanban-col {
  flex: 1 1 180px;
  min-width: 180px;
  background: #fafbfc;
  border: 1px solid #eef0f3;
  border-radius: var(--r-md);
  padding: 10px;
  min-height: 120px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.kanban-col h4 {
  margin: 0 0 4px 0;
  font-size: 12px;
  font-weight: 700;
  color: #56606b;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
/* POLISH-02: dollar total now dominant, count quietly parenthetical. The
   owner cares about column $ weight more than count of cards — the
   prior weights had it backwards. See UI-REVIEW.md H7. */
.kanban-col-count {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: #6b7280;
  background: transparent;
  padding: 0 2px;
}
.kanban-col-total {
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--brand-ink);
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}
.kanban-col h4 {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.kanban-col.dragover {
  background: #e3f2fd;
  border-color: #16C7C9;
}
/* Per-column accent (top border) so the columns are visually distinct.
   Awaiting * Payment columns share the red theme — these are AR
   concerns, the eye should land there first. Deposit darkest, Final
   lightest. */
.kanban-col[data-reason="Awaiting Deposit"]         { border-top: 3px solid #b71c1c; }
.kanban-col[data-reason="Awaiting Progress Payment"]{ border-top: 3px solid #d84315; }
.kanban-col[data-reason="Awaiting Final Payment"]   { border-top: 3px solid #ef5350; }
.kanban-col[data-reason="Awaiting Payment"]         { border-top: 3px solid #c62828; } /* legacy */
.kanban-col[data-reason="Design"] { border-top: 3px solid #e65100; }
.kanban-col[data-reason="Proof Out"] { border-top: 3px solid #f9a825; }
.kanban-col[data-reason="In Permit"] { border-top: 3px solid #388e3c; }
.kanban-col[data-reason="Vended"] { border-top: 3px solid #6a1b9a; }
.kanban-col[data-reason="Materials on Order"] { border-top: 3px solid #16C7C9; }
.kanban-col[data-reason="On Hold"] { border-top: 3px solid #00695c; }
.kanban-col[data-reason="Other"] { border-top: 3px solid #6b7280; }
.kanban-card {
  background: #fff;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  padding: 8px 10px;
  font-size: 12px;
  cursor: grab;
  transition: transform 0.06s, box-shadow 0.06s;
}
.kanban-card:hover {
  border-color: #16C7C9;
  box-shadow: 0 2px 6px rgba(0,0,0,0.06);
}
.kanban-card.dragging { opacity: 0.4; cursor: grabbing; }
.kanban-card-company {
  font-weight: 600;
  color: #1f2329;
  margin-bottom: 3px;
  line-height: 1.25;
}
.kanban-card-meta {
  font-size: 11px;
  color: #6b7280;
}
.kanban-empty {
  font-size: 11px;
  color: #b0b6bd;
  text-align: center;
  padding: 8px 0;
  font-style: italic;
}
/* CAL-17: dropped the responsive grid-template-columns overrides —
   the parent .kanban-columns is now flex-based and scrolls horizontally
   on narrow screens, so wrapping to fewer-columns-per-row is no longer
   the desired behavior. Owner wants one row always. */

/* ---------- CAL-02: Full lifecycle Kanban (own tab) ----------
   Reuses .kanban-col / .kanban-card / .kanban-empty / .dragover from
   the parked-kanban widget above. Adds:
     - .kanban-full          horizontal-scrolling 12-column row
     - .kanban-col-parked    amber top accent for parked sub-stages
     - .kanban-col-active    blue top accent for active workflow
     - .kanban-controls      search / filter strip
     - priority + assignee chrome on cards
*/
.kanban-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: #f8f9fa;
  border-bottom: 1px solid #e1e4e8;
  flex-wrap: wrap;
}
/* POLISH-08: search-input chrome shared with #cal-search above. */
.kanban-controls input[type="search"] {
  min-width: 220px;
}
.kanban-controls select {
  padding: 6px 10px;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  font: inherit;
  font-size: 13px;
  background: #fff;
}
.kanban-toggle-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: #56606b;
  cursor: pointer;
}
.kanban-summary {
  margin-left: auto;
  font-size: 12px;
  color: #6b7280;
}
.kanban-full {
  padding: 14px 16px 24px;
}

/* CAL-08: Awaiting Payment banner — prominent strip at the top of
   the Kanban tab. Deep red border + tinted background so the AR
   pile is impossible to miss when the page first loads. Acts as a
   drop target (data-kind + data-target on the wrapper). */
.kanban-banner {
  background: linear-gradient(to bottom, #fff5f5, #fff);
  border: 2px solid #c62828;
  border-radius: var(--r-lg);
  padding: 12px 14px;
  margin-bottom: 18px;
  box-shadow: 0 1px 3px rgba(198, 40, 40, 0.08);
}
.kanban-banner.dragover {
  background: #ffebee;
  border-style: dashed;
}
/* Empty state: smaller, quieter — drop hint only, no urgency. */
.kanban-banner.kanban-banner-empty {
  background: #fafbfc;
  border: 2px dashed #d0d4da;
  box-shadow: none;
}
.kanban-banner.kanban-banner-empty .kanban-banner-header h3 { color: #94a3b8; }
.kanban-banner-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.kanban-banner-header h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 700;
  color: #b71c1c;
  letter-spacing: 0.02em;
}
.kanban-banner-sub {
  font-size: 11px;
  color: #56606b;
  margin-top: 2px;
}
/* CAL-10: per-payment-type breakdown line under the banner header.
   Three small pills showing "Deposit: 3 · $1,200", "Progress: 2 ·
   $4,500", "Final: 5 · $8,200" so the owner can size up the AR
   mix without counting cards. */
.kanban-banner-breakdowns {
  margin-top: 6px;
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.kanban-banner-breakdown {
  font-size: 10px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  border: 1px solid;
}
.kanban-banner-breakdown-critical {
  background: #ffebee;
  color: #b71c1c;
  border-color: #ef9a9a;
}
.kanban-banner-breakdown-warning {
  background: #fff8e1;
  color: #b54708;
  border-color: #fde68a;
}
.kanban-banner-breakdown-normal {
  background: #e3f2fd;
  color: #16C7C9;
  border-color: #bbdefb;
}

/* CAL-12: same payment chip rendered inside the job modal header,
   next to the title. Same tone-class names as the Kanban card chip
   so visual continuity holds (the chip you saw on the card matches
   the chip you see in the modal). Slightly larger here because the
   modal header has more room than a Kanban card. */
.modal-payment-chip {
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: var(--r-md);
  margin-left: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  vertical-align: middle;
  white-space: nowrap;
}
.modal-payment-chip.hidden { display: none; }
.modal-payment-chip-critical {
  background: #b71c1c;
  color: #fff;
}
.modal-payment-chip-warning {
  background: #fde68a;
  color: #92400e;
}
.modal-payment-chip-normal {
  background: #bbdefb;
  color: #0E9799;
}

/* =====================================================================
   CAL-14: job modal redesign — hero header + toolbar + sectioned form.

   The redesign replaces the cramped single-row title+amount+button-grid
   header with three stacked zones:

     1) modal-hero      — company name, meta line, big amount, close (×)
     2) modal-toolbar   — quick-action buttons get their own row
     3) form-section[s] — Customer / Money / Description / Production /
                           Status & Flags / Install / Notes

   We use a higher-specificity selector (`#modal .modal-content >
   header.modal-hero`) to override the generic header rules above. */

#modal .modal-content > header.modal-hero {
  background: #fff;
  border-bottom: 1px solid #eef0f3;
  padding: 22px 32px 18px 32px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
}
@media (max-width: 760px) {
  #modal .modal-content > header.modal-hero { padding: 18px 22px 14px 22px; }
}
.modal-hero-main {
  flex: 1 1 auto;
  min-width: 0;
}
.modal-hero-title-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
#modal .modal-content > header.modal-hero h2 {
  margin: 0;
  font-size: 22px;
  font-weight: 600;
  line-height: 1.25;
  color: #1f2329;
  flex: 0 1 auto;
  word-break: break-word;
}
/* ONE-TRUTH: the short stage track under the job title. Quiet by default —
   it is orientation, not the headline. Only the current step is fully inked;
   done steps are legible but recessive; steps ahead are faint so the eye can
   see at a glance how far along the job is. Wraps and scrolls rather than
   pushing the header wider. */
.stage-track {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 2px;
  margin-top: 7px; font-size: .7rem; line-height: 1;
}
.stage-step { display: inline-flex; align-items: center; gap: 4px; padding: 2px 4px; border-radius: 5px; white-space: nowrap; }
.stage-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .5; flex: none; }
.stage-step.is-todo    { color: var(--text-muted); opacity: .55; }
.stage-step.is-done    { color: var(--text-muted); }
.stage-step.is-done .stage-dot { opacity: 1; background: #16a34a; }
.stage-step.is-current { color: var(--text); font-weight: 650; background: rgba(29,78,216,.09); }
.stage-step.is-current .stage-dot { opacity: 1; background: #1d4ed8; }
.stage-sep { color: var(--text-muted); opacity: .4; }
/* Parked and cancelled sit OFF the track — drawn after it, visually separate,
   because they are not a position along the line. */
.stage-off {
  margin-left: 6px; padding: 2px 7px; border-radius: 999px;
  font-size: .67rem; font-weight: 650; white-space: nowrap;
}
.stage-off.is-parked    { background: #fef6e4; color: #6b4e12; border: 1px solid #f0d08a; }
.stage-off.is-cancelled { background: #f1f5f9; color: #64748b; border: 1px solid #cbd5e1; text-decoration: line-through; }
.modal-hero-meta {
  font-size: 13px;
  color: #56606b;
  margin-top: 6px;
  line-height: 1.45;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.modal-hero-meta:empty { display: none; }
.modal-hero-meta-sep {
  color: #b8bec8;
  font-weight: 600;
}
/* ONE-TRUTH: a job waiting on QC shows current → requested in ONE pill, rather
   than the header claiming one status while the pipeline column shows another.
   The arrow and the QC tag are quieter than the two labels — the states are the
   information, the punctuation is not. */
.modal-hero-status-pill.is-qc-transition { display: inline-flex; align-items: center; gap: 5px; }
.hero-status-arrow { opacity: .55; font-weight: 600; }
.hero-status-qc {
  margin-left: 2px; padding: 1px 5px; border-radius: 999px;
  background: rgba(15, 23, 42, .16); font-size: .64rem; font-weight: 700;
  letter-spacing: .04em;
}
.modal-hero-status-pill {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: var(--r-sm);
  background: #f0f1f3;
  color: #56606b;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.modal-hero-status-pill.status-pending { background: #f4e3b8; color: #6d4c12; }
.modal-hero-status-pill.status-in_production { background: #c5e1ff; color: #0E9799; }
.modal-hero-status-pill.status-ready_for_install { background: #d4f1d0; color: #1b5e20; }
.modal-hero-status-pill.status-ready_for_pickup { background: #d4f1d0; color: #1b5e20; }
.modal-hero-status-pill.status-completed { background: #d8d8d8; color: #424242; }
.modal-hero-status-pill.status-cancelled { background: #ffcdd2; color: #b71c1c; }
.modal-hero-status-pill.status-parked { background: #ffe0b2; color: #5d4037; }
.modal-hero-side {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  flex-shrink: 0;
}
.modal-hero-amount {
  font-size: 22px;
  font-weight: 700;
  color: #1f2329;
  font-variant-numeric: tabular-nums;
  line-height: 1.3;
  white-space: nowrap;
}
.modal-hero-amount:empty { display: none; }
/* Reset the modal-payment-chip margin when it lives in the hero
   title row — the old layout had it sit next to a small h2 with a
   12px gutter; the new hero uses gap on the title row instead. */
.modal-hero-title-row .modal-payment-chip { margin-left: 0; }
/* Close button styling inside the hero — keep the existing
   #modal-close behavior, but make sure it sits flush with the
   amount in the side column. */
#modal .modal-content > header.modal-hero #modal-close {
  background: transparent;
  border: none;
  font-size: 28px;
  line-height: 1;
  padding: 0 4px;
  cursor: pointer;
  color: #56606b;
  align-self: flex-start;
}
#modal .modal-content > header.modal-hero #modal-close:hover { color: #1f2329; }

/* Toolbar row — quick-action buttons get a calm gray strip so they
   don't compete with the title or the form. Edit button right-aligned. */
.modal-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 10px 32px;
  background: #f8f9fa;
  border-bottom: 1px solid #eef0f3;
}
.modal-toolbar.hidden { display: none; }
.modal-toolbar-spacer { flex: 1 1 auto; }
@media (max-width: 760px) {
  .modal-toolbar { padding: 10px 22px; }
}

/* Form sections — replace the old single 40px/56px form padding with
   per-section padding. Each section has a small uppercase header and
   a soft divider underneath. */
/* POLISH-09 (M9): symmetric vertical padding so sections breathe
   evenly above and below their divider. Was 18px/6px (top-heavy). */
#job-form .form-section {
  padding: 22px 32px 22px 32px;
  border-bottom: 1px solid #eef0f3;
}
#job-form .form-section:last-of-type { border-bottom: none; }
#job-form .form-section-header {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #6b7280;
  margin-bottom: 14px;
}
#job-form .form-section .grid { gap: 16px 22px; }
@media (max-width: 760px) {
  #job-form .form-section { padding: 16px 22px 4px 22px; }
}
/* Label-less wrapper used in the Notes section where we don't want
   "Notes" repeated above the textarea (the section header already
   says it). Hides only the label text but keeps the input layout. */
.no-label-text { font-size: 0; }
.no-label-text > input,
.no-label-text > textarea,
.no-label-text > select { font-size: 14px; }

/* CAL-10: per-card chip distinguishing Deposit / Progress / Final
   on banner cards. Sits inline with the company name. */
.kanban-card-paychip {
  display: inline-block;
  font-size: 9px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: var(--r-sm);
  margin-right: 6px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  vertical-align: middle;
}
.kanban-card-paychip-critical {
  background: #b71c1c;
  color: #fff;
}
.kanban-card-paychip-warning {
  background: #fde68a;
  color: #92400e;
}
.kanban-card-paychip-normal {
  background: #bbdefb;
  color: #0E9799;
}
.kanban-banner-cards {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  align-items: stretch;
  padding-bottom: 4px;
}
.kanban-banner-cards .kanban-card {
  flex: 0 0 220px;
  min-width: 220px;
}
.kanban-banner-cards .kanban-empty {
  flex: 1;
  padding: 14px;
  text-align: center;
}

/* CAL-04: each kanban section is its own labeled row of columns.
   Two of them are stacked vertically — On-Calendar on top
   (active workflow), Off-Calendar below (parked queue). */
.kanban-section {
  margin-bottom: 18px;
}
.kanban-section:last-child { margin-bottom: 0; }
.kanban-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
  padding: 0 2px;
}
.kanban-section-header h3 {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  color: #56606b;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.kanban-section-count {
  font-size: 11px;
  font-weight: 600;
  color: #6b7280;
  padding: 2px 9px;
  border-radius: var(--r-pill);
  background: #f1f3f5;
}
/* Active band = branded/energetic (teal). Parked band = the quiet holding
   queue, so a calm graphite header reads more sophisticated than the old loud
   orange. Count pills tint to match — fixes the leftover blue pill (#e3f2fd)
   that lingered under the teal header after the blue→teal sweep. */
.kanban-section-active .kanban-section-header h3 { color: #0E9799; }
.kanban-section-active .kanban-section-count { background: #E6F7F7; color: #0E9799; }
.kanban-section-parked .kanban-section-header h3 { color: #64748B; }
.kanban-section-parked .kanban-section-count { background: #EEF1F5; color: #64748B; }
/* CAL-19: section dollar total — bold, tabular-numbered, sits to the
   right of the count pill so the section header reads "On Calendar
   active workflow · 47 jobs · $312,450". */
.kanban-section-total {
  font-size: 14px;
  font-weight: 700;
  color: #1f2329;
  margin-left: 8px;
  font-variant-numeric: tabular-nums;
}
/* CHAT/PIPE: the pipeline wraps into as many rows as needed (≈2 for the
   Fully Promoted board's stages) so EVERY stage stays visible, instead of a
   single row that scrolls sideways and hides the trailing stages. auto-fill
   packs as many ≥200px columns per row as fit and wraps the rest, left-aligned
   and evenly sized — and collapses to fewer-per-row on narrow screens. */
.kanban-row {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 10px;
  align-items: start;
}
.kanban-row .kanban-col {
  min-width: 0;
  max-height: calc(50vh - 100px);
  overflow-y: auto;
}
/* Parked sub-stages are a holding queue, not a progression — so they get
   muted, desaturated tones that harmonize with the brand instead of the old
   saturated rainbow (bright orange / vivid purple / primary green). Each keeps
   its original hue family so learned columns stay recognizable, just calmer.
   Awaiting Payment uses Signal Coral — the brand's alert color — so the AR
   concern is where the eye lands first. */
.kanban-full .kanban-col-parked[data-target="Awaiting Payment"]   { border-top: 3px solid #FF6B4A; }
.kanban-full .kanban-col-parked[data-target="Design"]             { border-top: 3px solid #8778D0; }
.kanban-full .kanban-col-parked[data-target="Proof Out"]          { border-top: 3px solid #D6973A; }
.kanban-full .kanban-col-parked[data-target="In Permit"]          { border-top: 3px solid #5E86B8; }
.kanban-full .kanban-col-parked[data-target="Vended"]             { border-top: 3px solid #7D8AA3; }
.kanban-full .kanban-col-parked[data-target="Materials on Order"] { border-top: 3px solid #16C7C9; }
.kanban-full .kanban-col-parked[data-target="On Hold"]            { border-top: 3px solid #9AA5B1; }
/* Active stages: one cohesive slate→teal→green "progress ramp" anchored on
   the Alignment Teal brand color. Reads left-to-right as "more done" without
   the muddy triple-cyan of before — each step is a distinct, evenly-spaced
   stop in a single cool family. */
.kanban-full .kanban-col-active[data-target="pending"]           { border-top: 3px solid #94a3b8; }
.kanban-full .kanban-col-active[data-target="in_production"]     { border-top: 3px solid #16C7C9; }
.kanban-full .kanban-col-active[data-target="ready_for_pickup"]  { border-top: 3px solid #0D9488; }
.kanban-full .kanban-col-active[data-target="ready_for_install"] { border-top: 3px solid #1FA06B; }
.kanban-full .kanban-col-active[data-target="delivered"]         { border-top: 3px solid #16A34A; }
.kanban-full .kanban-col-active[data-target="completed"]         { border-top: 3px solid #15803D; }
/* Whisper-subtle band tints — enough to separate active from parked without
   the loud cream/gray split that used to chop the board in half. */
.kanban-full .kanban-col-parked { background: #fbfaf8; }
.kanban-full .kanban-col-active { background: #fafbfc; }
/* Priority card + ★ badge */
.kanban-card.priority {
  border-color: #f9a825;
  background: linear-gradient(to right, #fff8e1 0%, #ffffff 8%);
}
.kanban-card-priority {
  color: #f9a825;
  font-size: 12px;
  margin-right: 4px;
  font-weight: 900;
}
/* CAL-03: same yellow "pending" chip the calendar uses on
   pending-review jobs (those synced from Corebridge but not yet
   approved by the owner). Pending-review cards also get a dashed
   left border so they're scannable in a busy column. */
.kanban-card.pending-review {
  border-left: 3px dashed #f9a825;
}
.kanban-card-pending {
  display: inline-block;
  font-size: 10px;
  background: #fff3e0;
  color: #e65100;
  padding: 1px 6px;
  border-radius: var(--r-sm);
  margin-left: 6px;
  font-weight: 600;
  vertical-align: middle;
}
.kanban-card-assignee {
  font-size: 10px;
  color: var(--text-muted);
  margin-top: 4px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
/* PIPE-AGE: time-in-current-stage badge. Neutral by default; ramps to amber
   then red as a card goes stale so backed-up jobs are obvious at a glance. */
.kanban-card-age {
  display: inline-block;
  margin-top: 5px;
  font-size: 10px;
  font-weight: 600;
  color: #64748b;
  background: #f1f5f9;
  border-radius: 4px;
  padding: 1px 6px;
}
.kanban-card-age.stale-1 { color: #92700e; background: #fef3c7; }
.kanban-card-age.stale-2 { color: #9a3412; background: #ffedd5; }
.kanban-card-age.stale-3 { color: #fff; background: #dc2626; }
/* CB-03: suggestion badge + popover. The 💡 icon sits inline with
   the card title; clicking it opens a popover with the apply/dismiss
   buttons. The has-suggestion card class adds a subtle blue tint to
   the entire card so it's easy to scan a column for "what needs
   attention". */
.kanban-card.has-suggestion {
  border-left: 3px solid #16C7C9;
  background: linear-gradient(to right, #e3f2fd 0%, #ffffff 8%);
}
.kanban-card-suggestion {
  display: inline-block;
  font-size: 12px;
  margin-left: 6px;
  padding: 1px 5px;
  border-radius: var(--r-lg);
  background: #e3f2fd;
  color: #16C7C9;
  cursor: pointer;
  font-weight: 600;
  vertical-align: middle;
  user-select: none;
}
.kanban-card-suggestion:hover { background: #bbdefb; }

.suggestion-popover {
  background: #fff;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  box-shadow: 0 8px 24px rgba(0,0,0,0.12);
  padding: 0;
  min-width: 280px;
  max-width: 360px;
  font-size: 13px;
}
.suggestion-row {
  padding: 12px 14px;
  border-bottom: 1px solid #eef0f3;
}
.suggestion-row:last-child { border-bottom: none; }
.suggestion-reason {
  font-size: 11px;
  color: #56606b;
  margin-bottom: 6px;
}
.suggestion-change {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
  font-weight: 600;
}
.suggestion-current {
  color: #6b7280;
  text-decoration: line-through;
  text-decoration-color: rgba(107, 114, 128, 0.4);
}
.suggestion-arrow { color: #94a3b8; }
.suggestion-suggested { color: #16C7C9; }
.suggestion-actions {
  display: flex;
  gap: 6px;
}
.suggestion-actions button {
  flex: 1;
  padding: 5px 10px;
  font-size: 12px;
  border-radius: var(--r-md);
  border: 1px solid #d0d4da;
  background: #fff;
  cursor: pointer;
  font-family: inherit;
}
.suggestion-actions button.primary {
  background: #16C7C9;
  color: #fff;
  border-color: #16C7C9;
}
.suggestion-actions button:hover { filter: brightness(1.05); }

/* CB-03: cancelled column gets a muted gray accent. Same hidden-
   by-default behaviour as Completed (controlled by the "Show
   Completed column" toggle). A lighter, faded gray than Pending's
   slate so the two neutral columns read distinctly — cancelled as
   "retired/archived", pending as "not started". */
.kanban-full .kanban-col-active[data-target="cancelled"]         { border-top: 3px solid #C2C8D0; }

/* CAL-09: quick-note button + popover for Awaiting Payment cards.
   The button sits at the top-right of the card and only appears on
   awaiting-payment cards. The latest note preview shows at the
   bottom of the card so the owner can scan "what did I do last
   time" without expanding anything. */
.kanban-card.awaiting-payment {
  position: relative;
}
.kanban-card-note-btn,
.kanban-card-mark-waiting-btn {
  position: absolute;
  top: 6px;
  right: 8px;
  font-size: 10px;
  font-weight: 600;
  background: #fff;
  color: #c62828;
  border: 1px solid #c62828;
  border-radius: var(--r-lg);
  padding: 1px 8px;
  cursor: pointer;
  font-family: inherit;
  z-index: 1;
  line-height: 1.4;
}
.kanban-card-note-btn:hover,
.kanban-card-mark-waiting-btn:hover {
  background: #c62828;
  color: #fff;
}
/* CAL-11: subtle styling difference — mark-as-waiting button is
   dashed-border (less commit, more "tag this") vs the solid-border
   note button (a "do this routine thing" action). */
.kanban-card-mark-waiting-btn {
  border-style: dashed;
}
/* Cards aren't relative-positioned by default — the AP-card class
   adds it for the +Note button. Add it for any card with the
   mark-waiting button too. */
.kanban-card:has(.kanban-card-mark-waiting-btn) {
  position: relative;
}

/* MOBILE: "⇄ Move" replaces drag-and-drop on touch — hidden on desktop
   where dragging already works. Sits in normal flow (not absolutely
   positioned) so it doesn't need the position:relative dance above. */
.kanban-card-move-btn { display: none; }
@media (max-width: 768px) {
  .kanban-card-move-btn {
    display: block;
    width: 100%;
    margin-top: 6px;
    padding: 6px 0;
    font-size: 11px;
    font-weight: 600;
    color: #16C7C9;
    background: #f0f6ff;
    border: 1px solid #cfe0fb;
    border-radius: var(--r-md);
    cursor: pointer;
    font-family: inherit;
  }
}
.move-popover-title {
  padding: 12px 14px 8px;
  font-size: 12px;
  font-weight: 600;
  color: #56606b;
}
.move-popover-list {
  display: flex;
  flex-direction: column;
  max-height: 50vh;
  overflow-y: auto;
}
.move-popover-option {
  padding: 10px 14px;
  text-align: left;
  font-size: 13px;
  border: none;
  border-top: 1px solid #eef0f3;
  background: #fff;
  cursor: pointer;
  font-family: inherit;
}
.move-popover-option:hover { background: #f0f6ff; }
.move-popover-cancel {
  width: 100%;
  padding: 10px 14px;
  text-align: center;
  font-size: 13px;
  font-weight: 600;
  color: #56606b;
  border: none;
  border-top: 1px solid #eef0f3;
  background: #fafbfc;
  border-radius: 0 0 var(--r-md) var(--r-md);
  cursor: pointer;
  font-family: inherit;
}
/* On phones a small anchored popover risks going off-screen (up to a
   dozen destinations) — pin it as a bottom sheet instead, matching the
   .topbar-actions .dropdown-menu mobile fix elsewhere in this file. */
@media (max-width: 768px) {
  .move-popover {
    position: fixed !important;
    left: 10px !important;
    right: 10px;
    top: auto !important;
    bottom: 10px;
    width: auto;
    max-width: none;
  }
}

/* Picker popover for "Mark as waiting on" → Deposit / Progress / Final. */
.mark-waiting-popover {
  min-width: 280px;
  max-width: 320px;
}
.mark-waiting-body {
  padding: 12px 14px;
}
.mark-waiting-title {
  font-size: 11px;
  font-weight: 600;
  color: #56606b;
  margin-bottom: 8px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.mark-waiting-options {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.mark-waiting-opt {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 8px 12px;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  background: #fff;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  transition: transform 0.04s, box-shadow 0.04s;
}
.mark-waiting-opt:hover {
  box-shadow: 0 2px 6px rgba(0,0,0,0.06);
  transform: translateY(-1px);
}
.mark-waiting-opt-label {
  font-size: 13px;
  font-weight: 600;
}
.mark-waiting-opt-hint {
  font-size: 10px;
  color: #94a3b8;
  margin-top: 2px;
}
/* Color tone per option matches the BANNER_CHIP_META tones —
   Deposit critical red, Progress amber, Final blue — so the
   picker is consistent with the chip the card will get afterward. */
.mark-waiting-deposit  { border-left: 4px solid #b71c1c; }
.mark-waiting-deposit .mark-waiting-opt-label  { color: #b71c1c; }
.mark-waiting-progress { border-left: 4px solid #d84315; }
.mark-waiting-progress .mark-waiting-opt-label { color: #d84315; }
.mark-waiting-final    { border-left: 4px solid #16C7C9; }
.mark-waiting-final .mark-waiting-opt-label    { color: #16C7C9; }
.kanban-card-latest-note {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px dashed #e1e4e8;
  font-size: 10px;
  color: #6b7280;
  font-style: italic;
  line-height: 1.4;
  /* Truncate to one line with ellipsis if too long. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Note popover reuses the suggestion-popover base styling but adds
   note-specific bits. */
.note-popover {
  min-width: 320px;
  max-width: 420px;
}
.note-popover-body {
  padding: 12px 14px;
}
.note-popover-title {
  font-size: 13px;
  font-weight: 600;
  color: #1f2329;
  margin-bottom: 10px;
}
.note-popover-history-label {
  font-size: 10px;
  font-weight: 700;
  color: #94a3b8;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 4px;
}
.note-popover-history {
  background: #f8f9fa;
  border-radius: var(--r-sm);
  padding: 6px 8px;
  margin-bottom: 10px;
  max-height: 100px;
  overflow-y: auto;
}
.note-popover-history-line {
  font-size: 11px;
  color: #56606b;
  line-height: 1.5;
  white-space: pre-wrap;
}
.note-popover-input {
  width: 100%;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  padding: 6px 8px;
  font-family: inherit;
  font-size: 13px;
  resize: vertical;
  min-height: 50px;
  box-sizing: border-box;
}
.note-popover-input:focus {
  outline: none;
  border-color: #16C7C9;
}
.note-popover-hint {
  font-size: 10px;
  color: #94a3b8;
  margin: 4px 0 10px;
}

/* CAL-05: truncation note shown at the bottom of the Completed
   column when the cap has hidden older completed jobs. Quiet,
   italic, not pretending to be a card. */
.kanban-col-footer {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed #e1e4e8;
  font-size: 10px;
  color: #94a3b8;
  font-style: italic;
  text-align: center;
}

/* ---------- Duplicates scanner ---------- */
#duplicates-modal .modal-content { width: min(960px, 94vw); max-height: 90vh; }
.duplicates-summary {
  padding: 12px 14px;
  background: #f8f9fa;
  border: 1px solid #e1e4e8;
  border-radius: var(--r-md);
  margin-bottom: 14px;
  font-size: 14px;
}
.duplicates-list { display: flex; flex-direction: column; gap: 14px; }
.dup-group {
  border: 1px solid #e1e4e8;
  border-radius: var(--r-md);
  background: #fff;
  overflow: hidden;
}
.dup-group.tier-cb_id { border-left: 4px solid #d93025; }
.dup-group.tier-invoice { border-left: 4px solid #f9a825; }
.dup-group.tier-soft,
.dup-group.tier-soft_due,
.dup-group.tier-soft_amount,
.dup-group.tier-soft_delivery { border-left: 4px solid #16C7C9; }
.dup-group.merged { opacity: 0.5; }
.dup-group-header {
  padding: 10px 14px;
  background: #fafbfc;
  border-bottom: 1px solid #eef0f3;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  font-size: 13px;
}
.dup-tier-badge {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: var(--r-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-right: 6px;
}
.dup-tier-badge.tier-cb_id { background: #fce8e6; color: #c5221f; }
.dup-tier-badge.tier-invoice { background: #fff3e0; color: #e65100; }
.dup-tier-badge.tier-soft,
.dup-tier-badge.tier-soft_due,
.dup-tier-badge.tier-soft_amount,
.dup-tier-badge.tier-soft_delivery { background: #e8f0fe; color: #16C7C9; }
.dup-group-body { padding: 0; }
.dup-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.dup-table th, .dup-table td {
  padding: 8px 10px;
  border-bottom: 1px solid #f0f1f3;
  text-align: left;
  vertical-align: top;
}
.dup-table th { font-size: 11px; font-weight: 700; color: #6b7280; text-transform: uppercase; background: #fafbfc; }
.dup-table tr.is-primary { background: #e8f5e9; }
.dup-table tr.is-primary td:first-child::before {
  content: '★ ';
  color: #2e7d32;
}
.dup-row-radio { cursor: pointer; }
.dup-actions { padding: 10px 14px; display: flex; gap: 8px; justify-content: flex-end; background: #fafbfc; border-top: 1px solid #eef0f3; }

/* ---------- Corebridge hub modal ---------- */
#corebridge-hub-modal .modal-content { width: min(640px, 92vw); }
/* Body inset now comes from the base .modal-body rule. */
/* PHASE 3: Corebridge connection panel at the top of the hub. */
.cb-conn-status { font-weight: 600; font-size: 14px; margin-bottom: 12px; display: flex; align-items: center; gap: 8px; }
.cb-conn-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.cb-conn-dot.ok { background: #2e7d32; }
.cb-conn-dot.off { background: #c5221f; }
.cb-conn-label { display: block; font-size: 12px; font-weight: 600; color: #56606b; margin-bottom: 10px; }
.cb-conn-label input {
  display: block; width: 100%; margin-top: 5px; padding: 9px 11px;
  border: 1px solid #d0d4da; border-radius: 8px; font-size: 14px; font-family: inherit;
}
.cb-conn-label input:focus { outline: none; border-color: var(--action-blue); box-shadow: 0 0 0 2px rgba(22,199,201,0.15); }
.cb-conn-actions { display: flex; gap: 8px; align-items: center; margin-top: 4px; }
.cb-conn-actions button { padding: 8px 14px; border-radius: 8px; border: 1px solid #d0d4da; background: #fff; font: inherit; font-size: 13px; cursor: pointer; }
.cb-conn-actions button.primary { background: var(--action-blue, #16C7C9); color: #fff; border-color: transparent; font-weight: 600; }
.cb-conn-actions button:disabled { opacity: .6; cursor: default; }
.cb-conn-msg { margin-top: 10px; font-size: 13px; min-height: 18px; }
.cb-conn-msg.ok { color: #137333; }
.cb-conn-msg.error { color: #c5221f; }
.cb-conn-rule { margin: 18px 0; border: none; border-top: 1px solid #e1e4e8; }
.cb-hub-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.cb-hub-action {
  text-align: left;
  background: #fff;
  border: 1px solid #d0d4da;
  border-left: 3px solid #16C7C9;
  border-radius: var(--r-md);
  padding: 14px 16px;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.1s, border-color 0.1s;
}
.cb-hub-action:hover {
  background: #f0f6ff;
  border-color: #16C7C9;
}
.cb-hub-action.cb-hub-warn {
  border-left-color: #f9a825;
}
.cb-hub-action.cb-hub-warn:hover {
  background: #fff8e1;
  border-color: #f9a825;
}
.cb-hub-action.cb-hub-danger {
  border-left-color: #d93025;
}
.cb-hub-action.cb-hub-danger:hover {
  background: #fdf3f2;
  border-color: #d93025;
}
.cb-hub-title {
  font-weight: 600;
  font-size: 14px;
  margin-bottom: 4px;
  color: #1f2329;
}
.cb-hub-desc {
  font-size: 12px;
  color: #6b7280;
  line-height: 1.35;
}
@media (max-width: 600px) {
  .cb-hub-grid { grid-template-columns: 1fr; }
}

/* ---------- Users & logins / Audit log ---------- */
.header-user {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: 10px;
  padding-left: 12px;
  border-left: 1px solid #e1e4e8;
}
.header-user #logout-btn {
  font-size: 12px;
  padding: 6px 12px;
}
.current-user {
  font-size: 12px;
  font-weight: 600;
  color: #4b5563;
  background: #f3f4f6;
  border: 1px solid #e5e7eb;
  border-radius: var(--r-pill);
  padding: 4px 10px;
  max-width: 180px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.current-user.role-admin { background: #fff3e0; color: #e65100; border-color: #ffcc80; }
/* Manage menu is admin-only — hidden in markup by default and revealed
   in JS via loadCurrentUser() once the user is known to be admin. */
.admin-only.hidden { display: none; }
@media (max-width: 768px) {
  .header-user {
    margin-left: 4px;
    padding-left: 6px;
  }
  .current-user { max-width: 100px; }
}
.modal-wide { width: min(900px, 92vw); }
.settings-account-section h3 { margin: 0 0 10px 0; font-size: 14px; }
.settings-account-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.settings-account-actions button {
  padding: 7px 14px;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  background: #fff;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-body);
  cursor: pointer;
}
.settings-account-actions button:hover { background: #f9fafb; }
.users-add {
  background: #f9fafb;
  border: 1px solid #e5e7eb;
  border-radius: var(--r-md);
  padding: 14px 16px;
  margin-bottom: 18px;
}
.users-add h3 { margin: 0 0 10px 0; font-size: 14px; }
.users-add-row {
  display: grid;
  grid-template-columns: 1.4fr 1.6fr 1.2fr 100px 80px;
  gap: 8px;
  align-items: center;
}
.users-add-row input, .users-add-row select {
  width: 100%;
  padding: 7px 10px;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  font-size: 14px;
  font-family: inherit;
}
.users-add-hint { margin-top: 8px; font-size: 12px; color: #6b7280; }
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.data-table th, .data-table td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid #eef0f3;
  vertical-align: middle;
}
.data-table th {
  font-size: 11px;
  font-weight: 700;
  color: #6b7280;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  background: #f9fafb;
}
.data-table tr.disabled td { opacity: 0.5; }
.role-pill {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: #e8f0fe;
  color: #16C7C9;
}
.role-pill.admin { background: #fff3e0; color: #e65100; }
.audit-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.audit-action {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  padding: 1px 7px;
  border-radius: var(--r-sm);
}
.audit-action-create { background: #e6f4ea; color: #137333; }
.audit-action-update { background: #e8f0fe; color: #16C7C9; }
.audit-action-delete { background: #fce8e6; color: #c5221f; }
.audit-action-login  { background: #f3e8fd; color: #6b21a8; }
.audit-action-system { background: #fff3e0; color: #e65100; }
@media (max-width: 768px) {
  .users-add-row { grid-template-columns: 1fr; }
}

/* WIP reconcile modal — long Corebridge company names get clipped so
   the table stays inside the modal instead of forcing a sideways scroll. */
#wipr-results .preview-table td:nth-child(2) {
  max-width: 340px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ============================================================
   NOTIF-07: bell button + notification panel. */
.notif-btn {
  position: relative;
  background: transparent;
  border: 1px solid #d8e0ea;
  border-radius: var(--r-md);
  padding: 6px 10px;
  font-size: 16px;
  cursor: pointer;
  line-height: 1;
}
.notif-btn:hover { background: #f5f7fa; }
.notif-badge {
  position: absolute;
  top: -6px;
  right: -6px;
  background: var(--brand-red);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  min-width: 18px;
  text-align: center;
  border: 2px solid #fff;
}
.notif-badge.hidden { display: none; }
.notif-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  width: 380px;
  max-width: calc(100vw - 20px); /* never hang off a narrow window */
  max-height: 480px;
  background: #fff;
  border: 1px solid #e1e4e8;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  z-index: 100;
}
.notif-panel.hidden { display: none; }
/* Phones: the fix for the panel opening off-screen lives in the mobile
   media block with the other topbar dropdowns — see the
   `.topbar-actions .dropdown-menu` position:fixed rule, which covers the
   bell panel, Manage and + New Job menus in one place. */
.notif-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid #eef0f3;
}
.notif-panel-title {
  font-size: var(--fs-md);
  font-weight: 700;
  color: var(--brand-ink);
}
.notif-mark-all {
  background: transparent;
  border: none;
  color: var(--action-blue);
  font-size: var(--fs-xs);
  font-weight: 600;
  cursor: pointer;
  padding: 4px 6px;
}
.notif-mark-all:hover { text-decoration: underline; }
.notif-list {
  overflow-y: auto;
  max-height: 420px;
}
.notif-empty {
  padding: 24px 16px;
  text-align: center;
  color: var(--cell-empty);
  font-size: var(--fs-sm);
  font-style: italic;
}
.notif-item {
  padding: 12px 16px;
  border-bottom: 1px solid #f0f1f3;
  cursor: pointer;
  transition: background 0.1s;
  position: relative;
}
.notif-item:hover { background: #fafbfc; }
.notif-item.unread {
  background: #f0f6ff;
  border-left: 3px solid var(--action-blue);
  padding-left: 13px;
}
.notif-item.unread:hover { background: #e6efff; }
.notif-item-title {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--brand-ink);
  line-height: 1.3;
}
.notif-item-body {
  font-size: var(--fs-xs);
  color: #6b7280;
  margin-top: 4px;
  line-height: 1.4;
}
.notif-item-time {
  font-size: 10px;
  color: #94a3b8;
  margin-top: 4px;
}

/* ---------- CHAT-02: team-chat button, panel, messages ---------- */
.chat-btn { position: relative; cursor: pointer; line-height: 1; }
.chat-badge {
  position: absolute;
  top: -6px;
  right: -6px;
  background: var(--brand-red);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  min-width: 18px;
  text-align: center;
  border: 2px solid #fff;
}
.chat-badge.hidden { display: none; }
.chat-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  width: 380px;
  max-width: calc(100vw - 20px);
  max-height: 480px;
  background: #fff;
  border: 1px solid #e1e4e8;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  z-index: 100;
}
.chat-panel.hidden { display: none; }
.chat-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid #eef0f3;
  flex-shrink: 0;
}
.chat-panel-title {
  font-size: var(--fs-md);
  font-weight: 700;
  color: var(--brand-ink);
}
.chat-list {
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 120px;
  max-height: 360px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 0;
}
.chat-empty {
  padding: 24px 16px;
  text-align: center;
  color: var(--cell-empty);
  font-size: var(--fs-sm);
  font-style: italic;
}
.chat-msg {
  padding: 6px 16px;
  line-height: 1.4;
}
.chat-msg-meta {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 2px;
}
.chat-msg-sender {
  font-size: var(--fs-sm);
  font-weight: 700;
}
.chat-msg-time {
  font-size: 10px;
  color: #94a3b8;
}
.chat-msg-body {
  font-size: var(--fs-sm);
  color: var(--brand-ink);
  white-space: pre-wrap;
  word-break: break-word;
}
.chat-compose {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  padding: 10px 12px;
  border-top: 1px solid #eef0f3;
  flex-shrink: 0;
}
.chat-input {
  flex: 1 1 auto;
  resize: none;
  max-height: 96px;
  border: 1px solid #d8e0ea;
  border-radius: var(--r-md);
  padding: 8px 10px;
  font-family: inherit;
  font-size: var(--fs-sm);
  line-height: 1.4;
  color: var(--brand-ink);
}
.chat-input:focus {
  outline: none;
  border-color: var(--action-blue);
  box-shadow: 0 0 0 3px var(--focus-ring);
}
.chat-send {
  flex-shrink: 0;
  border: none;
  border-radius: var(--r-md);
  background: var(--action-blue);
  color: #fff;
  font-weight: 650;
  font-size: var(--fs-sm);
  padding: 8px 14px;
  cursor: pointer;
}
.chat-send:hover { filter: brightness(0.95); }
/* The chat panel reuses the .dropdown-menu class, whose menu-item rule
   `.dropdown-menu button { display:block; width:100% }` (specificity 0,1,1) was
   overriding .chat-send (0,1,0) — stretching Send full-width and crushing the
   input to a sliver. Re-scope it back (0,2,0 wins). */
.chat-compose .chat-send {
  display: inline-flex;
  align-items: center;
  width: auto;
  flex: 0 0 auto;
}

/* CHAT-04: in-modal job discussion thread. Reuse the .chat-* look but frame the
   list as a bordered box inside the job form and constrain its scroll height. */
.job-thread-list {
  max-height: 260px;
  border: 1px solid #eef0f3;
  border-radius: var(--r-md);
  background: #fff;
}
.job-thread-list.hidden,
.job-thread-compose.hidden { display: none; }
.job-thread-compose {
  padding: 10px 0 0;
  border-top: none;
}
/* CHAT-05: per-job unread discussion dot on pipeline cards. */
.job-chat-dot {
  margin-left: 6px;
  font-size: 11px;
  line-height: 1;
  vertical-align: middle;
}

/* CHAT-06: own-message edit/delete affordances + soft-delete tombstone. */
.chat-msg-actions {
  display: inline-flex;
  gap: 8px;
  margin-left: auto;
}
.chat-msg-actions button {
  border: none;
  background: none;
  color: #94a3b8;
  font-size: 10px;
  cursor: pointer;
  padding: 0;
}
.chat-msg-actions button:hover {
  color: var(--action-blue);
  text-decoration: underline;
}
.chat-msg-edited {
  font-size: 10px;
  color: #94a3b8;
  font-style: italic;
}
.chat-msg-tombstone {
  color: #94a3b8;
  font-style: italic;
}
.notif-item-kind {
  display: inline-block;
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 1px 6px;
  border-radius: var(--r-sm);
  margin-bottom: 4px;
}
.notif-item-kind.kind-job_assigned       { background: #e3f2fd; color: #16C7C9; }
.notif-item-kind.kind-install_tomorrow   { background: #fff3e0; color: #ef6c00; }
.notif-item-kind.kind-sync_failed        { background: #ffebee; color: #c62828; }
.notif-item-kind.kind-overdue_payment    { background: #fce4ec; color: #c2185b; }
.notif-item-kind.kind-corebridge_completed { background: #e8f5e9; color: #2e7d32; }
.notif-item-kind.kind-manual             { background: #ede7f6; color: #4527a0; }
.notif-item-kind.kind-broadcast          { background: #fff8e1; color: #6d4c00; }
.notif-item-kind.kind-production_complete { background: #e0f2f1; color: #00695c; }
.notif-item-kind.kind-survey_scheduled   { background: #f3e5f5; color: #6a1b9a; } /* purple — matches calendar survey chips */
.notif-item-kind.kind-survey_today       { background: #f3e5f5; color: #6a1b9a; }

/* NOTIF-09: composer modal — recipient picker, title, body. Compact and
   shares modal-v2 chrome with the rest of the app. */
.notif-compose-row { margin-bottom: 12px; }
.notif-compose-row label {
  display: block;
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted, #666);
  margin-bottom: 4px;
}
.notif-compose-row input[type="text"],
.notif-compose-row select,
.notif-compose-row textarea {
  width: 100%;
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border, #d0d7de);
  border-radius: var(--r-md);
  background: var(--surface, #fff);
  box-sizing: border-box;
}
.notif-compose-row textarea {
  resize: vertical;
  min-height: 80px;
  font-family: inherit;
}
.notif-compose-mode {
  display: flex;
  gap: 6px;
  margin-bottom: 12px;
  border: 1px solid var(--border, #d0d7de);
  border-radius: var(--r-md);
  padding: 2px;
  background: var(--cell-empty, #fafbfc);
}
.notif-compose-mode button {
  flex: 1;
  border: 0;
  background: transparent;
  padding: 6px 10px;
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  cursor: pointer;
  color: var(--text-muted, #555);
}
.notif-compose-mode button.active {
  background: var(--surface, #fff);
  color: var(--text, #222);
  box-shadow: 0 1px 2px rgba(0,0,0,0.06);
  font-weight: 600;
}
.notif-compose-hint {
  font-size: var(--fs-xs);
  color: var(--text-muted, #666);
  margin-top: -8px;
  margin-bottom: 12px;
}

/* Bell panel "Send notification" button */
.notif-compose-btn {
  border: 0;
  background: transparent;
  color: var(--action-blue, #16C7C9);
  font-size: var(--fs-xs);
  font-weight: 600;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: var(--r-sm);
}
.notif-compose-btn:hover { background: rgba(21, 101, 192, 0.08); }

/* ============================================================
   POLISH-03: universal polish — focus rings, empty-state cells,
   sortable header affordance. Picks up everything outside the
   .grid form inputs (which keep their existing border+shadow
   focus treatment). See UI-REVIEW.md Top-5 #4, M4, H2. */

/* Keyboard-accessible focus rings — :focus-visible only fires on
   actual keyboard nav, so mouse clicks don't get the outline.
   Form inputs keep their existing 2px box-shadow treatment. */
:focus-visible {
  outline: 2px solid var(--action-blue);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}
button:focus-visible,
a:focus-visible,
input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible,
[role="button"]:focus-visible {
  outline-offset: 2px;
}
/* Form grid inputs already define their own focus treatment — opt out. */
.grid input:focus-visible,
.grid select:focus-visible,
.grid textarea:focus-visible {
  outline: none;
}

/* Labeled empty-state cell — replaces literal "—" placeholders. Used in
   table cells, kanban empty columns, and metric fallbacks. Italic +
   muted color clearly reads "no value yet" rather than "broken data". */
.cell-empty {
  color: var(--cell-empty);
  font-style: italic;
  font-size: var(--fs-sm);
}

/* Sortable header affordance — only show the click cursor on TH cells
   that are actually sortable (have data-sort). Plain TH stays default
   cursor. See UI-REVIEW.md M4. */
th { cursor: default; }
th[data-sort] { cursor: pointer; }
th[data-sort]:hover { background: #eef0f2; }

/* ============================================================
   POLISH-04: toast + confirm modal — replaces native alert() /
   confirm() / prompt(). Fixed bottom-right toast stack with
   auto-dismiss; centered confirm dialog reuses .modal patterns.
   See UI-REVIEW.md Top-5 #1, H1. */

#toast-stack {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
  max-width: 360px;
}
.toast {
  background: #fff;
  border-left: 4px solid var(--action-blue);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  padding: 12px 16px;
  font-size: var(--fs-sm);
  color: var(--brand-ink);
  pointer-events: auto;
  display: flex;
  gap: 10px;
  align-items: flex-start;
  animation: toast-in 180ms ease-out;
}
.toast.toast-success { border-left-color: #16a34a; }
.toast.toast-error   { border-left-color: var(--brand-red); }
.toast.toast-info    { border-left-color: var(--action-blue); }
.toast.toast-leaving { animation: toast-out 160ms ease-in forwards; }
.toast .toast-msg { flex: 1; line-height: 1.4; word-break: break-word; }
.toast .toast-close {
  background: none;
  border: none;
  cursor: pointer;
  color: #94a3b8;
  font-size: 16px;
  padding: 0 0 0 4px;
  line-height: 1;
}
.toast .toast-close:hover { color: var(--brand-ink); }
@keyframes toast-in {
  from { transform: translateY(8px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}
@keyframes toast-out {
  to { transform: translateY(8px); opacity: 0; }
}

/* Confirm modal — sits on top of every other modal, blocks interaction
   until the user picks Cancel or Confirm. Promise-based API in app.js. */
#confirm-modal,
#notif-compose-modal {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.45);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 10000;
  padding: 16px;
}
#confirm-modal.active,
#notif-compose-modal.active { display: flex; }
/* The compose modal shares button + card chrome with #confirm-modal. */
#notif-compose-modal .confirm-card {
  background: #fff;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xl);
  width: 100%;
  max-width: 480px;
  padding: 24px;
  animation: toast-in 160ms ease-out;
}
#notif-compose-modal .confirm-title {
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--brand-ink);
  margin: 0 0 16px;
}
#notif-compose-modal .confirm-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}
#notif-compose-modal .confirm-actions button {
  font-size: var(--fs-sm);
  font-weight: 600;
  padding: 8px 16px;
  border-radius: var(--r-md);
  border: 1px solid #d0d4da;
  background: #fff;
  cursor: pointer;
}
#notif-compose-modal .confirm-actions button.confirm-primary {
  background: var(--action-blue);
  color: #fff;
  border-color: var(--action-blue);
}
#notif-compose-modal .confirm-actions button.confirm-primary:hover {
  background: var(--action-blue-dark);
}
#notif-compose-modal .confirm-actions button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* NOTIF-12: broadcast popup. Pops up over everything when a new team
   announcement arrives — user has to click the X or "Got it" to
   dismiss. Backdrop clicks are intentionally NOT a dismiss path. */
#broadcast-popup-modal {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.62);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 11000; /* above #confirm-modal so it always wins */
  padding: 16px;
  animation: broadcast-fade-in 200ms ease-out;
}
#broadcast-popup-modal.active { display: flex; }
@keyframes broadcast-fade-in {
  from { background: rgba(15, 23, 42, 0); }
  to   { background: rgba(15, 23, 42, 0.62); }
}
#broadcast-popup-modal .broadcast-card {
  position: relative;
  background: #fff;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xl);
  width: 100%;
  max-width: 480px;
  padding: 28px 28px 20px;
  border-top: 6px solid #f59e0b; /* amber accent — matches broadcast chip */
  animation: broadcast-pop 220ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes broadcast-pop {
  from { transform: scale(0.92); opacity: 0; }
  to   { transform: scale(1);    opacity: 1; }
}
#broadcast-popup-modal .broadcast-close {
  position: absolute;
  top: 8px;
  right: 8px;
  border: 0;
  background: transparent;
  font-size: 24px;
  line-height: 1;
  color: #475569;
  cursor: pointer;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}
#broadcast-popup-modal .broadcast-close:hover {
  background: rgba(15, 23, 42, 0.06);
  color: var(--brand-ink, #0f172a);
}
#broadcast-popup-modal .broadcast-eyebrow {
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #b45309; /* deeper amber for contrast */
  margin-bottom: 8px;
}
#broadcast-popup-modal .broadcast-title {
  font-size: var(--fs-xl, 20px);
  font-weight: 700;
  color: var(--brand-ink, #0f172a);
  margin: 0 0 12px;
  line-height: 1.3;
}
#broadcast-popup-modal .broadcast-body {
  font-size: var(--fs-md, 15px);
  color: #334155;
  line-height: 1.55;
  margin: 0 0 16px;
  white-space: pre-wrap;
  word-wrap: break-word;
}
#broadcast-popup-modal .broadcast-body:empty { display: none; }
#broadcast-popup-modal .broadcast-meta {
  font-size: var(--fs-xs);
  color: #94a3b8;
  margin-bottom: 16px;
}
#broadcast-popup-modal .broadcast-meta:empty { display: none; }
#broadcast-popup-modal .broadcast-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
#broadcast-popup-modal .broadcast-view-job {
  font-size: var(--fs-sm);
  font-weight: 600;
  padding: 10px 22px;
  border-radius: var(--r-md);
  border: 1px solid var(--action-blue);
  background: #fff;
  color: var(--action-blue);
  cursor: pointer;
}
#broadcast-popup-modal .broadcast-view-job:hover {
  background: #f0f9ff;
}
#broadcast-popup-modal .broadcast-ack {
  font-size: var(--fs-sm);
  font-weight: 600;
  padding: 10px 22px;
  border-radius: var(--r-md);
  border: 0;
  background: var(--action-blue);
  color: #fff;
  cursor: pointer;
}
#broadcast-popup-modal .broadcast-ack:hover {
  background: var(--action-blue-dark);
}
#broadcast-popup-modal .broadcast-ack:focus-visible {
  outline: 2px solid var(--action-blue-dark);
  outline-offset: 2px;
}
#confirm-modal .confirm-card {
  background: #fff;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xl);
  width: 100%;
  max-width: 420px;
  padding: 24px;
  animation: toast-in 160ms ease-out;
}
#confirm-modal .confirm-title {
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--brand-ink);
  margin: 0 0 8px;
}
#confirm-modal .confirm-msg {
  font-size: var(--fs-sm);
  color: #475569;
  line-height: 1.5;
  margin: 0 0 20px;
  white-space: pre-wrap;
}
/* Optional date row (completion quick-actions: "Completed on" picker so a
   job can be completed as of a past date). */
#confirm-modal .confirm-date-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: -8px 0 20px;
  font-size: var(--fs-sm);
  color: #475569;
  font-weight: 600;
}
#confirm-modal .confirm-date-input {
  padding: 6px 10px;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  font: inherit;
  color: var(--text-body);
}
/* Optional note row (e.g. "why did this move backward?") — same slot
   pattern as confirm-date-row above. */
/* confirmDialog's optional picker — same shape as .confirm-date-row and
   .confirm-text-row below, so a dialog that asks "which one?" looks like every
   other dialog rather than a bespoke screen. Scoped to #confirm-modal like its
   siblings. */
#confirm-modal .confirm-select-row {
  display: flex; flex-direction: column; gap: 6px;
  margin: -8px 0 20px; font-size: var(--fs-sm); color: #475569; font-weight: 600;
}
#confirm-modal .confirm-select-input {
  padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px;
  font-size: var(--fs-sm); font-weight: 400; max-width: 100%; background: #fff;
}
#confirm-modal .confirm-text-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: -8px 0 20px;
  font-size: var(--fs-sm);
  color: #475569;
  font-weight: 600;
}
#confirm-modal .confirm-text-input {
  padding: 8px 10px;
  border: 1px solid #d0d4da;
  border-radius: var(--r-md);
  font: inherit;
  font-weight: 400;
  color: var(--text-body);
  resize: vertical;
}
#confirm-modal .confirm-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}
#confirm-modal .confirm-actions button,
#ticket-new-modal .confirm-actions button {
  font-size: var(--fs-sm);
  font-weight: 600;
  padding: 8px 16px;
  border-radius: var(--r-md);
  border: 1px solid #d0d4da;
  background: #fff;
  cursor: pointer;
}
#confirm-modal .confirm-actions button.confirm-primary,
#ticket-new-modal .confirm-actions button.confirm-primary,
#ticket-detail-modal button.confirm-primary {
  background: var(--action-blue);
  color: #fff;
  border-color: var(--action-blue);
}
#confirm-modal .confirm-actions button.confirm-primary:hover,
#ticket-new-modal .confirm-actions button.confirm-primary:hover,
#ticket-detail-modal button.confirm-primary:hover {
  background: var(--action-blue-dark);
}
#confirm-modal .confirm-actions button.confirm-danger {
  background: var(--brand-red);
  color: #fff;
  border-color: var(--brand-red);
}
#confirm-modal .confirm-actions button.confirm-danger:hover {
  background: var(--brand-red-dark);
}

/* FP-STAGES: Fully Promoted stage manager */
#manage-stages-btn {
  border: 1px solid var(--brand-red);
  color: var(--brand-red);
  background: #fff;
  border-radius: 6px;
  padding: 6px 12px;
  font-weight: 600;
  cursor: pointer;
}
#manage-stages-btn:hover { background: var(--brand-red); color: #fff; }
.stages-editor {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  padding: 4px 2px 8px;
}
@media (max-width: 720px) { .stages-editor { grid-template-columns: 1fr; } }
.stages-group h3 {
  margin: 0 0 10px;
  font-size: 0.95rem;
  color: var(--brand-red);
}
.stages-list { list-style: none; margin: 0 0 12px; padding: 0; }
.stages-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  border: 1px solid #e3e8ee;
  border-radius: 8px;
  margin-bottom: 6px;
  background: #fff;
}
.stages-row.stage-inactive { opacity: 0.55; background: #f6f8fa; }
.stages-reorder { display: flex; flex-direction: column; gap: 2px; }
.stages-reorder button {
  border: none; background: #eef2f6; color: #4a5763;
  width: 22px; height: 16px; line-height: 14px; font-size: 9px;
  border-radius: 4px; cursor: pointer; padding: 0;
}
.stages-reorder button:disabled { opacity: 0.3; cursor: default; }
.stage-label {
  flex: 1; min-width: 0; padding: 6px 8px;
  border: 1px solid #d4dbe2; border-radius: 6px; font-size: 0.9rem;
}
.stage-rename {
  border: 1px solid #cbd5dd; background: #f6f8fa; color: #44525e;
  border-radius: 6px; padding: 6px 10px; cursor: pointer; font-size: 0.82rem;
}
.stage-rename:hover { background: #e9eef2; }
.stage-toggle {
  border: 1px solid #cbd5dd; background: #f6f8fa; color: #44525e;
  border-radius: 6px; padding: 6px 10px; cursor: pointer; font-size: 0.82rem; white-space: nowrap;
}
.stage-toggle:hover { background: #e9eef2; }
.stage-reactivate {
  border: 1px solid var(--brand-red); background: #fff; color: var(--brand-red);
  border-radius: 6px; padding: 6px 10px; cursor: pointer; font-size: 0.82rem; white-space: nowrap;
}
.stage-reactivate:hover { background: var(--brand-red); color: #fff; }
.stage-remove {
  border: none; background: transparent; color: #b54a4a;
  font-size: 1rem; cursor: pointer; padding: 4px 6px; border-radius: 6px;
}
.stage-remove:hover { background: #fbeaea; }
.stages-empty { color: #8a95a0; font-size: 0.85rem; padding: 6px 2px; }
.stages-add { display: flex; gap: 8px; }
.stages-add input {
  flex: 1; padding: 8px 10px;
  border: 1px solid #d4dbe2; border-radius: 6px; font-size: 0.9rem;
}
.stages-add button {
  border: 1px solid var(--brand-red); background: var(--brand-red); color: #fff;
  border-radius: 6px; padding: 8px 14px; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.stages-add button:hover { background: var(--brand-red-dark); }

/* FP-VENDORS: vendor-management panel — reuses the stage-manager row styles. */
.manage-vendors-link {
  border: 1px solid var(--brand-red);
  color: var(--brand-red);
  background: #fff;
  border-radius: 6px;
  padding: 3px 10px;
  margin-left: 10px;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
}
.manage-vendors-link:hover { background: var(--brand-red); color: #fff; }
.vendor-row.vendor-inactive { opacity: 0.55; background: #f6f8fa; }

/* BRAND: Fully Promoted "Jobs in progress" dashboard card */
.fp-jobs-card {
  background: #fff;
  border: 1px solid #e3e8ee;
  border-radius: 12px;
  padding: 16px 18px;
  margin-bottom: 18px;
  box-shadow: 0 1px 3px rgba(16, 118, 188, 0.06);
}
.fp-jobs-card h3 {
  margin: 0 0 12px;
  font-size: 1rem;
  color: var(--brand-red);
  display: flex;
  align-items: center;
  gap: 8px;
}
.fp-jobs-count { color: #8a95a0; font-weight: 500; font-size: 0.85rem; }
.fp-jobs-list { display: flex; flex-direction: column; gap: 2px; max-height: 360px; overflow-y: auto; }
.fp-job-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 10px;
  border-radius: 8px;
  cursor: pointer;
}
.fp-job-row:hover { background: #eef6fc; }
.fp-job-company { font-weight: 600; color: #2a3742; }
.fp-job-stage {
  font-size: 0.8rem;
  color: #0A5A8F;
  background: #e3f1fb;
  border-radius: 999px;
  padding: 3px 10px;
  white-space: nowrap;
}
.fp-jobs-card .empty { color: #8a95a0; font-size: 0.88rem; padding: 8px 2px; }

/* FP-ESTIMATES: "New estimate requests" review section — shown on the FP
   dashboard (card) and atop the Project Pipeline board (banner). Amber accent
   signals "needs review", matching the calendar pending-review cards. */
.fp-estimates-card {
  background: #fff;
  border: 1px solid #e3e8ee;
  border-left: 3px solid #f9a825;
  border-radius: 12px;
  padding: 16px 18px;
  margin-bottom: 18px;
  box-shadow: 0 1px 3px rgba(16, 118, 188, 0.06);
}
.fp-estimates-card h3,
.fp-estimates-banner-head h3 {
  margin: 0 0 12px;
  font-size: 1rem;
  color: var(--brand-red);
  display: flex;
  align-items: center;
  gap: 8px;
}
.fp-estimates-count { color: #8a95a0; font-weight: 500; font-size: 0.85rem; }
.fp-estimates-banner {
  background: #fffdf7;
  border: 1px solid #f0e2c0;
  border-radius: 12px;
  padding: 14px 16px;
  margin-bottom: 16px;
}
.fp-estimates-banner-head h3 { margin-bottom: 10px; }
.fp-estimates-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 10px;
}
.fp-estimates-list .empty { color: #8a95a0; font-size: 0.88rem; padding: 6px 2px; }
.fp-estimate-card {
  background: #fff8e1;
  border: 1px solid #f0c869;
  border-left: 3px solid #f9a825;
  border-radius: var(--r-md);
  padding: 10px 12px;
  font-size: 13px;
}
.fp-estimate-card.is-rush { border-left-color: #c5221f; background: #fdecea; }
.fer-company { font-weight: 600; color: #1f2329; margin-bottom: 4px; line-height: 1.25; word-break: break-word; }
.fer-rush-flag { color: #c5221f; font-weight: 700; margin-left: 6px; font-size: 11px; }
.fer-meta { font-size: 11px; color: #56606b; margin-bottom: 8px; }
.fer-meta .dot-sep { margin: 0 4px; color: #b0b6bd; }
.fer-actions { display: flex; gap: 4px; flex-wrap: wrap; }
.fer-actions button {
  font-size: 12px;
  padding: 4px 8px;
  border-radius: var(--r-sm);
  border: 1px solid #d0d4da;
  background: #fff;
  cursor: pointer;
  font-family: inherit;
}
.fer-accept { background: #137333 !important; color: #fff !important; border-color: #137333 !important; }
.fer-accept:hover { background: #0e5e29 !important; }
.fer-edit:hover { background: #f0f1f3; }
.fer-discard { color: #c5221f; margin-left: auto; }
.fer-discard:hover { background: #fce8e6; }

/* AI-01: daily attention briefing card */
.ai-insights-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  border: 1px solid #c7d6ea;
  border-radius: 8px;
  background: #fff;
  color: #285b91;
  padding: 6px 10px;
  font: inherit;
  font-size: .8rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}
.ai-insights-btn:hover { background: #eef6fc; border-color: #9db9dc; }
.ai-briefing-modal-content { width: min(780px, 94vw); max-height: min(88vh, 820px); overflow: auto; }
#ai-briefing-modal .ai-briefing-modal-hero {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  padding: 24px 72px 20px 28px;
  background: linear-gradient(135deg, #eef4ff 0%, #f8faff 58%, #fff 100%);
  border-bottom: 1px solid #dfe8f4;
}
#ai-briefing-modal-close { position: absolute; top: 18px; right: 18px; }
.ai-briefing-modal-hero > div { min-width: 0; }
.ai-briefing-eyebrow { display: block; margin-bottom: 5px; color: #2a5a8f; font-size: .72rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
#ai-briefing-modal .ai-briefing-modal-hero h2 { margin: 0; color: #183b62; font-size: 1.35rem; line-height: 1.25; }
.ai-briefing-modal-hero p { margin: 6px 0 0; color: #64748b; font-size: .86rem; }
.ai-briefing-modal-body { display: grid; gap: 14px; padding: 20px 24px; }
.ai-briefing-modal-body .ai-briefing-card { margin: 0; }
.ai-briefing-modal-footer { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 24px 18px; border-top: 1px solid #eef0f3; }
.ai-briefing-modal-footer span { color: #7a8794; font-size: .76rem; }
.ai-briefing-modal-footer button { border: 1px solid #16C7C9; border-radius: 7px; background: #16C7C9; color: #fff; padding: 8px 20px; font: inherit; font-size: .84rem; font-weight: 700; cursor: pointer; }
.ai-briefing-modal-footer button:hover { background: #0E9799; }
.ai-briefing-card {
  background: linear-gradient(135deg, #f5f8ff 0%, #eef3fb 100%);
  border: 1px solid #d9e4f5;
  border-radius: 12px;
  padding: 14px 18px;
  margin-bottom: 16px;
}
.ai-briefing-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}
.ai-briefing-head h3 { margin: 0; font-size: 1rem; color: #1f3a5f; }
.ai-briefing-actions { display: flex; align-items: center; gap: 10px; }
.ai-briefing-meta { font-size: 0.75rem; color: #8a95a0; }
.ai-briefing-refresh {
  border: 1px solid #c7d6ea; background: #fff; color: #2a5a8f;
  border-radius: 6px; width: 28px; height: 28px; cursor: pointer; font-size: 0.95rem; line-height: 1;
}
.ai-briefing-refresh:hover { background: #eef6fc; }
.ai-briefing-body { display: flex; flex-direction: column; gap: 5px; }
.ai-briefing-line {
  font-size: 0.9rem; color: #2a3742; line-height: 1.45;
  padding-left: 2px;
}
.ai-briefing-loading, .ai-briefing-empty { font-size: 0.88rem; color: #8a95a0; font-style: italic; }

@media (max-width: 720px) {
  .ai-insights-btn-label { display: none; }
  .ai-insights-btn { width: 36px; justify-content: center; padding: 6px; font-size: 1rem; }
  #ai-briefing-modal .ai-briefing-modal-hero { padding: 20px 64px 16px 18px; }
  .ai-briefing-modal-body { padding: 14px; }
  .ai-briefing-modal-footer { align-items: stretch; flex-direction: column; padding: 12px 16px 18px; }
  .ai-briefing-modal-footer button { width: 100%; min-height: 44px; }
  .ai-briefing-head { align-items: flex-start; }
  .ai-briefing-actions { flex-direction: column-reverse; align-items: flex-end; gap: 4px; }
}

/* AI-03: pending-inbox triage suggestion */
.psc-suggestion:empty { display: none; }
.psc-suggestion {
  margin: 4px 0 2px; font-size: 0.8rem; display: flex; align-items: center;
  gap: 8px; flex-wrap: wrap;
}
.psc-suggest-text { color: #2a5a8f; }
.psc-suggest-text em { color: #8a95a0; font-style: normal; font-size: 0.72rem; }
.psc-suggest-loading, .psc-suggest-err { color: #8a95a0; font-style: italic; }
.psc-suggest-apply {
  border: 1px solid #2e7d32; background: #2e7d32; color: #fff;
  border-radius: 5px; padding: 2px 8px; font-size: 0.75rem; cursor: pointer;
}
.psc-suggest-apply:hover { background: #266a2b; }
.psc-suggest {
  border: 1px solid #c7d6ea; background: #f5f8ff; color: #2a5a8f;
  border-radius: 5px; cursor: pointer;
}

/* Topbar refresh-data button */
.refresh-data-btn {
  border: 1px solid #c7d6ea; background: #fff; color: #2a5a8f;
  border-radius: 8px; width: 36px; height: 36px; cursor: pointer;
  font-size: 1.1rem; line-height: 1; display: inline-flex;
  align-items: center; justify-content: center;
}
.refresh-data-btn:hover { background: #eef6fc; }
.refresh-data-btn:disabled { opacity: 0.6; cursor: default; }
.refresh-data-btn.spinning { animation: refresh-spin 0.8s linear infinite; }

/* Corebridge freshness is operationally critical, so stale/offline state is
   visible above every workspace rather than buried on the dashboard. */
.corebridge-sync-alert {
  display: flex;
  align-items: center;
  gap: 11px;
  margin: 12px 24px 0;
  padding: 11px 13px;
  border: 1px solid #e4a11b;
  border-left-width: 5px;
  border-radius: 9px;
  background: #fff8e7;
  color: #5f4100;
  box-shadow: 0 2px 8px rgba(95, 65, 0, .08);
}
.corebridge-sync-alert.hidden { display: none; }
.corebridge-sync-alert.is-stale { border-color: #c62828; background: #fff0f0; color: #7f1d1d; }
.corebridge-sync-alert.is-unknown { border-color: #64748b; background: #f8fafc; color: #334155; }
.corebridge-sync-alert-icon { font-size: 1.2rem; flex: 0 0 auto; }
.corebridge-sync-alert-copy { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: 2px; }
.corebridge-sync-alert-copy strong { font-size: .88rem; }
.corebridge-sync-alert-copy span { font-size: .78rem; line-height: 1.35; }
.corebridge-sync-now {
  flex: 0 0 auto;
  border: 0;
  border-radius: 7px;
  background: #b91c1c;
  color: #fff;
  padding: 8px 13px;
  font: inherit;
  font-size: .82rem;
  font-weight: 700;
  cursor: pointer;
}
.corebridge-sync-alert:not(.is-stale) .corebridge-sync-now { background: #9a6700; }
.corebridge-sync-now:disabled { opacity: .65; cursor: wait; }
@media (max-width: 720px) {
  .corebridge-sync-alert { margin: 8px 12px 0; align-items: flex-start; flex-wrap: wrap; }
  .corebridge-sync-alert-copy { min-width: calc(100% - 40px); }
  .corebridge-sync-now { margin-left: 31px; }
}
@keyframes refresh-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

/* small inline hint inside form labels */
.field-hint { font-weight: 400; color: #8a95a0; font-size: 0.78rem; }

/* CUST-AUTOCOMPLETE: customer suggestions under the Company field */
.company-field { position: relative; }
.cust-suggest {
  position: absolute; left: 0; right: 0; top: 100%; z-index: 50;
  background: #fff; border: 1px solid #c7d6ea; border-top: none;
  border-radius: 0 0 8px 8px; box-shadow: 0 6px 16px rgba(16,40,80,0.12);
  max-height: 260px; overflow-y: auto;
}
.cust-suggest-item {
  display: flex; flex-direction: column; gap: 1px; width: 100%; text-align: left;
  background: none; border: none; border-bottom: 1px solid #f0f3f8;
  padding: 7px 10px; cursor: pointer;
}
.cust-suggest-item:hover { background: #eef6fc; }
.cust-co { font-weight: 600; color: #2a3742; font-size: 0.9rem; }
.cust-meta { color: #8a95a0; font-size: 0.78rem; }

.mini-cal-hint { color: #8a95a0; font-size: 0.72rem; }

/* Sidebar "Admin" section label */
.sidebar-section-label {
  margin: 14px 12px 4px;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #8a95a0;
}
.sidebar-section-label.hidden { display: none; }

/* BRIEF-LINK: clickable job names inside Today's Briefing lines */
.ai-job-link {
  color: inherit;
  font-weight: 600;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  cursor: pointer;
}
.ai-job-link:hover { text-decoration-style: solid; color: #16C7C9; }

/* PULSE-MODAL: Business Pulse in-app (same content as /pulse, no navigation) */
.pm-hero-card { border-left: 4px solid var(--action-blue); cursor: pointer; }
.pm-tap { cursor: pointer; }
.pm-meter { height: 10px; border-radius: var(--r-sm); background: #DBEAFE; overflow: hidden; }
.pm-meter-fill { height: 100%; border-radius: var(--r-sm); background: var(--action-blue); width: 0; transition: width 0.4s; }
#pm-drill-list .dl-item { cursor: pointer; align-items: flex-start; }
#pm-drill-list .dl-item.dimmed { opacity: 0.55; }
#pm-drill-list .dl-label { display: flex; flex-direction: column; }
#pm-drill-list .dl-meta { display: block; margin-top: 2px; }
#pm-drill-list .dl-date { white-space: nowrap; }

/* ADMIN: admin dashboard tab */
#admin-pulse-card { cursor: pointer; }
#admin-pulse-card:hover { background: #f8fafc; }
#admin-pulse-card .admin-tile { pointer-events: none; }
.admin-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
}
#tab-admin > .dashboard-list-card { margin-top: 16px; }
#admin-audit-list .dl-item { cursor: default; }
#admin-audit-list .dl-meta { margin-left: auto; color: #8a95a0; font-size: 12px; }

/* ATTEND: Team attendance card + record modal */
#attendance-card { margin-top: 16px; }
#attendance-card.att-flash {
  outline: 2px solid #16C7C9;
  outline-offset: 2px;
  transition: outline-color 0.3s ease;
}
.att-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; margin-bottom: 4px;
}
.att-head h3 { margin: 0; }
.att-controls { display: flex; align-items: center; gap: 6px; }
.att-year-label { font-weight: 600; color: #56606b; font-size: 13px; min-width: 38px; text-align: center; }
.att-controls select {
  padding: 4px 8px; border: 1px solid var(--border-soft); border-radius: 8px;
  font-size: 13px; color: #2a3742; background: #fff; cursor: pointer;
}
.att-row .dl-label { display: inline-flex; align-items: center; gap: 6px; }
.att-row .dl-meta { flex: 1; color: #8a95a0; font-size: 12px; text-align: right; }
.att-row .att-days { min-width: 56px; text-align: right; }
.att-year-head {
  padding: 10px 10px 4px;
  font-size: 12px;
  color: #56606b;
  border-bottom: 1px solid #f0f3f8;
  margin-bottom: 4px;
}
.att-year-head:not(:first-child) { margin-top: 10px; }

/* Day-view modal footer: add-to-this-day + open-in-calendar actions */
.day-actions {
  display: flex; gap: 8px; flex-wrap: wrap;
  padding: 0 24px 20px;
}
.day-actions button {
  flex: 1; min-width: 130px;
  background: #f5f7fa; border: 1px solid var(--border-soft); border-radius: 8px;
  padding: 10px 12px; cursor: pointer; font-size: 0.88rem; color: #2a3742;
}
.day-actions button:hover { background: #eef6fc; }

/* Notification settings panel */
.notif-settings-body { padding: 4px 2px 2px; }
.ns-group { padding: 10px 0; border-bottom: 1px solid #f0f3f8; }
.ns-group:last-of-type { border-bottom: none; }
.ns-row { display: flex; align-items: center; gap: 9px; padding: 5px 2px; font-size: 0.92rem; color: #2a3742; cursor: pointer; }
.ns-row input { width: 16px; height: 16px; cursor: pointer; }
.ns-row em { color: #8a95a0; font-style: normal; font-size: 0.78rem; }
.ns-master { margin-bottom: 2px; }
.ns-sub { margin-left: 24px; }
.ns-sub.ns-disabled { opacity: 0.5; }
.ns-note { color: #8a95a0; font-size: 0.78rem; margin: 4px 2px 0; }
.ns-enable-btn { margin-top: 8px; border: 1px solid #2a5a8f; background: #2a5a8f; color: #fff; border-radius: 6px; padding: 5px 12px; font-size: 0.82rem; cursor: pointer; }
.ns-enable-btn:hover { background: #234d79; }
.ns-saved { color: #2e7d32; font-size: 0.8rem; height: 1.1em; margin-top: 8px; text-align: right; }

/* Weekly Stats: highlight the current week's row */
#weekly-table tr.current-week > td { background: #fff7e0; }
#weekly-table tr.current-week > td:first-child { box-shadow: inset 3px 0 0 #f0a500; }
.this-week-tag {
  display: inline-block; margin-left: 6px; background: #f0a500; color: #fff;
  border-radius: 999px; padding: 1px 7px; font-size: 0.66rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.03em; vertical-align: middle;
}

/* Search results dropdown — used by the calendar search (#cal-search-results).
   Named "global-search"/"gsr" from when the (now-removed) top-bar search
   used it first; kept as-is rather than renaming every selector. */
.global-search-results {
  position: absolute; z-index: 300; background: #fff;
  border: 1px solid #c7d6ea; border-radius: 10px;
  box-shadow: 0 10px 28px rgba(16,40,80,0.18); max-height: 380px; overflow-y: auto; padding: 4px;
}
.gsr-item {
  display: flex; flex-direction: column; gap: 1px; width: 100%; text-align: left;
  background: none; border: none; padding: 7px 10px; border-radius: 7px; cursor: pointer;
}
.gsr-item:hover { background: #eef6fc; }
.gsr-co { font-weight: 600; color: #2a3742; font-size: 0.9rem; }
.gsr-meta { color: #8a95a0; font-size: 0.78rem; }

/* Manage menu: link item (Install crew app) matches the button items */
.manage-menu-link {
  display: block; width: 100%; box-sizing: border-box; text-decoration: none;
  padding: 9px 14px; font: inherit; color: inherit; cursor: pointer;
  border-top: 1px solid #eef2f7;
}
.manage-menu-link:hover { background: #eef6fc; }

/* CompanyCam link in the job-modal attachments header */
.attachments-header-actions { display: flex; align-items: center; gap: 10px; }
.companycam-link {
  font-size: 0.82rem; font-weight: 600; color: #2a5a8f; text-decoration: none;
  border: 1px solid #c7d6ea; border-radius: 7px; padding: 5px 10px; background: #eef6fc;
}
.companycam-link:hover { background: #e0eefb; }

/* CompanyCam "link existing project" picker */
.companycam-search-panel { margin-top: 8px; border: 1px solid #c7d6ea; border-radius: 8px; background: #f7fafd; padding: 8px; }
.cc-search-row { display: flex; gap: 6px; align-items: center; }
.cc-search-row input { flex: 1; padding: 7px 9px; border: 1px solid #c7d6ea; border-radius: 6px; font-size: 0.9rem; }
.cc-search-row button { border: none; background: none; font-size: 1.2rem; color: #8a95a0; cursor: pointer; line-height: 1; }
.cc-search-results { margin-top: 6px; max-height: 220px; overflow-y: auto; }
.cc-hint { color: #8a95a0; font-size: 0.82rem; padding: 6px 4px; }
.cc-result { display: flex; flex-direction: column; gap: 1px; width: 100%; text-align: left; background: #fff; border: 1px solid #e3e8ee; border-radius: 6px; padding: 7px 10px; margin-bottom: 5px; cursor: pointer; }
.cc-result:hover { background: #eef6fc; }
.cc-result-name { font-weight: 600; color: #2a3742; font-size: 0.9rem; }
.cc-result-addr { color: #8a95a0; font-size: 0.78rem; }
.cc-unlink { background: none; border: none; color: #c0392b; font-size: 0.82rem; cursor: pointer; padding: 6px 4px; text-decoration: underline; }

/* ===== Job Photos gallery tab ===== */
#tab-photos.active { display: flex; flex-direction: column; height: 100%; overflow: hidden; }
.photos-header { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px 12px; flex-shrink: 0; border-bottom: 1px solid var(--border); gap: 12px; flex-wrap: wrap; }
.photos-title { margin: 0; font-size: 1.2rem; font-weight: 700; color: var(--text); }
.photos-toolbar { display: flex; align-items: center; gap: 8px; }
.photos-search { padding: 7px 12px; border: 1px solid var(--border); border-radius: 8px; font-size: 0.9rem; width: 220px; background: var(--surface); color: var(--text); }
.photos-search:focus { outline: none; border-color: var(--primary); }
.photos-refresh-btn { background: none; border: 1px solid var(--border); border-radius: 8px; padding: 6px 10px; font-size: 1rem; cursor: pointer; color: var(--text-muted); }
.photos-refresh-btn:hover { border-color: var(--primary); color: var(--primary); }
.photos-empty { color: var(--text-muted); text-align: center; padding: 48px 0; font-size: 0.95rem; }
.photos-list { flex: 1; overflow-y: auto; }
.photos-load-more-wrap { flex-shrink: 0; text-align: center; padding: 12px; }
.photos-load-more-btn { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 8px 24px; font-size: 0.9rem; cursor: pointer; color: var(--text); }
.photos-load-more-btn:hover { border-color: var(--primary); color: var(--primary); }

/* Job row (project list style) */
.pjob-row { display: grid; grid-template-columns: 80px 1fr auto; align-items: center; gap: 16px; padding: 14px 20px; border-bottom: 1px solid var(--border); cursor: pointer; transition: background 0.1s; }
.pjob-row:hover { background: var(--hover-bg, #f8f9fa); }
.pjob-row.expanded { background: var(--hover-bg, #f8f9fa); }
.pjob-cover { width: 80px; height: 60px; border-radius: 8px; overflow: hidden; background: #e8eaed; flex-shrink: 0; }
.pjob-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pjob-cover-empty { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; font-size: 1.5rem; color: #bbb; }
.pjob-info { min-width: 0; }
.pjob-name { font-weight: 600; font-size: 0.95rem; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pjob-addr { font-size: 0.8rem; color: var(--text-muted); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pjob-meta { display: flex; align-items: center; gap: 6px; margin-top: 4px; font-size: 0.78rem; color: var(--text-muted); }
.pjob-count { font-weight: 600; color: var(--primary, #16C7C9); }
.pjob-strip { display: flex; gap: 4px; align-items: center; flex-shrink: 0; }
.pjob-strip-img { width: 52px; height: 40px; border-radius: 5px; overflow: hidden; cursor: pointer; flex-shrink: 0; }
.pjob-strip-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pjob-strip-img:hover img { opacity: 0.85; }
.pjob-strip-more { width: 52px; height: 40px; border-radius: 5px; background: #e8eaed; display: flex; align-items: center; justify-content: center; font-size: 0.78rem; font-weight: 600; color: var(--text-muted); flex-shrink: 0; }

/* Expanded photo grid for a job */
.pjob-expand { background: #f3f5f7; border-bottom: 2px solid var(--border); padding: 14px 20px 14px 116px; display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 8px; }
.pjob-expand-loading { grid-column: 1/-1; color: var(--text-muted); font-size: 0.88rem; padding: 12px 0; }
.pjob-expand-thumb { position: relative; aspect-ratio: 4/3; border-radius: 7px; overflow: hidden; background: #dde0e4; cursor: pointer; }
.pjob-expand-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.15s; }
.pjob-expand-thumb:hover img { transform: scale(1.05); }
.pgallery-delete { position: absolute; top: 4px; right: 4px; background: rgba(255,255,255,0.9); border: 1px solid #ccc; border-radius: 50%; width: 22px; height: 22px; font-size: 13px; line-height: 20px; cursor: pointer; padding: 0; color: #555; z-index: 2; text-align: center; }
.pgallery-delete:hover { background: #d93025; color: #fff; border-color: #d93025; }

/* Lightbox */
/* PHOTO-ZOOM: overflow hidden so a zoomed (transformed) image clips at the
   overlay edge instead of spilling scrollbars; the cursor says it's zoomable. */
.photos-lightbox { position: fixed; inset: 0; background: rgba(0,0,0,0.88); z-index: 9000; display: flex; align-items: center; justify-content: center; overflow: hidden; }
.photos-lightbox.hidden { display: none; }
.photos-lb-img { max-width: 90vw; max-height: 85vh; object-fit: contain; border-radius: 6px; box-shadow: 0 8px 40px rgba(0,0,0,0.5); cursor: zoom-in; }
.photos-lb-close { position: absolute; top: 16px; right: 20px; background: none; border: none; color: #fff; font-size: 2rem; cursor: pointer; line-height: 1; opacity: 0.8; }
.photos-lb-close:hover { opacity: 1; }
.photos-lb-prev, .photos-lb-next { position: absolute; top: 50%; transform: translateY(-50%); background: rgba(255,255,255,0.15); border: none; color: #fff; font-size: 2rem; cursor: pointer; padding: 10px 16px; border-radius: 6px; line-height: 1; }
.photos-lb-prev { left: 16px; }
.photos-lb-next { right: 16px; }
.photos-lb-prev:hover, .photos-lb-next:hover { background: rgba(255,255,255,0.25); }
.photos-lb-caption { position: absolute; bottom: 24px; left: 50%; transform: translateX(-50%); color: rgba(255,255,255,0.85); font-size: 0.9rem; background: rgba(0,0,0,0.45); padding: 5px 14px; border-radius: 20px; white-space: nowrap; max-width: 80vw; overflow: hidden; text-overflow: ellipsis; }

/* ─── JobShot Tab ───────────────────────────────────────────────────────────── */
#tab-jobshot.active { display: flex; flex-direction: column; min-height: 0; padding: 0; }
/* The shell is the whole office page body now (title + search + stats + tab
   strip + panes), not a header strip above a separate list — so it grows and
   its panes own the scrolling. Padding lives on the head/panes rather than
   here, so a pane can scroll edge to edge. */
.jshot-shell { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.jshot-shell-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 18px 24px 14px; flex-shrink: 0; }
/* JOBSHOT-TILES: shared shape with .qtile in public/jobshot.html — radius 12,
   min-height 64, 20px icon, 13px/600 label (.81rem). D-8. */
.jshot-office-stats { display: grid; grid-template-columns: repeat(4, minmax(112px, 1fr)); gap: 10px; padding: 0 24px; flex-shrink: 0; }
.jshot-tile { appearance: none; text-align: left; font: inherit; background: #fff; border: 1px solid var(--border);
  border-radius: 12px; min-height: 64px; padding: 10px 12px; cursor: pointer; color: var(--text);
  display: flex; flex-direction: column; justify-content: center; gap: 1px; }
.jshot-tile:hover { border-color: var(--action-blue); }
.jshot-tile .jshot-tile-ico { font-size: 20px; line-height: 1; }
.jshot-tile strong { display: block; font-size: 1.2rem; color: var(--text); }
/* .81rem/600 = the field app's 13px/600 .qtile label; the sub-line is smaller. */
.jshot-tile .jshot-tile-label { display: block; color: var(--text); font-size: .81rem; font-weight: 600; }
.jshot-tile .jshot-tile-sub { display: block; color: var(--text-muted); font-size: .69rem; }
.jshot-tile.attention { border-color: #f3c46b; background: #fffaf0; }
.jshot-tile-note { grid-column: 1 / -1; color: var(--text-muted); font-size: .75rem; padding: 2px 2px 0; }

/* ── Office IA shell: segmented tab strip + panes ──────────────────────────
      Same segmented language as Material Pricing's view switcher
      (.mp-view / .mp-view-btn), one size up for a page-level nav. */
.jshot-tabs { display: inline-flex; align-self: flex-start; height: 40px; margin: 12px 24px 0; padding: 3px; border-radius: 10px; background: #edf1f5; flex-shrink: 0; max-width: calc(100% - 48px); overflow-x: auto; }
.jshot-tab-btn { border: 0; border-radius: 8px; padding: 0 14px; background: transparent; color: #748195; font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; white-space: nowrap; }
.jshot-tab-btn:hover { color: var(--text); }
.jshot-tab-btn.active { background: #fff; color: #243246; box-shadow: 0 1px 3px rgba(28,47,67,.12); }
.jshot-tab-btn:focus-visible { outline: 2px solid #16C7C9; outline-offset: 1px; }
/* Panes are the scroll container — that's what keeps the project list near
   the top of the page instead of ~1,355px down it. */
.jshot-pane { flex: 1; min-height: 0; overflow-y: auto; padding: 14px 24px 18px; }
/* The grid must not become a nested scroller inside an already-scrolling
   pane (house pattern: #id-scoped override, cf. #tab-material-pricing above). */
#jshot-pane-projects #jshot-grid { flex: none; overflow: visible; }
/* Section wrapper replacing what .jshot-fold's summary+body provided. */
.jshot-pane-block { margin-top: 14px; background: #fff; border: 1px solid var(--border); border-radius: 10px; padding: 0 14px 12px; }
.jshot-pane-block-head { display: flex; align-items: baseline; gap: 8px; padding: 11px 0 0; font-size: .9rem; }
.jshot-pane-block-head strong { color: var(--text); }
.jshot-pane-block .jshot-office-queue { padding-top: 12px; }
/* Projects filter row: subtitle + pills + the jump-to-any-job select. */
.jshot-proj-filters { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.jshot-list-filters { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.jshot-proj-filters .jshot-subtitle { margin-right: 2px; }
.jshot-pill { border: 1px solid var(--border); border-radius: 7px; padding: 5px 11px; background: #fff; color: #748195; font: inherit; font-size: 12px; font-weight: 700; cursor: pointer; white-space: nowrap; }
.jshot-pill:hover { color: var(--text); }
.jshot-pill.active { background: #102842; border-color: #102842; color: #fff; }
.jshot-pill:focus-visible { outline: 2px solid #16C7C9; outline-offset: 1px; }
.jshot-dash-card {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
  min-width: 0;
}
.jshot-dash-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}
.jshot-dash-card-head strong { font-size: .95rem; }
.jshot-dash-card-sub { color: var(--text-muted); font-size: .72rem; white-space: nowrap; }
/* JOBSHOT-HEALTH: field-sync + daily-check verdict strip above the live feed. */
.jshot-sync-strip {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  padding: 8px 12px;
  margin-bottom: 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #f0faf4;
  color: #1c7c46;
  font-size: .8rem;
  line-height: 1.4;
}
.jshot-sync-strip .ic { margin-top: .15em; }
.jshot-sync-strip.warn { background: #fff7ec; color: #a05a00; border-color: #f0d9b0; }
.jshot-live-dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: #16a34a;
  margin-right: 7px;
  animation: jshot-live-pulse 2s ease-in-out infinite;
}
@keyframes jshot-live-pulse {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(22, 163, 74, 0.35); }
  50% { opacity: .6; box-shadow: 0 0 0 5px rgba(22, 163, 74, 0); }
}
/* JOBSHOT-ACTIVITY: shared shape with .acard in public/jobshot.html — 148px
   card, 104px thumb, radius 10, 10px gap, 12 items. A horizontal rail, so the
   newest work reads left-to-right on both surfaces. D-8. */
.jshot-live-feed {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  scrollbar-width: thin;
  scroll-snap-type: x proximity;
  padding-bottom: 4px;
}
.jshot-live-item {
  flex: none;
  width: 148px;
  display: block;
  text-align: left;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  padding: 0;
  cursor: pointer;
  scroll-snap-align: start;
}
.jshot-live-item:hover { border-color: #9ebce8; }
.jshot-live-item:disabled { cursor: default; opacity: .75; }
.jshot-live-item.fresh { animation: jshot-live-fresh 3s ease-out; }
@keyframes jshot-live-fresh {
  0% { background: #e8f7ee; }
  100% { background: #fff; }
}
.jshot-live-item img {
  width: 100%; height: 104px;
  object-fit: cover;
  display: block;
  background: #eef1f4;
}
.jshot-live-company { display: block; font-weight: 600; font-size: .75rem; color: var(--text); padding: 6px 8px 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jshot-live-meta { display: block; color: var(--text-muted); font-size: .69rem; padding: 1px 8px 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The find-any-job card had its own input; the shell header's #jshot-search
   drives it now, so only the results list survives. */
.jshot-find-results { display: flex; flex-direction: column; max-height: 372px; overflow-y: auto; margin-bottom: 12px; border: 1px solid var(--border); border-radius: 10px; background: #fff; }
.jshot-find-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-bottom: 1px solid #f0f2f5;
  padding: 8px 4px;
  cursor: pointer;
  border-radius: 6px;
}
.jshot-find-row:last-child { border-bottom: none; }
.jshot-find-row:hover { background: #f6f9fc; }
.jshot-find-main { min-width: 0; display: flex; flex-direction: column; }
.jshot-find-company { font-weight: 600; font-size: .84rem; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jshot-find-meta { color: var(--text-muted); font-size: .74rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jshot-find-end { display: flex; flex-direction: column; align-items: flex-end; color: var(--text-muted); font-size: .74rem; white-space: nowrap; }
/* .jshot-fold* retired with the <details> wrappers — .jshot-pane-block
   (above) provides the heading row + body those sections needed. The sub
   label is still used by #jshot-review-summary and #jshot-map-summary. */
.jshot-fold-sub { color: var(--text-muted); font-size: .75rem; font-weight: 400; }

/* Client gallery builder modal */
.jshot-share-switch { display: flex; gap: 8px; align-items: baseline; margin-top: 8px; font-size: .88rem; cursor: pointer; }
.jshot-share-switch .hint { font-weight: 400; }
.jshot-share-url { background: #f6f8fa; border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; font-size: .85rem; }
.jshot-share-url code { word-break: break-all; }
.jshot-share-url button { margin-left: 8px; }
.jshot-share-pin-note { margin-top: 8px; color: #b45309; font-size: .85rem; }
.jshot-share-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid #f0f2f5; font-size: .85rem; }
.jshot-share-row:last-child { border-bottom: none; }
.jshot-share-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.jshot-share-row a { font-size: .8rem; }
/* Second subject added for the cross-project list so Revoke looks identical
   in both places — the declaration itself is untouched. */
.jshot-share-row .danger,
.jshot-cs-row .danger { color: #d93025; background: none; border: 1px solid #f0c4c0; border-radius: 6px; padding: 3px 8px; cursor: pointer; font-size: .78rem; }

/* ── Client sharing pane: every client link across every project ───────────
      Own .jshot-cs-* classes rather than reusing .jshot-share-row (which the
      gallery modal owns globally) — same visual language, no shared coupling. */
.jshot-cs-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; font-size: .9rem; }
.jshot-cs-head strong { color: var(--text); }
#jshot-share-states { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.jshot-cs-tally { color: var(--text-muted); font-size: .78rem; }
/* No max-height / overflow here: .jshot-pane is already the scroll container,
   and a nested scroller is the bug Phase 1 removed from #jshot-grid. */
.jshot-cs-list { display: block; }
.jshot-cs-row { display: flex; align-items: center; gap: 10px; padding: 10px 0; border-bottom: 1px solid #f0f2f5; font-size: .85rem; }
.jshot-cs-row:last-child { border-bottom: none; }
.jshot-cs-row.is-dead { opacity: .62; }
.jshot-cs-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.jshot-cs-top { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.jshot-cs-job { border: 0; background: none; padding: 0; font: inherit; font-weight: 600; color: var(--text); cursor: pointer; text-align: left; }
.jshot-cs-job:hover { text-decoration: underline; }
.jshot-cs-job:focus-visible { outline: 2px solid #16C7C9; outline-offset: 1px; }
.jshot-cs-job:disabled { cursor: default; color: var(--text-muted); text-decoration: none; }
.jshot-cs-meta { color: var(--text-muted); font-size: .74rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jshot-cs-chip { font-size: .66rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; border-radius: 999px; padding: 2px 7px; border: 1px solid transparent; white-space: nowrap; }
.jshot-cs-chip.is-live { color: #0E9799; background: #e6fbfb; border-color: #16C7C9; }
.jshot-cs-chip.is-expired { color: #92610a; background: #fffaf0; border-color: #f3c46b; }
.jshot-cs-chip.is-revoked { color: #d93025; background: #fdf0ef; border-color: #f0c4c0; }
.jshot-cs-type { color: var(--text-muted); font-size: .74rem; white-space: nowrap; }
.jshot-cs-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.jshot-cs-actions a { font-size: .8rem; }
.jshot-cs-copy { border: 1px solid var(--border); border-radius: 6px; background: #fff; color: var(--text); padding: 3px 8px; font: inherit; font-size: .78rem; cursor: pointer; }
.jshot-cs-copy:hover { background: #f6f9fc; }
@media (max-width: 700px) {
  /* Let the actions drop under the main column so the meta lines aren't
     squeezed to an ellipsis on a tablet. */
  .jshot-cs-row { align-items: flex-start; flex-wrap: wrap; }
  .jshot-cs-actions { width: 100%; justify-content: flex-end; }
}

/* Before/after composer */
.jshot-ba-toolbar { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.jshot-ba-slots { display: flex; gap: 8px; align-items: center; }
.jshot-ba-slot {
  width: 96px; height: 68px;
  border: 2px dashed #c6ccd4; border-radius: 8px;
  background: #f6f8fa center/cover no-repeat;
  cursor: pointer; position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
}
.jshot-ba-slot.filled { border-style: solid; }
.jshot-ba-slot.active { border-color: var(--action-blue); }
.jshot-ba-slot-label { font-size: .66rem; font-weight: 800; letter-spacing: .06em; background: rgba(15,23,42,.8); color: #fff; padding: 1px 6px; border-radius: 4px; }
.jshot-ba-slot-hint { font-size: .66rem; color: #475569; background: rgba(255,255,255,.85); padding: 1px 5px; border-radius: 4px; }
.jshot-ba-formats { display: flex; gap: 4px; }
.jshot-ba-formats button { padding: 6px 10px; border: 1px solid #d0d4da; background: #fff; border-radius: 8px; font-size: .8rem; cursor: pointer; }
.jshot-ba-formats button.on { background: var(--action-blue); border-color: var(--action-blue); color: #fff; }
.jshot-ba-picker { display: flex; gap: 8px; flex-wrap: wrap; max-height: 220px; overflow-y: auto; border: 1px solid var(--border); border-radius: 10px; padding: 10px; margin-bottom: 10px; background: #fafbfc; }
.jshot-ba-picker .hint { width: 100%; }
.jshot-ba-pick { position: relative; width: 84px; height: 84px; border: 2px solid transparent; border-radius: 8px; overflow: hidden; padding: 0; cursor: pointer; background: #eef1f4; }
.jshot-ba-pick:hover { border-color: var(--action-blue); }
.jshot-ba-pick img { width: 100%; height: 100%; object-fit: cover; display: block; }
.jshot-ba-pick span { position: absolute; bottom: 2px; left: 2px; font-size: .62rem; background: rgba(15,23,42,.75); color: #fff; padding: 0 4px; border-radius: 3px; }
.jshot-ba-stage { text-align: center; }
#jshot-ba-canvas { border: 1px solid var(--border); border-radius: 10px; max-width: 100%; touch-action: none; cursor: grab; background: #fff; }
.jshot-ba-stage .hint label { margin-left: 10px; }
.jshot-ba-stage input[type="range"] { vertical-align: middle; width: 110px; }
.jshot-ba-actions { display: flex; gap: 8px; align-items: center; margin-top: 10px; flex-wrap: wrap; }
.jshot-office-card { width: 220px; min-width: 220px; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: #fff; }
.jshot-office-photo { display: block; width: 100%; height: 112px; border: 0; padding: 0; background: #e8eaed; cursor: pointer; }
.jshot-office-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.jshot-office-card-body { padding: 9px 10px 10px; }
.jshot-office-company { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--text); font-weight: 700; font-size: .83rem; }
.jshot-office-meta { margin-top: 3px; color: var(--text-muted); font-size: .74rem; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.jshot-office-actions { display: flex; gap: 6px; margin-top: 8px; }
.jshot-office-actions button { flex: 1; border: 1px solid var(--border); border-radius: 6px; background: #fff; color: var(--text); padding: 6px 7px; font: inherit; font-size: .74rem; cursor: pointer; }
.jshot-office-actions .reviewed { border-color: #83c58a; color: #23752e; }
.jshot-office-empty, .jshot-office-loading { color: var(--text-muted); font-size: .84rem; padding: 4px 0; }
/* margin-top:0 — the map card is the Map pane's only child now, and the pane
   already supplies the top padding the old fold used to. */
.jshot-map-card { overflow: hidden; border: 1px solid var(--border); border-radius: 10px; background: #fff; }
.jshot-map-card > .jshot-pane-block-head { padding: 11px 14px 0; }
.jshot-map-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 12px; border-bottom: 1px solid var(--border); }
.jshot-map-head > div:first-child { display: flex; min-width: 0; flex-direction: column; gap: 2px; }
.jshot-map-head strong { color: var(--text); font-size: .9rem; }
.jshot-map-head span { color: var(--text-muted); font-size: .75rem; }
.jshot-map-head button { border: 1px solid var(--border); border-radius: 6px; background: #fff; color: var(--text); padding: 6px 9px; font: inherit; font-size: .75rem; cursor: pointer; white-space: nowrap; }
.jshot-map-controls { display: flex; align-items: center; gap: 7px; }
/* min-width:0 is the actual fix — a <select> flex item defaults to
   min-width:auto, which resolves to its widest OPTION's intrinsic text
   width (job company names can run 80+ characters) and won't shrink
   below that no matter what `width` says, pushing the row wider than the
   viewport. Truncate the closed-box display with ellipsis so a long name
   doesn't just get abruptly clipped by overflow:hidden. */
.jshot-map-controls select {
  width: min(280px, 34vw); max-width: 100%; min-width: 0;
  border: 1px solid var(--border); border-radius: 6px; background: #fff; color: var(--text);
  padding: 6px 26px 6px 8px; font: inherit; font-size: .75rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* isolation + z-index:0 trap Leaflet's internal panes/controls (which go up to
   z-index 1000) inside the map's own stacking context, so an embedded map can
   never paint on top of a modal (our .modal overlay is only z-index 100). */
.jshot-photo-map { width: 100%; height: 360px; background: #e9eef3; position: relative; z-index: 0; isolation: isolate; }
.jshot-map-empty { padding: 28px 18px; color: var(--text-muted); text-align: center; font-size: .84rem; }
.jshot-map-empty.hidden { display: none; }
#jshot-map-expand { font-size: .95rem; line-height: 1; padding: 5px 8px; }
/* Enlarge: the card itself becomes a fullscreen flex column (header stays
   on top, map fills the rest) instead of moving the live Leaflet instance
   to a different container — Leaflet doesn't like being reparented, and
   this way invalidateSize() is the only thing the map needs to know. */
.jshot-map-card.is-expanded {
  position: fixed; inset: 0; z-index: 9500; margin: 0; border: none; border-radius: 0;
  display: flex; flex-direction: column;
}
.jshot-map-card.is-expanded .jshot-photo-map { flex: 1; height: auto; min-height: 0; }
.jshot-map-card.is-expanded .jshot-map-empty { flex: 1; }
.jshot-map-popup { width: 240px; max-height: 280px; overflow-y: auto; }
.jshot-map-popup-title { margin-bottom: 7px; font-weight: 700; font-size: .83rem; }
.jshot-map-popup-photo { display: grid; grid-template-columns: 58px 1fr; gap: 8px; align-items: center; padding: 6px 0; border-top: 1px solid #e5e7eb; color: #1f2937; text-decoration: none; }
.jshot-map-popup-photo img { width: 58px; height: 48px; border-radius: 5px; object-fit: cover; }
.jshot-map-popup-photo strong, .jshot-map-popup-photo span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jshot-map-popup-photo strong { font-size: .75rem; }
.jshot-map-popup-photo span { margin-top: 3px; color: #64748b; font-size: .68rem; }
.jshot-map-popup-job { margin-bottom: 7px; }
.jshot-map-popup-job strong, .jshot-map-popup-job span { display: block; }
.jshot-map-popup-job strong { color: #1e293b; font-size: .82rem; }
.jshot-map-popup-job span { margin-top: 2px; color: #64748b; font-size: .7rem; }
.jshot-map-open { width: 100%; margin: 8px 0 2px; border: 0; border-radius: 6px; background: #16C7C9; color: #fff; padding: 7px 9px; font: inherit; font-size: .74rem; font-weight: 700; cursor: pointer; }
.jshot-map-marker { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border: 3px solid #fff; border-radius: 50% 50% 50% 0; transform: rotate(-45deg); background: #e3212d; color: #fff; box-shadow: 0 2px 6px rgba(0,0,0,.3); font-size: 11px; font-weight: 800; }
.jshot-map-marker span { transform: rotate(45deg); }
@media (max-width: 720px) {
  .jshot-shell-head { padding: 14px 16px 12px; }
  .jshot-office-stats { grid-template-columns: repeat(2, 1fr); padding: 0 16px; }
  .jshot-tabs { margin: 12px 16px 0; max-width: calc(100% - 32px); }
  .jshot-pane { padding: 12px 16px 16px; }
  .jshot-photo-map { height: 300px; }
  .jshot-map-head { align-items: stretch; flex-direction: column; }
  .jshot-map-controls select { width: 100%; max-width: 100%; min-width: 0; flex: 1; }
}
/* .jshot-header / .jshot-header-text retired — .jshot-shell-head replaced
   the second title row (see the top of this block). */
.jshot-title { margin: 0; font-size: 1.25rem; font-weight: 700; color: var(--text); }
.jshot-subtitle { font-size: 0.85rem; color: var(--text-muted); }
.jshot-search { flex: 1; min-width: 0; max-width: 320px; border: 1px solid var(--border); border-radius: 6px; padding: 7px 12px; font-size: 0.9rem; background: #fff; color: var(--text); }
.jshot-search:focus { outline: none; border-color: #16C7C9; box-shadow: 0 0 0 2px rgba(22,199,201,0.15); }
/* min-width:0 is the real fix (see .jshot-map-controls select above) —
   without it this flex item won't shrink below its widest OPTION's
   intrinsic text width (job company names run 80+ characters), which
   pushes its row (.jshot-proj-filters) wider than the viewport. */
.jshot-alljobs {
  max-width: 220px; min-width: 0;
  border: 1px solid var(--border); border-radius: 6px; padding: 7px 8px; font-size: 0.88rem;
  background: #fff; color: var(--text); cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.jshot-header-actions { display: flex; align-items: center; gap: 10px; }
.jshot-refresh-btn { background: none; border: 1px solid var(--border); border-radius: 6px; width: 32px; height: 32px; font-size: 1rem; cursor: pointer; color: var(--text-muted); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.jshot-refresh-btn:hover { background: var(--hover-bg, #f1f3f4); color: var(--text); }
/* Year-end photo export. Lives on the Admin dashboard's Admin tools card —
   the .jshot-* prefix is historical (it used to sit on the JobShot page). */
.admin-archive-row { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border-soft, #eef0f3); }
.admin-archive-row label { display: block; margin-bottom: 6px; color: var(--text-muted); font-size: .8rem; }
.jshot-archive-wrap { display: flex; align-items: center; gap: 6px; }
.jshot-archive-year { border: 1px solid var(--border); border-radius: 6px; padding: 5px 8px; font-size: 0.85rem; background: #fff; color: var(--text); cursor: pointer; }
.jshot-archive-btn { background: #16C7C9; color: #fff; border: none; border-radius: 6px; padding: 6px 12px; font-size: 0.85rem; cursor: pointer; white-space: nowrap; }
.jshot-archive-btn:hover { background: #0E9799; }
/* Table header row mirrors CompanyCam's project-list columns */
/* JOBSHOT-CARD: shared visual language with .jcard / .jcard.cover in
   public/jobshot.html (the field app) — radius 14, a 172px cover box, the same
   scrim, 15px/600 title (.94rem), 12px/400 sub (.75rem), and the same count
   chip. A project card must read the same in both apps; change one only by
   changing both. See .planning/phases/jobshot-6-dashboard/PLAN.md, D-8.
   Colour and type unit stay theme-local: this app is white and rem-based, the
   field app is dark and px-based. */
.jshot-grid {
  flex: 1; overflow-y: auto; display: grid; align-content: start;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 10px; padding: 0 0 4px;   /* .jshot-pane owns the gutter */
}
/* COMPANY-FIRST: when the list is grouped by company the grid stops being the
   card grid itself and becomes a column of company blocks — each block holds
   its own card grid, so cards keep the identical auto-fill behaviour they had
   when the list was flat. The class is only added by the grouped renderer, so
   any other consumer of .jshot-grid is untouched. */
.jshot-grid.grouped {
  display: flex; flex-direction: column; gap: 14px;
}
.jshot-co-cards {
  display: grid; align-content: start;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 10px;
}
.jshot-co-head {
  width: 100%; display: flex; align-items: center; gap: 8px;
  background: none; border: 0; cursor: pointer; text-align: left;
  padding: 2px 2px 8px; color: var(--text);
  border-bottom: 1px solid var(--border); margin-bottom: 10px;
}
.jshot-co-head:hover .jshot-co-name { color: #1d4ed8; }
.jshot-co-caret { display: flex; color: var(--text-muted); transition: transform .12s; }
.jshot-co-head[aria-expanded="true"] .jshot-co-caret { transform: rotate(90deg); }
.jshot-co-name {
  font-size: .95rem; font-weight: 650; letter-spacing: -.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Pushed right and kept quiet: the company is the heading, the tallies are
   reference. margin-left:auto rather than flex:1 on the name so a long company
   name truncates instead of shoving the count off the edge. */
.jshot-co-meta {
  margin-left: auto; flex: none; font-size: .75rem; color: var(--text-muted); white-space: nowrap;
}
.jshot-card {
  position: relative; background: #fff; border: 1px solid var(--border);
  border-radius: 14px; overflow: hidden; cursor: pointer;
  transition: box-shadow .12s, border-color .12s;
}
.jshot-card:hover { border-color: #9ebce8; box-shadow: 0 2px 10px rgba(29,78,216,.12); }
.jshot-card-cover { position: relative; height: 172px; background: #e8eaed; display: flex; align-items: center; justify-content: center; }
.jshot-card-cover img { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.jshot-card-ph { position: relative; z-index: 0; font-size: 26px; opacity: .35; }
/* The cover <img> is PREPENDED (it has to sit under the scrim and the overlay,
   which live in this same box), so the placeholder would otherwise paint on top
   of the photo. Hidden once the image has actually DECODED, not merely been
   created: with loading="lazy" an off-screen card would otherwise show a bare
   grey box until it scrolled into view. onerror drops the class again. */
.jshot-card-cover.has-cover .jshot-card-ph { display: none; }
.jshot-card-scrim { position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(2,6,23,0) 42%, rgba(2,6,23,.86) 100%); }
.jshot-card-over { position: absolute; z-index: 2; left: 12px; right: 12px; bottom: 10px; }
.jshot-card-co { font-size: .94rem; font-weight: 600; color: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jshot-card-sub { font-size: .75rem; font-weight: 400; color: #cbd5e1; margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jshot-card-badge { position: absolute; z-index: 2; top: 10px; right: 10px; font-size: .69rem; font-weight: 700;
  letter-spacing: .03em; text-transform: uppercase; background: rgba(15,23,42,.85); color: #fff; border-radius: 999px; padding: 3px 8px; }
.jshot-card-foot { display: flex; justify-content: space-between; gap: 8px; padding: 8px 12px;
  font-size: .72rem; color: var(--text-muted); border-top: 1px solid var(--border); }
.jshot-card-foot span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Status pill — scoped on purpose. The class is built from a raw job.status, so
   without these four rules it inherits the calendar's global .status-* palette
   (styles.css:2267+, including line-through on cancelled). Emitted by the
   project card (app.js) and by project detail's identity line. */
.jshot-status-badge { display: inline-block; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; padding: 2px 8px; border-radius: 20px; align-self: flex-start; }
.jshot-status-badge.status-in_production { background: #c5e1ff; color: #0E9799; }
.jshot-status-badge.status-ready_for_install { background: #d4f1d0; color: #1b5e20; }
.jshot-status-badge.status-completed { background: #dcfce7; color: #166534; }
.jshot-empty { grid-column: 1 / -1; color: var(--text-muted); font-size: 0.93rem; padding: 40px 24px; text-align: center; }



/* Project detail — CompanyCam-style photo page for one job */
/* Defensive: the list/detail elements set their own display (flex/grid),
   which would otherwise beat the UA's [hidden]{display:none} default. */
#tab-jobshot [hidden] { display: none !important; }
.jshot-detail { flex: 1; overflow-y: auto; display: flex; flex-direction: column; min-height: 0; }
.jshot-detail-head {
  display: flex; align-items: flex-start; gap: 16px;
  padding: 16px 24px; border-bottom: 1px solid var(--border); flex-shrink: 0;
  flex-wrap: wrap;
}
.jshot-back-btn { background: none; border: 1px solid var(--border); border-radius: 8px; padding: 8px 14px; font-size: 0.88rem; cursor: pointer; color: var(--text); white-space: nowrap; }
.jshot-back-btn:hover { background: var(--hover-bg, #f1f3f4); }
.jshot-detail-info { flex: 1; min-width: 200px; }
.jshot-detail-info h2 { margin: 0 0 6px; font-size: 1.3rem; line-height: 1.25; }
.jshot-detail-sub { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; min-width: 0; font-size: 0.85rem; color: var(--text-muted); }
/* The address is the one variable-length item on the identity line — let it
   ellipsize instead of pushing status/invoice/install/crew onto a second row.
   Same treatment .jshot-find-meta and .jshot-cs-meta already use. */
.jshot-detail-sub #jshot-d-addr { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jshot-d-addr { color: #16C7C9; text-decoration: none; }
.jshot-d-addr:hover { text-decoration: underline; }
.jshot-d-jobmeta { display: flex; gap: 7px 14px; flex-wrap: wrap; margin-top: 8px; color: var(--text-muted); font-size: .78rem; }
.jshot-d-jobmeta span { white-space: nowrap; }
/* OFFICE-CHECKLIST: the crew's six onsite steps, read-only. Done chips are
   green with who/when; pending chips stay muted outlines. */
.jshot-d-checklist { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.jshot-ck-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: .72rem;
  color: var(--text-muted);
  background: #fff;
  white-space: nowrap;
}
.jshot-ck-chip.done { background: #f0faf4; border-color: #bfe6cd; color: #1c7c46; }
.jshot-ck-chip small { color: inherit; opacity: .75; font-size: .92em; }
.jshot-detail-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.jshot-d-btn { background: #fff; border: 1px solid var(--border); border-radius: 8px; padding: 8px 14px; font-size: 0.85rem; cursor: pointer; color: var(--text); white-space: nowrap; }
.jshot-d-btn:hover { background: var(--hover-bg, #f1f3f4); }
.jshot-d-btn.primary { background: #16C7C9; border-color: #16C7C9; color: #fff; }
.jshot-d-btn.primary:hover { background: #0E9799; }
.jshot-d-btn.active { background: #16C7C9; border-color: #16C7C9; color: #fff; }
/* ── Project detail sub-tabs and panes ────────────────────────────────────
      .jshot-d-tabs is a MODIFIER on Phase 1's .jshot-tabs, one step smaller,
      so a user can tell the page level from the project level. The base
      rules are shared and must not be edited here. */
/* max-width is set explicitly rather than inherited: .jshot-tabs' own 720px
   media rule caps it at calc(100% - 32px), which wouldn't match this element's
   24px margins in the 701-720px window. */
.jshot-d-tabs { height: 34px; margin: 12px 24px 0; max-width: calc(100% - 48px); }
.jshot-d-tabs .jshot-tab-btn { font-size: 12px; padding: 0 12px; }
/* No overflow-y and no height: .jshot-detail is already the scroll container,
   and a pane-level scroller would nest one inside it. */
.jshot-d-pane { display: block; }
.jshot-d-pane-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; padding: 14px 24px 0; font-size: .9rem; }
.jshot-d-pane-head strong { color: var(--text); }
.jshot-d-toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 12px 24px 0; }
/* Reads as a state, not another button row — the accent tint already used by
   .jshot-d-filter.active below. Deliberately not sticky. */
.jshot-d-bulkbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 10px 24px 0; padding: 8px 12px; border: 1px solid #16C7C9; border-radius: 10px; background: #e8f0fe; }
.jshot-d-bulk-count { font-size: .82rem; font-weight: 700; color: #0E9799; }
.jshot-d-activity-list { display: block; padding: 8px 24px 18px; }
#jshot-d-pane-sharing #jshot-share-existing { padding: 8px 24px 18px; }
/* Wide enough that "Copy live timeline link" doesn't wrap. */
#jshot-d-more-menu { min-width: 220px; }
#jshot-d-more-menu button, #jshot-d-more-menu a { white-space: nowrap; }
@media (max-width: 700px) {
  /* Let the three header controls and the bulk bar wrap rather than squeeze.
     .jshot-d-tabs inherits .jshot-tabs' horizontal scroll, so the three
     sub-tabs can never stack. */
  .jshot-detail-actions { width: 100%; }
  .jshot-detail-actions .jshot-d-btn, .jshot-d-more-wrap { flex: 1 1 auto; }
  .jshot-d-tabs { margin: 12px 16px 0; max-width: calc(100% - 32px); }
  .jshot-d-pane-head, .jshot-d-toolbar { padding-left: 16px; padding-right: 16px; }
  .jshot-d-bulkbar { margin-left: 16px; margin-right: 16px; }
  .jshot-d-activity-list, #jshot-d-pane-sharing #jshot-share-existing { padding-left: 16px; padding-right: 16px; }
}
.jshot-d-filters { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; padding: 10px 24px; border-bottom: 1px solid var(--border); background: #fafbfc; }
.jshot-d-filter-label { font-size: 0.76rem; color: var(--text-muted); font-weight: 700; margin-right: 2px; }
.jshot-d-filter { appearance: none; border: 1px solid var(--border); background: #fff; color: var(--text); border-radius: 999px; padding: 5px 10px; font-size: 0.78rem; cursor: pointer; }
.jshot-d-filter:hover { border-color: #16C7C9; color: #0E9799; }
.jshot-d-filter.active { background: #e8f0fe; border-color: #16C7C9; color: #0E9799; font-weight: 700; }
.jshot-d-filter.user { background: #fff; }
/* Tag filter chips read "Before (3)" like the field app's chips. Scoped to
   [data-tag-filter] on purpose: this class is shared with the person filters,
   and a person's name must not be re-cased. */
.jshot-d-filter[data-tag-filter] { text-transform: capitalize; }
.jshot-d-grid {
  padding: 18px 24px; display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; align-content: start;
}
.jshot-d-date { grid-column: 1 / -1; font-size: 0.8rem; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; color: var(--text-muted); margin: 8px 0 -4px; padding-top: 10px; border-top: 1px solid var(--border); }
.jshot-d-date:first-child { margin-top: 0; padding-top: 0; border-top: none; }
.jshot-d-tile { position: relative; border-radius: 10px; overflow: hidden; background: #e8eaed; cursor: pointer; border: 1px solid var(--border); }
.jshot-d-tile img { width: 100%; height: 170px; object-fit: cover; display: block; }
.jshot-d-tile .jshot-d-meta { padding: 6px 10px; font-size: 0.75rem; color: var(--text-muted); background: #fff; display: flex; justify-content: space-between; gap: 6px; }
.jshot-d-tile.sel { outline: 3px solid #16C7C9; outline-offset: -3px; }
.jshot-d-tile.sel::after { content: "✓"; position: absolute; top: 8px; right: 8px; width: 24px; height: 24px; border-radius: 50%; background: #16C7C9; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 14px; }
.jshot-d-avatar { position: absolute; top: 8px; left: 8px; width: 26px; height: 26px; border-radius: 50%; background: rgba(15,23,42,0.8); color: #fff; font-size: 11px; font-weight: 700; display: flex; align-items: center; justify-content: center; }
/* JOBSHOT-TAGS: photo-tag palette. TWIN of .tileBadge.tag-* in
   public/jobshot.html (~line 111) — the field app is the source of truth,
   because that is where tags are set and its palette already agrees across the
   tile badge, the filter chip and the capture buttons. A tag must look the
   same in both apps (see .planning/phases/jobshot-5-workflow-clarity/PLAN.md,
   D-9/D-11), so change one only by changing both.
   before #0891b2 · after #16a34a · damage #dc2626 · materials #7c3aed ·
   issue #f59e0b (dark text) · progress #0284c7
   Modifiers stay compound (.jshot-d-tag.tag-x), never a bare .tag-x (D-10). */
.jshot-d-tag { position: absolute; top: 8px; right: 8px; border-radius: 999px; padding: 3px 7px; font-size: 0.68rem; text-transform: uppercase; font-weight: 700; background: rgba(15,23,42,0.86); color: #fff; }
.jshot-d-tag.tag-before { background: #0891b2; }
.jshot-d-tag.tag-after { background: #16a34a; }
.jshot-d-tag.tag-damage { background: #dc2626; }
.jshot-d-tag.tag-materials { background: #7c3aed; }
.jshot-d-tag.tag-issue { background: #f59e0b; color: #111827; }
.jshot-d-tag.tag-progress { background: #0284c7; }

/* JobShot review lightbox: the office can describe, classify, download, or
   remove a photo without sending someone back to the phone. */
#jshot-lb { align-items: center; justify-content: center; padding: 32px 20px 184px; box-sizing: border-box; }
#jshot-lb .photos-lb-img { max-height: calc(100vh - 250px); }
.jshot-lb-panel { position: fixed; z-index: 2; bottom: 0; left: 50%; transform: translateX(-50%); width: min(720px, calc(100vw - 24px)); background: #fff; color: var(--text); border-radius: 12px 12px 0 0; padding: 12px 16px 16px; box-shadow: 0 -8px 30px rgba(0,0,0,.32); }
.jshot-lb-meta { font-size: .78rem; color: var(--text-muted); margin-bottom: 9px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jshot-lb-edit { display: flex; gap: 8px; }
.jshot-lb-edit input { min-width: 0; flex: 1; border: 1px solid var(--border); border-radius: 7px; padding: 8px 10px; font: inherit; }
.jshot-lb-edit button, .jshot-lb-actions button, .jshot-lb-actions a { border: 1px solid var(--border); border-radius: 7px; background: #fff; color: var(--text); padding: 8px 10px; font: inherit; font-size: .82rem; cursor: pointer; text-decoration: none; }
.jshot-lb-edit button { background: #16C7C9; border-color: #16C7C9; color: #fff; }
.jshot-lb-tags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.jshot-lb-tags button { border: 1px solid var(--border); border-radius: 999px; background: #fff; color: var(--text-muted); padding: 4px 9px; cursor: pointer; font-size: .76rem; }
.jshot-lb-tags button.active { background: #e8f0fe; border-color: #16C7C9; color: #0E9799; font-weight: 700; }
.jshot-lb-actions { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.jshot-lb-actions .danger { color: #b91c1c; border-color: #fecaca; margin-left: auto; }
@media (max-width: 640px) { .jshot-lb-actions { flex-wrap: wrap; } #jshot-lb { padding-bottom: 230px; } #jshot-lb .photos-lb-img { max-height: calc(100vh - 295px); } }

@media (max-width: 900px) {
  /* Shell head stacks on phones: title + actions on the first row, then the
     search gets a full-width row instead of all three fighting for one line. */
  .jshot-shell-head { flex-wrap: wrap; gap: 10px; }
  .jshot-title { order: 1; flex: 1; min-width: 0; white-space: nowrap; }
  .jshot-header-actions { order: 2; }
  /* max-width:none here used to remove the only thing capping these —
     on a phone that let .jshot-alljobs grow to its widest OPTION's
     intrinsic text width (job company names run 80+ characters) and
     push the whole row wider than the viewport. min-width:0 lets the
     flex item actually shrink; max-width:100% keeps it inside its row. */
  .jshot-search { order: 3; flex: 1 1 100%; max-width: 100%; min-width: 0; }
  .jshot-alljobs { flex: 1 1 100%; max-width: 100%; min-width: 0; padding: 10px 8px; }
}

/* ============================================================
   MOBILE READABILITY (≤720px) — the app was designed desktop-dense;
   on a phone the 10–12px text is hard to read. This block bumps the
   most-read surfaces and, critically, keeps every form control at
   16px so iOS stops auto-zooming the page on focus.
   ============================================================ */
@media (max-width: 720px) {
  /* iOS zooms the viewport when a focused control is under 16px. */
  input, select, textarea { font-size: 16px !important; }

  /* Dashboard */
  .metric-label { font-size: 13px; }
  .metric-sub { font-size: 13px; }
  .metric-value { font-size: 26px; }
  .dashboard-list .dl-item { font-size: 14px; padding: 10px 10px; }
  .dashboard-list .dl-meta, .dashboard-list .dl-date { font-size: 13px; }
  .dashboard-list .empty { font-size: 14px; }
  .ai-briefing-line, .ai-briefing-empty { font-size: 14px; line-height: 1.5; }
  .wir-stat-label, .wir-stat-meta { font-size: 13px; }

  /* Calendar chips — 10px is unreadable on glass */
  .cal-event { font-size: 12px; padding: 3px 6px; line-height: 1.3; }
  /* Day-view modal: phone-sized tap targets so events are easy to hit */
  .day-list .cal-event { font-size: 15px; padding: 12px 12px; }
  .day-actions button { padding: 12px; font-size: 15px; }

  /* Pipeline cards */
  .kanban-card { font-size: 14px; }
  .kanban-card .kc-meta, .kanban-card small { font-size: 13px; }
  .kanban-col-title { font-size: 14px; }

  /* Tables (Jobs, Weekly Stats, Time Off) */
  table td, table th { font-size: 14px; }

  /* Job form / modals */
  .modal-content label { font-size: 14px; }
  .form-section-header { font-size: 15px; }
  .attachments-hint, .hint-inline { font-size: 13px; }
  .attachment-name { font-size: 12px; }
  .modal-hero-sub { font-size: 14px; }

  /* Sidebar drawer + topbar */
  .sidebar-label { font-size: 15px; }
  .topbar-manage-btn, .tab-dropdown-btn { font-size: 14px; }

  /* Toasts & pending sidebar */
  .toast { font-size: 14px; }
  .pending-sidebar { font-size: 14px; }
}

/* ====================================================================
   PRODUCT COHESION PASS — July 2026
   One visual language for the shell, navigation, dashboard and calendar.
   This block intentionally sits last while the older screens are migrated
   onto the shared token system over time.
   ==================================================================== */
:root {
  --brand-navy: #172033;
  --brand-navy-soft: #26344d;
  --surface-muted: #f5f7fb;
  --surface-tint: #f8fafc;
  --focus-ring: rgba(22,199,201, .2);
  --shadow-card: 0 1px 2px rgba(15, 23, 42, .04), 0 8px 24px rgba(15, 23, 42, .05);
  --shadow-float: 0 16px 40px rgba(15, 23, 42, .14);
}

body { line-height: 1.45; }
button, input, select, textarea { transition: border-color .15s ease, background-color .15s ease, color .15s ease, box-shadow .15s ease; }
button:focus-visible,
[role="button"]:focus-visible,
[role="searchbox"]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}

.app-icon-sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
  pointer-events: none;
}
.sidebar-icon,
.button-icon,
.inline-icon,
.metric-card-icon svg,
.wir-stat-icon svg {
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.button-icon { width: 17px; height: 17px; flex: 0 0 auto; }
.inline-icon { width: 14px; height: 14px; }
.button-caret { margin-left: 1px; color: currentColor; font-size: 13px; opacity: .72; }

/* App shell */
.sidebar {
  width: 224px;
  border-right-color: #dce3ec;
  box-shadow: 1px 0 0 rgba(15, 23, 42, .02);
}
.sidebar-brand {
  min-height: 72px;
  justify-content: flex-start;
  gap: 11px;
  padding: 14px 16px;
  border-bottom-color: #edf1f6;
}
.sidebar-brand .brand-logo {
  width: 62px;
  height: auto;
  flex: 0 0 auto;
}
.sidebar-brand-copy {
  display: flex;
  min-width: 0;
  flex-direction: column;
  line-height: 1.15;
}
.sidebar-brand-copy strong {
  color: var(--text-heading);
  font-size: 13px;
  font-weight: 750;
  white-space: nowrap;
}
.sidebar-brand-copy span {
  margin-top: 4px;
  color: var(--text-muted);
  font-size: 10px;
  white-space: nowrap;
}
.sidebar-nav { gap: 3px; padding: 10px; }
.sidebar-section-label {
  margin: 13px 10px 5px;
  padding: 12px 2px 0;
  color: #8b98a9;
  font-size: 10px;
  letter-spacing: .12em;
}
.sidebar-workspace-label { margin-top: 0; padding-top: 3px; border-top: 0; }
.sidebar-item {
  position: relative;
  min-height: 42px;
  gap: 11px;
  padding: 10px 11px;
  border-radius: 10px;
  color: #455468;
  font-size: 13px;
  font-weight: 550;
}
.sidebar-item:hover { background: #f4f6fa; color: var(--text-heading); }
.sidebar-item.active {
  background: linear-gradient(90deg, rgba(225, 27, 34, .11), rgba(225, 27, 34, .055));
  color: #c9151c;
  font-weight: 700;
}
.sidebar-item.active::before {
  content: '';
  position: absolute;
  left: -10px;
  top: 9px;
  bottom: 9px;
  width: 3px;
  border-radius: 0 4px 4px 0;
  background: var(--brand-red);
}
.sidebar-icon { width: 18px; height: 18px; flex: 0 0 18px; stroke-width: 1.9; }
.sidebar-tenant {
  position: relative;
  padding: 13px 16px 14px 34px;
  border-top-color: #edf1f6;
  background: #fbfcfe;
}
.sidebar-tenant::before {
  content: '';
  position: absolute;
  left: 17px;
  top: 20px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--semantic-green);
  box-shadow: 0 0 0 3px rgba(16, 185, 129, .12);
}
.sidebar-tenant-name { color: var(--text-heading); font-size: 12px; }
.sidebar-tenant-loc { margin: 2px 0 0; font-size: 10px; }

.topbar {
  min-height: 64px;
  padding: 10px 20px;
  border-bottom-color: rgba(203, 213, 225, .75);
  background: rgba(255, 255, 255, .94);
  box-shadow: 0 1px 0 rgba(15, 23, 42, .025);
  backdrop-filter: blur(12px);
}
.topbar-nav { gap: 14px; }
.topbar-actions { gap: 8px; }
.tab-dropdown-btn,
.topbar-manage-btn,
.ai-insights-btn,
.refresh-data-btn,
.chat-btn,
.notif-btn {
  min-height: 38px;
  border: 1px solid #d8e0ea;
  border-radius: 9px;
  background: #fff;
  color: #42526a;
  box-shadow: 0 1px 1px rgba(15, 23, 42, .025);
}
.topbar-manage-btn,
.ai-insights-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 7px 11px;
  font-size: 12px;
  font-weight: 650;
  white-space: nowrap;
}
.refresh-data-btn,
.chat-btn,
.notif-btn { display: inline-flex; width: 38px; height: 38px; padding: 0; align-items: center; justify-content: center; }
.refresh-data-btn:hover,
.chat-btn:hover,
.notif-btn:hover,
.topbar-manage-btn:hover,
.ai-insights-btn:hover,
.tab-dropdown-btn:hover { border-color: #b8c4d2; background: #f6f8fb; color: var(--text-heading); }
.topbar-new-btn {
  min-height: 40px;
  gap: 7px;
  border-radius: 9px;
  padding: 8px 14px;
  font-size: 12px;
  font-weight: 750;
  box-shadow: 0 5px 14px rgba(225, 27, 34, .18);
}
.topbar-new-btn:hover { box-shadow: 0 7px 18px rgba(176, 21, 27, .22); }
.refresh-data-btn.spinning { animation: none; }
.refresh-data-btn.spinning .button-icon { animation: refresh-spin .8s linear infinite; }
.topbar-user { gap: 8px; margin-left: 3px; padding-left: 12px; }
.topbar-user-avatar {
  width: 36px;
  height: 36px;
  border: 2px solid #fff;
  background: var(--brand-navy);
  box-shadow: 0 0 0 1px #d8e0ea;
  font-size: 12px;
}
.topbar-user-name .current-user { font-size: 12px; }
.topbar-user-name .topbar-signout { font-size: 10px; }
.dropdown-menu {
  margin-top: 4px;
  border-color: #dce3ec;
  border-radius: 11px;
  box-shadow: var(--shadow-float);
  padding: 6px;
}
.dropdown-menu button { border-radius: 7px; color: #334155; font-size: 13px; }

/* Main content and page hierarchy */
main { padding: 28px 32px 40px; }
main > .tab-panel { width: 100%; max-width: 1600px; margin: 0 auto; }
.page-heading {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  margin: 0 0 22px;
}
.page-heading-copy { min-width: 0; }
.page-eyebrow {
  display: block;
  margin-bottom: 5px;
  color: var(--brand-red);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.page-heading h1 {
  margin: 0;
  color: var(--text-heading);
  font-size: 26px;
  font-weight: 760;
  letter-spacing: -.025em;
  line-height: 1.15;
}
.page-heading p { margin: 6px 0 0; color: var(--text-muted); font-size: 13px; }
.page-heading-status {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
  padding: 7px 11px;
  border: 1px solid #dce3ec;
  border-radius: var(--r-pill);
  background: #fff;
  color: var(--text-muted);
  font-size: 11px;
  white-space: nowrap;
}
.page-status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--semantic-green); box-shadow: 0 0 0 3px rgba(16,185,129,.11); }
.last-sync-line { margin: 0; padding-left: 8px; border-left: 1px solid #e2e8f0; text-align: left; font-size: 11px; }
.page-heading-status .last-sync-line { display: none; }
.page-heading-compact { margin-bottom: 18px; }
.page-heading-compact h1 { font-size: 24px; }

.corebridge-sync-alert {
  margin: 14px 32px 0;
  padding: 12px 15px;
  border-radius: 11px;
  box-shadow: var(--shadow-sm);
}
.corebridge-sync-now { min-height: 34px; border-radius: 8px; }

/* Dashboard */
.dashboard-metrics { gap: 14px; margin-bottom: 18px; }
.metric-card {
  --metric-color: var(--action-blue);
  min-height: 138px;
  padding: 17px 18px;
  border: 1px solid #dfe6ef;
  border-top: 1px solid #dfe6ef;
  border-radius: 14px;
  box-shadow: var(--shadow-card);
}
.metric-card:hover { box-shadow: var(--shadow-card); }
.metric-card.metric-installs { --metric-color: #16C7C9; border-top-color: #dfe6ef; }
.metric-card.metric-in-prod { --metric-color: #475569; border-top-color: #dfe6ef; }
.metric-card.metric-scheduled { --metric-color: #d97706; border-top-color: #dfe6ef; }
.metric-card.metric-completed { --metric-color: #7c3aed; border-top-color: #dfe6ef; }
.metric-card-head { display: flex; align-items: center; gap: 9px; margin-bottom: 13px; }
.metric-card-icon {
  display: inline-flex;
  width: 30px;
  height: 30px;
  align-items: center;
  justify-content: center;
  border-radius: 9px;
  background: color-mix(in srgb, var(--metric-color) 11%, white);
  color: var(--metric-color);
}
.metric-card-icon svg { width: 16px; height: 16px; }
.metric-card .metric-label { margin: 0; color: #657386; font-size: 10px; }
.metric-card .metric-value { color: var(--text-heading); font-size: 28px; letter-spacing: -.02em; }
.metric-card .metric-sub { color: #718096; font-size: 11px; }
.week-in-review,
.dashboard-list-card,
.mini-cal-card,
.rework-card,
.dashboard-alert-card {
  border-color: #dfe6ef;
  border-radius: 14px;
  box-shadow: var(--shadow-card);
}
.week-in-review { padding: 19px 20px; margin-bottom: 18px; }
.wir-title { font-size: 17px; letter-spacing: -.01em; }
.wir-date-chip { padding: 5px 10px; background: #fff1f2; font-size: 11px; }
.wir-stat { border-color: #e2e8f0; border-radius: 12px; background: #f8fafc; }
.wir-stat::before { height: 2px; }
.wir-stat-icon {
  display: inline-flex;
  width: 25px;
  height: 25px;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: #eaf2ff;
  color: #12B6B8;
}
#wir-completed .wir-stat-icon { background: #e9f9f2; color: #078455; }
.wir-stat-icon svg { width: 14px; height: 14px; }
.dashboard-alert-card,
.rework-card { border-left-width: 3px; }
.mini-cal-card { padding: 17px 18px; }
.dashboard-list-card { padding: 18px 19px; }
.dashboard-list .dl-item { border: 1px solid transparent; }
.dashboard-list .dl-item:hover { border-color: #e5eaf1; background: #f7f9fc; }

/* Calendar */
.calendar-page-heading { margin-bottom: 17px; }
.cal-layout { gap: 20px; }
.cal-controls,
.cal-toolbar {
  border: 1px solid #dfe6ef;
  background: #fff;
  box-shadow: var(--shadow-sm);
}
.cal-controls {
  min-height: 58px;
  margin-bottom: 10px;
  padding: 10px 12px;
  border-radius: 12px;
}
.cal-controls h2 { color: var(--text-heading); font-size: 17px; font-weight: 720; letter-spacing: -.01em; }
.cal-controls > button { min-height: 36px; border-color: #d9e1ea; border-radius: 8px; }
.cal-controls #cal-prev,
.cal-controls #cal-next { width: 36px; padding: 0; font-size: 19px; }
.cal-views { margin-left: auto; border-color: #d9e1ea; border-radius: 8px; background: #f6f8fb; }
.cal-view-btn { min-height: 34px; border-right-color: #d9e1ea; background: transparent; color: #5a687a; font-size: 12px; font-weight: 650; }
.cal-view-btn.active { background: var(--action-blue); color: #fff; }
.cal-toolbar {
  gap: 8px;
  margin-bottom: 14px;
  padding: 11px 12px;
  border-radius: 12px;
}
#cal-search { min-height: 36px; border-color: #d9e1ea; border-radius: 8px; background: #f8fafc; }
.cal-mode-toggle { border-color: #d9e1ea; border-radius: 8px; background: #f6f8fb; }
.cal-mode-btn { min-height: 34px; background: transparent; color: #5d697a; }
.cal-mode-btn.active { background: var(--action-blue); }
.cal-toolbar-label { margin: 0 1px 0 5px; font-size: 10px; color: #8491a3; }
.toggle {
  gap: 5px;
  padding: 5px 7px;
  border-radius: 7px;
  color: #576579;
  font-size: 12px;
}
.toggle:hover { background: #f3f6fa; color: var(--text-heading); }
.toggle input { width: 14px; height: 14px; accent-color: var(--action-blue); }
.legend-toggle { min-height: 32px; border-color: #d9e1ea; border-radius: 7px; }
#calendar {
  border-color: #dce3ec;
  border-radius: 14px;
  box-shadow: var(--shadow-card);
}
.cal-header > div { padding: 10px 8px; border-bottom-color: #dce3ec; background: #f6f8fb; color: #657386; font-size: 10px; letter-spacing: .06em; }
.cal-day { border-right-color: #e6ebf1; border-bottom-color: #e6ebf1; }
.cal-day.other-month { background: #fafbfd; }
.cal-day.today { background: #fffaf0; }
.cal-day.today .day-number { background: var(--brand-red); }
.cal-day::after { background: var(--brand-navy); box-shadow: 0 2px 6px rgba(15,23,42,.2); }
.cal-side-column { width: 280px; top: 80px; max-height: calc(100vh - 100px); gap: 12px; }
.pending-sidebar { border-color: #dfe6ef; border-radius: 14px; box-shadow: var(--shadow-card); }
.pending-sidebar > header { padding: 13px 14px; border-radius: 13px 13px 0 0; background: #f7f9fc; }
.pending-sidebar h3 { color: #334155; font-size: 13px; font-weight: 700; }
.pending-sidebar-empty { color: #7c8999; }

@media (max-width: 1400px) {
  .topbar-user-name .current-user { display: none; }
}

@media (max-width: 1200px) {
  main { padding: 24px; }
  .corebridge-sync-alert { margin-right: 24px; margin-left: 24px; }
}

@media (max-width: 1024px) {
  .sidebar { width: 72px; }
  .sidebar-brand { justify-content: center; padding: 14px 8px; }
  .sidebar-brand .brand-logo { width: 46px; }
  .sidebar-brand-copy,
  .sidebar-workspace-label { display: none; }
  /* NAV-CONSOLIDATION: the sidebar is a 72px icon rail at this width, and a
     section label no longer fits — "Reference" measures 73px and would spill.
     ("Admin" survived here only by being short.) The grouping still matters,
     so the label collapses to the divider it already carries rather than
     disappearing: text goes, border-top stays. */
  .sidebar-section-label {
    font-size: 0;
    margin: 10px 12px 4px;
    padding-top: 10px;
  }
  .sidebar-item.active::before { left: -10px; }
  .sidebar-tenant { padding: 14px 8px; }
  .sidebar-tenant::before { left: 31px; top: 18px; }
  .page-heading-status { display: none; }
}

@media (max-width: 900px) {
  .cal-layout { flex-direction: column; }
  .cal-side-column { position: static; width: 100%; max-height: none; overflow: visible; }
  .pending-sidebar { width: 100%; max-height: 420px; }
  .cal-views { margin-left: 0; }
}

@media (max-width: 720px) {
  main { padding: 18px 12px 28px; }
  .corebridge-sync-alert { margin: 8px 12px 0; }
  .sidebar.open .sidebar-brand { justify-content: flex-start; padding: 14px 16px; }
  .sidebar.open .sidebar-brand .brand-logo { width: 58px; }
  .sidebar.open .sidebar-brand-copy { display: flex; }
  .sidebar.open .sidebar-workspace-label { display: block; }
  .topbar { min-height: 60px; padding: 9px 12px; }
  .topbar-actions { gap: 6px; }
  .topbar-manage-btn,
  .topbar-new-btn,
  .ai-insights-btn {
    width: 38px;
    min-width: 38px;
    padding: 0;
    justify-content: center;
  }
  .topbar-manage-btn > span,
  .topbar-new-btn > span { display: none; }
  .topbar-user { display: none; }
  .mobile-signout-item {
    margin-top: 8px;
    border-top: 1px solid rgba(255, 255, 255, .11);
    border-radius: 0;
    color: #fecaca;
  }
  .page-heading { align-items: flex-start; margin-bottom: 16px; }
  .page-heading h1,
  .page-heading-compact h1 { font-size: 22px; }
  .page-heading p { font-size: 12px; }
  .dashboard-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px; }
  .metric-card { min-height: 126px; padding: 14px; }
  .metric-card-head { align-items: flex-start; gap: 7px; margin-bottom: 11px; }
  .metric-card .metric-label { font-size: 9px; line-height: 1.3; }
  .metric-card .metric-value { font-size: 24px; }
  .week-in-review { padding: 16px; }
  .wir-grid { grid-template-columns: 1fr; }
  .cal-controls { gap: 7px; padding: 9px; }
  .cal-controls h2 { min-width: 0; font-size: 15px; }
  .cal-controls #cal-today { order: 5; }
  .cal-views { order: 6; width: 100%; }
  .cal-view-btn { flex: 1; }
  .cal-toolbar { align-items: stretch; padding: 10px; }
  .cal-search-wrap, #cal-search { width: 100%; }
  .cal-mode-toggle { width: 100%; }
  .cal-mode-btn { flex: 1; }
  .legend-toggle { margin-left: 0; }
}

/* ===================================================================== */
/* Phase 9 — Fully Promoted in-app intake (timeline / pricing / shipping */
/* / product cards / live job ticket). Built on the existing CSS-variable */
/* system; no framework, no new colours beyond the shared tokens.        */
/* ===================================================================== */

/* Display-only computed markup readout under the Pricing & Margins grid. */
.fp-markup-readout {
  font-size: 13px;
  color: var(--text-muted);
  padding: 2px 0;
}
.fp-markup-readout:empty { display: none; }

/* FP-INTAKE parity: item-category tick grid + steer note. */
.fp-cats-label { display: block; margin-bottom: 6px; }
.fp-category-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 4px 14px;
  margin-bottom: 12px;
}
.fp-category-grid label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-weight: 400;
  cursor: pointer;
  padding: 2px 0;
}
.fp-category-grid input { width: auto; margin: 0; }
.fp-cat-pref { margin-bottom: 14px; }

/* Repeatable product line-item cards inside the FP intake form. */
.fp-products-list { display: flex; flex-direction: column; gap: 14px; margin-bottom: 12px; }
.fp-product-card {
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
  background: var(--bg-page);
  padding: 14px 16px;
}
.fp-product-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.fp-product-card-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}
.fp-product-remove {
  border: none;
  background: none;
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
  color: var(--text-muted);
  padding: 2px 6px;
  border-radius: var(--r-sm);
}
.fp-product-remove:hover { background: var(--bg-surface); color: var(--text-heading); }
.fp-product-grid { gap: 14px 18px; }
/* View mode: product cards read-only (matches the shared .grid view-mode rules
   so an existing job's products only become editable after clicking Edit). */
#job-form.view-mode .fp-product-remove,
#job-form.view-mode #fp-add-product-btn { display: none !important; }

/* Live monospace job ticket — read-only running summary of the FP intake. */
.fp-job-ticket {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
  padding: 14px 16px;
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
  background: var(--bg-page);
  color: var(--text-body);
}
.fp-job-ticket:empty { display: none; }

/* ========================================================================
   SIGN PRICING TOOL (admin-only). Uses the shared CSS-var design system —
   no new tokens. Scoped under #tab-pricing / .pricing-* to avoid collisions.
   ======================================================================== */
#tab-pricing { padding: 4px 2px 40px; }
.pricing-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 18px;
}
.pricing-title { font-size: var(--fs-2xl); color: var(--text-heading); margin: 0; }
.pricing-sub { color: var(--text-muted); font-size: var(--fs-sm); margin: 4px 0 0; max-width: 640px; }
.pricing-nav { display: flex; gap: 4px; background: var(--bg-page); padding: 4px; border-radius: var(--r-pill); border: 1px solid var(--border-soft); }
.pricing-navbtn {
  border: 0; background: transparent; color: var(--text-muted); cursor: pointer;
  padding: 7px 16px; border-radius: var(--r-pill); font-size: var(--fs-sm); font-weight: 600;
}
.pricing-navbtn.active { background: var(--bg-surface); color: var(--text-heading); box-shadow: var(--shadow-sm); }

.pricing-view { display: none; }
.pricing-view.active { display: block; }
.pricing-toolbar { margin-bottom: 12px; }

/* Buttons */
.pricing-btn {
  border: 1px solid var(--border-strong); background: var(--bg-surface); color: var(--text-body);
  padding: 8px 14px; border-radius: var(--r-md); font-size: var(--fs-sm); font-weight: 600; cursor: pointer;
}
.pricing-btn:hover { background: var(--bg-page); }
.pricing-btn-sm { padding: 4px 10px; font-size: var(--fs-xs); }
.pricing-btn-primary { background: var(--action-blue); border-color: var(--action-blue); color: #fff; }
.pricing-btn-primary:hover { filter: brightness(0.95); background: var(--action-blue); }
.pricing-btn-danger { color: var(--semantic-rose); border-color: var(--border-soft); }
.pricing-btn-danger:hover { background: rgba(244,63,94,0.08); }

/* Tables */
.pricing-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.pricing-table th {
  text-align: left; color: var(--text-muted); font-size: var(--fs-xs); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.04em; padding: 8px 10px; border-bottom: 1px solid var(--border-soft);
}
.pricing-table td { padding: 8px 10px; border-bottom: 1px solid var(--border-soft); color: var(--text-body); vertical-align: middle; }
.pricing-table tbody tr:hover { background: var(--bg-page); }
.pricing-cell-name { font-weight: 600; color: var(--text-heading); }
.pricing-cell-price { font-weight: 700; color: var(--semantic-green); }
.pricing-row-actions { display: flex; gap: 6px; justify-content: flex-end; }
.pricing-empty, .pricing-line-empty td { color: var(--text-faint); text-align: center; padding: 20px; font-style: italic; }

/* Editor */
.pricing-editor-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
.pricing-editor-actions { display: flex; gap: 8px; }
.pricing-meta { display: grid; grid-template-columns: 2fr 1fr; gap: 12px; margin-bottom: 20px; }
.pricing-field { display: flex; flex-direction: column; gap: 4px; }
.pricing-field > span { font-size: var(--fs-xs); color: var(--text-muted); font-weight: 600; }
.pricing-input, .pricing-field input, .pricing-field textarea, .pricing-field select {
  border: 1px solid var(--border-strong); border-radius: var(--r-md); padding: 8px 10px;
  font-size: var(--fs-sm); color: var(--text-body); background: var(--bg-surface); width: 100%; font-family: inherit;
}
.pricing-input:focus { outline: none; border-color: var(--action-blue); box-shadow: 0 0 0 3px rgba(22,199,201,0.12); }
.pricing-notes { margin: 16px 0; }

.pricing-section { background: var(--bg-surface); border: 1px solid var(--border-soft); border-radius: var(--r-lg); padding: 14px 16px; margin-bottom: 14px; box-shadow: var(--shadow-sm); }
.pricing-section-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.pricing-section-head h3 { margin: 0; font-size: var(--fs-md); color: var(--text-heading); }
.pricing-section-sub { margin: 2px 0 0; font-size: var(--fs-xs); color: var(--text-muted); }
.pricing-section-tools { display: flex; align-items: center; gap: 12px; }
.pricing-toggle { display: flex; align-items: center; gap: 6px; font-size: var(--fs-sm); color: var(--text-body); white-space: nowrap; }

.pricing-lines { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.pricing-lines th { text-align: left; color: var(--text-muted); font-size: var(--fs-xs); font-weight: 600; padding: 4px 8px; }
.pricing-lines td { padding: 4px 8px; vertical-align: middle; }
.pricing-lines .pl-num { text-align: right; }
.pricing-lines .pl-num input { text-align: right; }
.pl-item { min-width: 180px; }
.pl-num input { max-width: 110px; }
.pl-line { font-weight: 600; color: var(--text-heading); white-space: nowrap; }
.pl-unit-label { color: var(--text-muted); font-size: var(--fs-xs); }
.pricing-x { border: 0; background: transparent; color: var(--text-faint); cursor: pointer; font-size: 14px; padding: 4px 6px; border-radius: var(--r-sm); }
.pricing-x:hover { color: var(--semantic-rose); background: rgba(244,63,94,0.08); }
.pricing-dim { opacity: 0.45; }

/* Footer / totals */
.pricing-footer {
  position: sticky; bottom: 0; margin-top: 18px;
  display: grid; grid-template-columns: 1fr 1.2fr 1.4fr; gap: 20px; align-items: center;
  background: var(--bg-surface); border: 1px solid var(--border-strong); border-radius: var(--r-lg);
  padding: 16px 20px; box-shadow: var(--shadow-lg);
}
.pricing-total-row { display: flex; flex-direction: column; gap: 2px; }
.pricing-total-row span { font-size: var(--fs-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.pricing-total-row strong { font-size: var(--fs-lg); color: var(--text-heading); }
.pricing-mode { display: flex; flex-direction: column; gap: 8px; }
.pricing-mode-switch { display: inline-flex; gap: 4px; background: var(--bg-page); padding: 3px; border-radius: var(--r-pill); border: 1px solid var(--border-soft); }
.pricing-modebtn { border: 0; background: transparent; color: var(--text-muted); cursor: pointer; padding: 5px 12px; border-radius: var(--r-pill); font-size: var(--fs-xs); font-weight: 600; }
.pricing-modebtn.active { background: var(--bg-surface); color: var(--action-blue); box-shadow: var(--shadow-sm); }
.pricing-mode-value input { max-width: 120px; }
.pricing-price-out { text-align: right; }
.pricing-price-big { display: flex; align-items: baseline; justify-content: flex-end; gap: 10px; }
.pricing-price-big span { font-size: var(--fs-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.pricing-price-big strong { font-size: var(--fs-2xl); color: var(--semantic-green); }
.pricing-price-metrics { display: flex; gap: 16px; justify-content: flex-end; margin-top: 4px; font-size: var(--fs-xs); color: var(--text-muted); }
.pricing-price-metrics b { color: var(--text-heading); }

/* Libraries */
.pricing-lib-intro { color: var(--text-muted); font-size: var(--fs-sm); max-width: 680px; margin: 0 0 16px; }
.pricing-lib-card { background: var(--bg-surface); border: 1px solid var(--border-soft); border-radius: var(--r-lg); padding: 14px 16px; margin-bottom: 16px; box-shadow: var(--shadow-sm); }
.pricing-lib-table .pricing-input { max-width: 160px; }
.pricing-lib-add td { border-top: 2px solid var(--border-soft); padding-top: 10px; }

@media (max-width: 760px) {
  .pricing-meta { grid-template-columns: 1fr; }
  .pricing-footer { grid-template-columns: 1fr; gap: 12px; text-align: left; }
  .pricing-price-out, .pricing-price-big, .pricing-price-metrics { text-align: left; justify-content: flex-start; }
}

/* Sign Pricing — Market check panel */
.pricing-market { background: var(--bg-surface); border: 1px solid var(--border-soft); border-radius: var(--r-lg); padding: 16px 18px; margin: 16px 0 140px; box-shadow: var(--shadow-sm); }
.pricing-market-head { margin-bottom: 12px; }
.pricing-market-head h3 { margin: 0; font-size: var(--fs-md); color: var(--text-heading); display: inline-flex; align-items: center; gap: 8px; }
.pricing-badge-ai { font-size: var(--fs-xs); font-weight: 700; color: var(--semantic-purple); background: rgba(139,92,246,0.12); padding: 2px 8px; border-radius: var(--r-pill); text-transform: uppercase; letter-spacing: 0.04em; }
.pricing-market-hint { color: var(--text-muted); font-size: var(--fs-sm); margin: 0; }
.pricing-market-inputs { display: grid; grid-template-columns: 1fr 2fr; gap: 12px; margin-bottom: 12px; }
.pricing-market-actions { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.pricing-market-status { color: var(--text-muted); font-size: var(--fs-sm); }

.pricing-market-range { margin: 14px 0 6px; }
.pmr-scale { position: relative; height: 10px; margin: 8px 4px; }
.pmr-bar { position: absolute; inset: 0; background: linear-gradient(90deg, var(--semantic-amber), var(--semantic-green), var(--semantic-amber)); border-radius: var(--r-pill); opacity: 0.55; }
.pmr-typ { position: absolute; top: -3px; width: 2px; height: 16px; background: var(--text-heading); transform: translateX(-1px); }
.pmr-you { position: absolute; top: -7px; width: 14px; height: 14px; border-radius: 50%; background: var(--action-blue); border: 2px solid var(--bg-surface); transform: translateX(-8px); top: -3px; box-shadow: var(--shadow-sm); }
.pmr-you-below { background: var(--semantic-amber); }
.pmr-you-above { background: var(--semantic-rose); }
.pmr-you-within { background: var(--semantic-green); }
.pmr-labels { display: flex; justify-content: space-between; font-size: var(--fs-xs); color: var(--text-muted); margin: 0 4px; }
.pmr-labels span:nth-child(2) { color: var(--text-heading); font-weight: 600; }

.pricing-market-verdict { font-size: var(--fs-sm); color: var(--text-body); margin: 10px 0 4px; }
.pmv-within b:last-of-type { color: var(--semantic-green); }
.pmv-below b:last-of-type { color: var(--semantic-amber); }
.pmv-above b:last-of-type { color: var(--semantic-rose); }
.pricing-conf { color: var(--text-muted); text-transform: capitalize; }
.pricing-market-basis { font-size: var(--fs-sm); color: var(--text-muted); margin: 4px 0 10px; }
.pricing-market-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.pricing-market-cols h4, .pricing-market-sources h4 { margin: 6px 0 4px; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }
.pricing-market-cols ul { margin: 0; padding-left: 18px; font-size: var(--fs-sm); color: var(--text-body); }
.pricing-market-cols li { margin-bottom: 3px; }
.pricing-market-sources { margin-top: 12px; display: flex; flex-direction: column; gap: 4px; }
.pricing-market-sources a { color: var(--action-blue); font-size: var(--fs-sm); text-decoration: none; }
.pricing-market-sources a:hover { text-decoration: underline; }
.pms-note { color: var(--text-muted); }
.pricing-market-disclaim { margin-top: 12px; font-size: var(--fs-xs); color: var(--text-faint); font-style: italic; }

@media (max-width: 760px) {
  .pricing-market-inputs, .pricing-market-cols { grid-template-columns: 1fr; }
}

/* Sign Pricing — substrate materials with variants (library) */
.pricing-sub-mat { border: 1px solid var(--border-soft); border-radius: var(--r-md); padding: 12px 14px; margin-bottom: 12px; background: var(--bg-page); }
.pricing-sub-mat-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.pricing-sub-mat-name { max-width: 240px; font-weight: 600; }
.pricing-sub-mat-waste { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); color: var(--text-muted); }
.pricing-sub-mat-waste input { max-width: 90px; }
.pricing-sub-vartable { width: 100%; }
.pricing-sub-vartable th { font-size: var(--fs-xs); }
.pricing-sub-vartable .pricing-input { max-width: 130px; }
.pricing-sub-perft { font-weight: 600; color: var(--semantic-green); white-space: nowrap; }
.pricing-sub-addmat { display: flex; gap: 10px; align-items: center; margin-top: 6px; flex-wrap: wrap; }
.pricing-sub-addmat #pricing-newmat-name { max-width: 260px; }
.pricing-sub-addmat #pricing-newmat-waste { max-width: 110px; }
/* substrate quote line: two selects (material + variant) */
.pricing-lines[data-cat="substrate"] .pl-item { min-width: 150px; }

/* Sign Pricing — material categories (library) */
.pricing-cat-name { font-weight: 600; font-size: var(--fs-md); color: var(--text-heading); }
input.pricing-cat-name { max-width: 240px; }
.pricing-mat-updated { color: var(--text-muted); font-size: var(--fs-xs); white-space: nowrap; }
.pricing-mat-cat { max-width: 130px; }
.pricing-sub-vartable .pricing-row-actions { display: flex; gap: 6px; align-items: center; justify-content: flex-end; flex-wrap: wrap; }

/* ==================================================================
   SIGNMETRY DESIGN SYSTEM — Slice 1: tokens + shell
   Appended last so the :root token overrides win by source order.
   Each store keeps its own name/logo; this is the shared Signmetry look.
   ================================================================== */
:root {
  --bg-page: #F5F7FA;              /* Cloud */
  --text-heading: #10233F;        /* Midnight */
  --text-body: #26313D;           /* Graphite */
  /* Midnight carries solid buttons/badges (keeps existing white button text
     legible) + nav; teal is the lead accent (links, active, focus). */
  --brand-red: #10233F;
  --brand-red-dark: #0B1A30;
  --action-blue: #16C7C9;
  --action-blue-dark: #12B6B8;
  --sm-midnight: #10233F;
  --sm-teal: #16C7C9;
  --sm-teal-dark: #12B6B8;
  --sm-coral: #FF6B4A;
  --sm-sidebar-line: #1C3555;
}
/* Manrope for headings / nav / primary controls; Inter stays for data + body. */
h1, h2, h3, .page-eyebrow, .sidebar-item, .sidebar-brand-copy strong,
.sidebar-tenant-name, button.primary, .topbar-new-btn, .topbar-manage-btn {
  font-family: "Manrope", "Inter", system-ui, sans-serif;
}
/* Teal leads on the eyebrow accent. */
.page-eyebrow { color: var(--sm-teal-dark); }
/* Hero CTAs on white surfaces — Midnight with white text (teal reads muddy on
   white; teal is kept for the dark sidebar's active state instead). */
button.primary, .topbar-new-btn {
  background: var(--sm-midnight); color: #ffffff;
  border-color: transparent; box-shadow: 0 6px 16px rgba(16,35,63,.18);
}
button.primary:hover, .topbar-new-btn:hover { background: #0B1A30; color: #ffffff; }
/* Signature Signmetry shell — dark Midnight sidebar with teal active item. */
.sidebar { background: var(--sm-midnight); border-right-color: var(--sm-sidebar-line); }
.sidebar-brand { border-bottom-color: var(--sm-sidebar-line); }
.sidebar-brand-copy strong { color: #ffffff; }
.sidebar-brand-copy span { color: #8FA1BB; }
.sidebar-section-label { color: #74869F; }
.sidebar-item { color: #C7D3E2; }
.sidebar-item:hover { background: rgba(255,255,255,.07); color: #ffffff; }
.sidebar-item.active { background: rgba(22,199,201,.16); color: var(--sm-teal); font-weight: 600; }
.sidebar-tenant { border-top-color: var(--sm-sidebar-line); }
.sidebar-tenant-name { color: #EEF2F8; }
.sidebar-tenant-loc { color: #8FA1BB; }

/* Sign Pricing — AI draft panel + custom (AI-estimated) lines */
.pricing-ai { background: var(--bg-surface); border: 1px solid var(--semantic-purple); border-radius: var(--r-lg); padding: 14px 16px; margin-bottom: 18px; box-shadow: var(--shadow-sm); }
.pricing-ai-head h3 { margin: 0; font-size: var(--fs-md); color: var(--text-heading); display: inline-flex; align-items: center; gap: 8px; }
.pricing-ai #pricing-ai-desc { margin: 10px 0; resize: vertical; }
.pricing-ai-actions { display: flex; align-items: center; gap: 12px; }
.pricing-ai-status { color: var(--text-muted); font-size: var(--fs-sm); }
.pricing-ai-result { margin-top: 12px; border-top: 1px solid var(--border-soft); padding-top: 10px; }
.pricing-ai-summary { font-size: var(--fs-sm); color: var(--text-body); margin: 0 0 6px; }
.pricing-ai-flag { color: var(--semantic-amber); font-weight: 600; }
.pricing-ai-assumptions h4 { margin: 6px 0 4px; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }
.pricing-ai-assumptions ul { margin: 0; padding-left: 18px; font-size: var(--fs-sm); color: var(--text-body); }
.pricing-ai-assumptions li { margin-bottom: 3px; }
.pricing-ai-empty { color: var(--text-faint); font-size: var(--fs-sm); font-style: italic; margin: 10px 0 0; }

.pl-custom { display: flex; align-items: center; gap: 8px; }
.pricing-custom-badge { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--semantic-amber); background: rgba(245,158,11,0.14); padding: 2px 6px; border-radius: var(--r-pill); white-space: nowrap; }
.pricing-custom-line { background: rgba(245,158,11,0.05); }

/* ==================================================================
   SIGNMETRY DESIGN SYSTEM — Slice 2: surfaces
   Blue accents were swept to teal above; these keep teal legible and
   bring warning states onto the coral (attention) brand color.
   ================================================================== */
/* Teal-background controls need Midnight text — white on teal fails contrast. */
nav#main-nav .nav-items > .tab.active,
.tab-dropdown-btn.active,
.cal-mode-btn.active,
.cal-view-btn.active,
.status-ready_for_install,
.header-action-btn,
.quick-action-btn.quick-install:hover:not(:disabled),
.pcc-mark-btn,
.suggestion-actions button.primary,
.ai-briefing-modal-footer button,
.jshot-map-open,
.jshot-archive-btn,
.jshot-d-btn.primary,
.jshot-d-btn.active,
.jshot-lb-edit button,
.cal-day.today .day-number {
  color: var(--sm-midnight) !important;
}
/* Attention state → Signal Coral (was red), per the brand guide. */
.corebridge-sync-alert.is-stale {
  border-color: var(--sm-coral); background: #FFF2EE; color: #7A2E1A;
}
.corebridge-sync-alert.is-stale .corebridge-sync-now { background: #E8502E; color: #fff; }
/* Signmetry mark in the sidebar brand (replaces the old app wordmark). */
.sidebar-brand .sidebar-mark { height: 34px; width: 34px; flex: 0 0 auto; }

/* ==================================================================
   CALENDAR CATEGORY COLORS — editable via the calendar "Colors" panel.
   Defaults below match the built-in palette, so nothing changes until a
   color is customized (saved per browser; applied as CSS vars on :root).
   ================================================================== */
:root {
  --cal-install:#16C7C9; --cal-pickup:#F59E0B; --cal-removal:#6D4C41;
  --cal-production:#212121; --cal-completed:#AB47BC; --cal-priority:#E53935;
  --cal-materials:#FB8C00; --cal-survey:#EC407A; --cal-task:#64748B;
}
.span-bar.in-prod { background: var(--cal-production); color: var(--cal-production-text, #fff); }
.span-bar.in-prod:hover { background: var(--cal-production); filter: brightness(1.25); }
.span-bar.completed { background: var(--cal-completed); color: var(--cal-completed-text, #fff); }
.span-bar.completed:hover { background: var(--cal-completed); filter: brightness(.92); }
.span-bar.priority { background: var(--cal-priority); color: var(--cal-priority-text, #fff); }
.span-bar.priority:hover { background: var(--cal-priority); filter: brightness(.92); }
/* Month-view chips for the same statuses (span bars are the week view). */
.cal-event.in-prod { background: var(--cal-production); color: var(--cal-production-text, #fff); border-left-color: color-mix(in srgb, var(--cal-production) 55%, #000); }
.cal-event.completed { background: color-mix(in srgb, var(--cal-completed) 16%, #fff); color: color-mix(in srgb, var(--cal-completed) 80%, #000); border-left-color: var(--cal-completed); }
.dot.install { background: var(--cal-install); }
/* Event chips use a light tint + colored border + dark text so they stay
   readable for ANY category color the user picks (solid bg + white text
   breaks for light colors). */
.cal-event.install { background: color-mix(in srgb, var(--cal-install) 16%, #fff); color: color-mix(in srgb, var(--cal-install) 82%, #000); border-left: 3px solid var(--cal-install); }
.cal-event.removal { background: color-mix(in srgb, var(--cal-removal) 16%, #fff); color: color-mix(in srgb, var(--cal-removal) 82%, #000); border-left: 3px solid var(--cal-removal); }
.dot.pickup { background: var(--cal-pickup); }
.cal-event.pickup { background: color-mix(in srgb, var(--cal-pickup) 16%, #fff); border-left-color: var(--cal-pickup); color: color-mix(in srgb, var(--cal-pickup) 82%, #000); }
.cal-event.priority, .span-bar.priority-chip { background: color-mix(in srgb, var(--cal-priority) 14%, #fff); border-left-color: var(--cal-priority); color: color-mix(in srgb, var(--cal-priority) 76%, #000); }
.cal-event.material-ordered, .cal-event.material-delivery { background: color-mix(in srgb, var(--cal-materials) 18%, #fff); border-left-color: var(--cal-materials); color: color-mix(in srgb, var(--cal-materials) 82%, #000); }
.cal-event.survey { background: color-mix(in srgb, var(--cal-survey) 14%, #fff); border-left-color: var(--cal-survey); color: color-mix(in srgb, var(--cal-survey) 80%, #000); }
.cal-event.task { border-left-color: var(--cal-task); }
/* The colors panel */
.cal-colors-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 18px; margin: 4px 0 6px; }
.cal-color-row { display: flex; align-items: center; gap: 10px; }
.cal-color-row input[type="color"] { width: 34px; height: 30px; border: 1px solid var(--border-soft); border-radius: 8px; padding: 0; background: none; cursor: pointer; flex: 0 0 auto; }
.cal-color-row label { font-size: 13px; color: var(--text-body); }
/* Materials to order — dashboard card + order-form price memory */
.mto-card h3 .mto-count { display:inline-block; background:#fff3e0; color:#e65100; font-size:12px; font-weight:700; padding:1px 8px; border-radius:20px; margin-left:6px; }
.mto-card h3 .mto-count.zero { background:#eef0f3; color:#6b7280; }
.mto-item { display:flex; align-items:center; justify-content:space-between; gap:10px; padding:9px 0; border-bottom:1px solid #eef0f3; }
.mto-item:last-child { border-bottom:none; }
.mto-main { min-width:0; }
.mto-meta { color:#6b7280; font-size:12px; margin-left:6px; }
.mto-actions { display:flex; gap:6px; flex:0 0 auto; }
.mto-actions button { font-size:12px; padding:5px 10px; border-radius:7px; border:1px solid #d0d4da; background:#fff; cursor:pointer; }
.mto-order { border-color:#a5d6a7; color:#137333; font-weight:600; }
.dl-empty { color:#6b7280; font-size:13px; padding:6px 0; }
.material-price-hint { background:#f6f8fb; border:1px solid #e1e4e8; border-radius:8px; padding:8px 11px; font-size:13px; color:#26313d; }
.mph-label { color:#6b7280; font-weight:700; font-size:11px; text-transform:uppercase; letter-spacing:.03em; margin-right:6px; }
.mph-hist-label { display:block; margin:0 0 4px; }
.mph-hist-row { display:flex; align-items:baseline; gap:10px; padding:3px 0; }
.mph-hist-row + .mph-hist-row { border-top:1px solid #e6eaf0; }
.mph-hist-date { color:#6b7280; font-size:12px; min-width:76px; }
.mph-hist-vendor { color:#455063; }

/* QC-GATE: persistent topbar QC count button (replaces the pop-up alerts) */
.qc-btn {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 38px; padding: 7px 12px; border-radius: 9px;
  border: 1px solid #d8e0ea; background: #fff; color: #42526a;
  font: inherit; font-size: 12px; font-weight: 650; cursor: pointer;
  box-shadow: 0 1px 1px rgba(15,23,42,.025); white-space: nowrap;
}
.qc-btn:hover { border-color: #b8c4d2; background: #f6f8fb; color: #10233F; }
.qc-btn .qc-badge {
  display: inline-block; min-width: 18px; text-align: center;
  background: #e11b22; color: #fff; font-size: 11px; font-weight: 700;
  padding: 1px 6px; border-radius: 999px;
}
.qc-btn .qc-badge.hidden { display: none; }
/* When jobs are waiting, the whole button reads as "act on me". */
.qc-btn.qc-has-pending { border-color: #f3b4b0; background: #fff4f3; color: #b3261e; }
.qc-btn.qc-has-pending:hover { background: #ffe9e7; }

/* QC approved-today report (Admin dashboard) */
.qc-appr-count { display:inline-block; background:#e6f7ee; color:#137333; font-size:13px; font-weight:700; padding:1px 9px; border-radius:20px; margin-left:6px; }
.qc-appr-people { display:flex; flex-wrap:wrap; gap:8px; margin:2px 0 12px; }
.qc-appr-chip { background:#eef6fc; color:#1a56c4; border:1px solid #d4e4f7; border-radius:999px; padding:3px 10px; font-size:12px; }
.qc-appr-chip b { font-weight:700; }
.qc-appr-row { display:flex; justify-content:space-between; gap:12px; padding:7px 0; border-bottom:1px solid #eef0f3; font-size:13px; }
.qc-appr-row:last-child { border-bottom:none; }
.qc-appr-job { color:#26313d; }
.qc-appr-meta { color:#6b7280; white-space:nowrap; }

/* ===================== ESTIMATES ===================== */
#tab-estimates { padding: 16px 20px 40px; }
.est-controls { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 4px; }
.est-view-title { margin: 0; font-size: 20px; }
.est-summary { color: #6b7280; font-size: 13px; }
.est-controls-spacer { flex: 1; }
.est-toggle-label { font-size: 13px; color: #4b5563; display: inline-flex; align-items: center; gap: 6px; }
.est-intro { color: #6b7280; font-size: 13px; margin: 6px 0 14px; max-width: 720px; }
.est-intro strong { color: #374151; }

.est-board { display: flex; gap: 14px; align-items: flex-start; overflow-x: auto; padding-bottom: 12px; }
.est-col { flex: 0 0 260px; background: #f4f6f8; border: 1px solid #e6e9ee; border-radius: 12px; display: flex; flex-direction: column; max-height: calc(100vh - 220px); }
.est-col-won { background: #eefaf1; border-color: #cdeed6; }
.est-col-lost { background: #fbf0f0; border-color: #f0d5d5; }
.est-col-head { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; font-weight: 600; font-size: 13px; color: #374151; border-bottom: 1px solid #e6e9ee; }
.est-col-count { background: #e2e6ec; color: #4b5563; border-radius: 999px; padding: 1px 8px; font-size: 12px; font-weight: 700; }
.est-col-body { padding: 10px; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
.est-col-empty { color: #b6bcc6; font-size: 13px; text-align: center; padding: 8px 0; }

.est-card { background: #fff; border: 1px solid #e3e7ec; border-radius: 10px; padding: 10px 11px; cursor: pointer; box-shadow: 0 1px 2px rgba(16,24,40,0.04); transition: box-shadow .12s, transform .12s; }
.est-card:hover { box-shadow: 0 3px 10px rgba(16,24,40,0.10); transform: translateY(-1px); }
.est-card-archived { opacity: .55; }
.est-card-top { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; }
.est-card-co { font-weight: 600; font-size: 14px; color: #1f2937; }
.est-card-amt { font-weight: 700; font-size: 13px; color: #137333; white-space: nowrap; }
.est-card-title { font-size: 12.5px; color: #4b5563; margin-top: 2px; }
.est-card-note { font-size: 12px; color: #6b7280; margin-top: 6px; font-style: italic; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.est-card-meta { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; }
.est-age { font-size: 11px; font-weight: 700; color: #6b7280; background: #eef0f3; border-radius: 999px; padding: 1px 7px; }
.est-age-warm { color: #92610a; background: #fdf1d8; }
.est-age-hot { color: #a4262c; background: #fbe0e1; }
.est-card-fu { font-size: 11px; color: #1a56c4; background: #eaf1fc; border-radius: 999px; padding: 1px 7px; }
.est-card-owner { font-size: 11px; color: #6b7280; margin-left: auto; }

/* Modal shell */
.est-modal-overlay { position: fixed; inset: 0; background: rgba(17,24,39,.45); display: flex; align-items: flex-start; justify-content: center; padding: 6vh 16px; z-index: 1000; overflow-y: auto; }
.est-modal { background: #fff; border-radius: 14px; width: 100%; max-width: 480px; padding: 18px 20px 20px; box-shadow: 0 12px 40px rgba(16,24,40,.25); }
.est-modal-wide { max-width: 820px; }
.est-modal-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; margin-bottom: 6px; }
.est-modal-head h3 { margin: 0; font-size: 18px; }
.est-modal-sub { color: #6b7280; font-size: 13px; margin: 0 0 14px; }
.est-x { background: none; border: none; font-size: 18px; color: #9ca3af; cursor: pointer; line-height: 1; padding: 2px 6px; }
.est-x:hover { color: #4b5563; }

.est-form { display: flex; flex-direction: column; gap: 10px; }
.est-form label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: #6b7280; font-weight: 600; }
.est-form input, .est-form select, .est-form textarea { font: inherit; font-size: 14px; color: #1f2937; font-weight: 400; padding: 8px 10px; border: 1px solid #d5dae1; border-radius: 8px; background: #fff; }
.est-form input:focus, .est-form select:focus, .est-form textarea:focus { outline: none; border-color: #2563eb; box-shadow: 0 0 0 3px rgba(37,99,235,.12); }
.est-form-row { display: flex; gap: 10px; }
.est-form-row > label { flex: 1; }
.est-form-actions { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-top: 6px; }

/* Detail drawer */
.est-d-body { display: flex; gap: 22px; }
.est-d-left { flex: 1 1 50%; }
.est-d-right { flex: 1 1 50%; display: flex; flex-direction: column; border-left: 1px solid #eef0f3; padding-left: 20px; }
.est-d-co { margin: 0; font-size: 18px; }
.est-d-title { color: #6b7280; font-size: 13px; margin-top: 2px; }
.est-d-field { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: #6b7280; font-weight: 600; margin-bottom: 4px; }
.est-d-field select { font: inherit; font-size: 14px; font-weight: 600; color: #1f2937; padding: 8px 10px; border: 1px solid #d5dae1; border-radius: 8px; }
.est-d-stageline { min-height: 18px; margin-bottom: 10px; }
.est-archive-btn { background: none; border: 1px solid #e3c4c4; color: #a4262c; border-radius: 8px; padding: 8px 12px; font: inherit; font-size: 13px; cursor: pointer; }
.est-archive-btn:hover { background: #fbf0f0; }

.est-notes-h { margin: 0 0 8px; font-size: 13px; color: #374151; }
.est-notes { flex: 1; overflow-y: auto; max-height: 340px; display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.est-notes-empty { color: #9ca3af; font-size: 13px; }
.est-note { background: #f7f8fa; border-radius: 8px; padding: 8px 10px; }
.est-note-system { background: transparent; border-left: 2px solid #e2e6ec; border-radius: 0; padding: 2px 0 2px 10px; }
.est-note-system .est-note-body { color: #8a919c; font-size: 12px; font-style: italic; }
.est-note-body { font-size: 13px; color: #1f2937; white-space: pre-wrap; }
.est-note-meta { font-size: 11px; color: #9ca3af; margin-top: 3px; }
.est-note-form { display: flex; gap: 8px; align-items: flex-end; }
.est-note-form textarea { flex: 1; font: inherit; font-size: 13px; padding: 8px 10px; border: 1px solid #d5dae1; border-radius: 8px; resize: vertical; }

/* Manage stages */
.est-stage-row { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.est-stage-label { flex: 1; font: inherit; font-size: 14px; padding: 6px 9px; border: 1px solid #d5dae1; border-radius: 7px; }
.est-stage-kind { font: inherit; font-size: 13px; padding: 6px 8px; border: 1px solid #d5dae1; border-radius: 7px; }
.est-stage-row button { background: #f2f4f7; border: 1px solid #e0e4ea; border-radius: 7px; padding: 6px 9px; cursor: pointer; color: #4b5563; }
.est-stage-row button:disabled { opacity: .4; cursor: default; }
.est-stage-del:hover { background: #fbf0f0; color: #a4262c; }
.est-stage-add { display: flex; gap: 8px; margin: 14px 0; }
.est-stage-add input { flex: 1; font: inherit; padding: 8px 10px; border: 1px solid #d5dae1; border-radius: 8px; }

@media (max-width: 680px) {
  .est-d-body { flex-direction: column; }
  .est-d-right { border-left: none; border-top: 1px solid #eef0f3; padding-left: 0; padding-top: 16px; }
  .est-form-row { flex-direction: column; }
}

/* The Lost-reason field is toggled via the [hidden] attribute; the label's
   display:flex would otherwise override the UA [hidden] rule, so restore it. */
.est-form label[hidden] { display: none !important; }

/* CB-EST: Corebridge estimate review strip */
.est-review { background: #fff7ed; border: 1px solid #fed7aa; border-radius: 12px; padding: 12px 14px; margin: 0 0 16px; }
.est-review-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.est-review-title { font-weight: 600; font-size: 13px; color: #9a3412; }
.est-review-count { background: #f97316; color: #fff; border-radius: 999px; padding: 1px 9px; font-size: 12px; font-weight: 700; }
.est-review-list { display: flex; flex-direction: column; gap: 8px; }
.est-review-card { display: flex; align-items: center; gap: 12px; justify-content: space-between; background: #fff; border: 1px solid #f1d9c0; border-radius: 9px; padding: 9px 12px; flex-wrap: wrap; }
.est-review-info { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; min-width: 0; }
.est-review-co { font-weight: 600; font-size: 14px; color: #1f2937; }
.est-review-amt { font-weight: 700; font-size: 13px; color: #137333; }
.est-review-num { font-size: 12px; color: #9ca3af; }
.est-review-desc { flex-basis: 100%; font-size: 12.5px; color: #6b7280; }
.est-review-actions { display: flex; gap: 8px; flex-shrink: 0; }
.est-review-actions button { padding: 6px 12px; font-size: 13px; }

/* CB-EST-DEDUP: duplicate-check modal */
.est-dup-list { display: flex; flex-direction: column; gap: 10px; margin: 6px 0 14px; max-height: 60vh; overflow-y: auto; }
.est-dup-clear { color: #137333; background: #eefaf1; border: 1px solid #cdeed6; border-radius: 10px; padding: 14px; font-size: 14px; }
.est-dup-row { border: 1px solid #f0d5d5; background: #fdf7f7; border-radius: 10px; padding: 11px 13px; }
.est-dup-est { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.est-dup-est-co { font-weight: 600; font-size: 14px; color: #1f2937; }
.est-dup-est-amt { font-weight: 700; font-size: 13px; color: #137333; }
.est-dup-est-num { font-size: 12px; color: #9ca3af; }
.est-dup-est-stage { font-size: 11px; color: #6b7280; background: #eef0f3; border-radius: 999px; padding: 1px 8px; margin-left: auto; }
.est-dup-matches { margin: 8px 0; padding-left: 12px; border-left: 2px solid #e6c9c9; display: flex; flex-direction: column; gap: 4px; }
.est-dup-match { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.est-dup-order { font-size: 13px; color: #374151; }
.est-dup-tag { font-size: 11px; font-weight: 600; border-radius: 999px; padding: 1px 8px; }
.est-dup-tag.exact { color: #a4262c; background: #fbe0e1; }
.est-dup-tag.likely { color: #92610a; background: #fdf1d8; }
.est-dup-actions { display: flex; gap: 8px; margin-top: 8px; }
.est-dup-actions button { padding: 6px 12px; font-size: 13px; }

/* Estimate date notation on cards + review strip */
.est-card-date { font-size: 11px; color: #4b5563; background: #eef0f3; border-radius: 999px; padding: 1px 7px; }
.est-review-date { font-size: 12px; color: #6b7280; }

/* CB-EST: review-strip bulk tools */
.est-review-tools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 4px 0 12px; }
/* #est-review-search is a contenteditable div standing in for an <input>
   (Chrome-email-autofill defense, same as #kanban-search / #cal-search) —
   mimic single-line input behavior. */
.est-review-tools #est-review-search { flex: 1 1 240px; min-width: 180px; font: inherit; font-size: 13px; padding: 7px 10px; border: 1px solid #e6c9a8; border-radius: 8px; background: #fff; cursor: text; white-space: nowrap; overflow-x: auto; overflow-y: hidden; line-height: 1.4; }
.est-review-tools #est-review-search:empty::before { content: attr(data-placeholder); color: #9ca3af; pointer-events: none; }
.est-review-tools #est-review-search:focus { outline: none; border-color: #2563eb; box-shadow: 0 0 0 3px rgba(37,99,235,.12); }
.est-review-beforelbl, .est-review-selall-lbl { font-size: 12px; color: #7a4a12; display: inline-flex; align-items: center; gap: 6px; }
.est-review-beforelbl input { font: inherit; font-size: 12px; padding: 5px 7px; border: 1px solid #e6c9a8; border-radius: 7px; }
.est-review-selcount { font-size: 12px; color: #9a3412; font-weight: 600; min-width: 64px; }
.est-review-tools button { padding: 6px 12px; font-size: 13px; }
.est-review-tools button:disabled { opacity: .5; cursor: default; }
.est-review-list { max-height: 460px; overflow-y: auto; }
.est-review-card { align-items: center; }
.est-review-cb { width: 16px; height: 16px; flex-shrink: 0; margin-right: 4px; }
.est-review-more { padding: 10px 4px 2px; font-size: 12px; color: #9a3412; font-style: italic; }
.est-review-empty { padding: 10px 4px; font-size: 13px; color: #9ca3af; }

/* CB-EST: review head + bulk stage select */
.est-review-head-spacer { flex: 1; }
.est-review-place-lbl { font-size: 12px; color: #7a4a12; display: inline-flex; align-items: center; gap: 6px; }
.est-review-place-lbl select { font: inherit; font-size: 12px; padding: 5px 7px; border: 1px solid #e6c9a8; border-radius: 7px; background: #fff; }

/* CB-EST: triage modal */
.est-triage .est-tri-progress { font-size: 12px; color: #6b7280; margin-bottom: 2px; }
.est-triage .est-tri-stats { color: #9ca3af; }
.est-tri-co { margin: 0; font-size: 20px; }
.est-tri-facts { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: baseline; margin: 10px 0 6px; }
.est-tri-amt { font-weight: 700; font-size: 16px; color: #137333; }
.est-tri-num { font-size: 13px; color: #9ca3af; }
.est-tri-date { font-size: 13px; color: #4b5563; }
.est-tri-owner { font-size: 13px; color: #6b7280; }
.est-tri-title { font-size: 14px; color: #26313d; margin-bottom: 4px; }
.est-tri-contact { font-size: 13px; color: #6b7280; }
.est-tri-prompt { margin: 16px 0 8px; font-weight: 600; color: #374151; }
.est-tri-hint { font-weight: 400; font-size: 12px; color: #9ca3af; }
.est-tri-stages { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.est-tri-stage { display: inline-flex; align-items: center; gap: 8px; padding: 10px 14px; font: inherit; font-size: 14px; font-weight: 600; color: #1f2937; background: #eef6fc; border: 1px solid #d4e4f7; border-radius: 10px; cursor: pointer; }
.est-tri-stage:hover { background: #dcebfa; }
.est-tri-stage.est-tri-won { background: #eefaf1; border-color: #cdeed6; color: #137333; }
.est-tri-stage.est-tri-lost { background: #fbf0f0; border-color: #f0d5d5; color: #a4262c; }
.est-tri-key { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 5px; font-size: 12px; font-weight: 700; color: #fff; background: #64748b; border-radius: 5px; }
.est-tri-actions { display: flex; gap: 10px; border-top: 1px solid #eef0f3; padding-top: 12px; }
.est-tri-actions button { display: inline-flex; align-items: center; gap: 7px; padding: 8px 12px; font: inherit; font-size: 13px; border-radius: 8px; cursor: pointer; border: 1px solid #d5dae1; background: #f7f8fa; color: #4b5563; }
.est-tri-dismiss:hover { background: #fbf0f0; color: #a4262c; border-color: #e3c4c4; }
.est-tri-undo:disabled { opacity: .4; cursor: default; }

/* CB-EST: import queue is now a slim persistent banner (board stays primary). */
.est-review { background: transparent; border: none; padding: 0; margin: 0 0 14px; }
.est-review-banner { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: #fff7ed; border: 1px solid #fdba74; border-radius: 12px; padding: 11px 16px; }
.est-review-banner-icon { font-size: 18px; line-height: 1; }
.est-review-banner-text { font-size: 14px; color: #7c2d12; }   /* darker for contrast */
.est-review-banner-text strong { font-weight: 700; }
.est-review-banner-actions { margin-left: auto; display: flex; gap: 8px; }
.est-review-banner-actions button { padding: 7px 14px; font-size: 13px; }
/* Bulk-sort modal reuses .est-review-tools / .est-review-list (styled earlier). */
.est-modal .est-review-tools { margin-top: 4px; }
.est-modal .est-review-list { max-height: 52vh; }
.est-summary { color: #4b5563; }   /* was lighter — bump contrast on the header summary */

/* CB-EST: salesperson filter + auto-sort + suggested-stage highlight */
.est-review-ownerlbl, .est-tri-ownerlbl { font-size: 12px; color: #7a4a12; display: inline-flex; align-items: center; gap: 6px; }
.est-review-ownerlbl select, .est-tri-ownerlbl select { font: inherit; font-size: 12px; padding: 5px 7px; border: 1px solid #e6c9a8; border-radius: 7px; background: #fff; }
.est-tri-ownerlbl { color: #6b7280; }
.est-tri-ownerlbl select { border-color: #d5dae1; }
.est-tri-head-right { display: flex; align-items: center; gap: 12px; }
#est-review-autosort { border-color: #c7b3ea; color: #5b3a9e; background: #f3eefc; }
#est-review-autosort:hover { background: #e9e0fa; }
.est-tri-stage.est-tri-suggested { outline: 2px solid #2563eb; outline-offset: 1px; box-shadow: 0 0 0 4px rgba(37,99,235,.12); }
.est-tri-star { color: #2563eb; font-size: 12px; }
.est-tri-stage.est-tri-won.est-tri-suggested { outline-color: #137333; }
.est-tri-stage.est-tri-lost.est-tri-suggested { outline-color: #a4262c; }

/* CB-EST: clickable column header + open-stage footer */
.est-col-head { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 12px; font: inherit; font-weight: 600; font-size: 13px; color: #374151; background: none; border: none; border-bottom: 1px solid #e6e9ee; cursor: pointer; text-align: left; }
.est-col-head:hover { background: rgba(37,99,235,.06); }
.est-col-headright { display: inline-flex; align-items: center; gap: 8px; }
.est-col-total { font-size: 11px; font-weight: 700; color: #137333; }
.est-col-more { width: 100%; padding: 8px 10px; font: inherit; font-size: 12px; font-weight: 600; color: #1a56c4; background: #eef4fd; border: none; border-top: 1px solid #e6e9ee; border-radius: 0 0 12px 12px; cursor: pointer; }
.est-col-more:hover { background: #dde9fb; }
.est-col-more-quiet { color: #6b7280; background: transparent; font-weight: 500; }
.est-col-more-quiet:hover { background: rgba(37,99,235,.06); color: #1a56c4; }

/* CB-EST: stage view (comprehensive per-stage list) */
.est-sv-tools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 4px 0 12px; }
#est-sv-search { flex: 1 1 260px; min-width: 200px; font: inherit; font-size: 13px; padding: 7px 10px; border: 1px solid #d5dae1; border-radius: 8px; background: #fff; cursor: text; white-space: nowrap; overflow-x: auto; overflow-y: hidden; line-height: 1.4; }
#est-sv-search:empty::before { content: attr(data-placeholder); color: #9ca3af; pointer-events: none; }
#est-sv-search:focus { outline: none; border-color: #2563eb; box-shadow: 0 0 0 3px rgba(37,99,235,.12); }
.est-sv-sortlbl { font-size: 12px; color: #6b7280; display: inline-flex; align-items: center; gap: 6px; }
.est-sv-sortlbl select { font: inherit; font-size: 12px; padding: 5px 7px; border: 1px solid #d5dae1; border-radius: 7px; background: #fff; }
.est-sv-list { max-height: 62vh; overflow-y: auto; }
.est-sv-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.est-sv-table thead th { position: sticky; top: 0; background: #f7f8fa; text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .03em; color: #6b7280; padding: 7px 10px; border-bottom: 1px solid #e6e9ee; }
.est-sv-table th.est-sv-r, .est-sv-table td.est-sv-r { text-align: right; }
.est-sv-row { cursor: pointer; border-bottom: 1px solid #eef0f3; }
.est-sv-row:hover { background: #eef6fc; }
.est-sv-row td { padding: 8px 10px; }
.est-sv-co { font-weight: 600; color: #1f2937; }
.est-sv-title { color: #4b5563; max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.est-sv-amt { font-weight: 700; color: #137333; white-space: nowrap; }
.est-sv-empty { padding: 14px 10px; color: #9ca3af; }

/* ===================== REPURCHASE (Phase 2) ===================== */
.rp-search { font: inherit; font-size: 14px; padding: 8px 11px; border: 1px solid #d5dae1; border-radius: 8px; background: #fff; margin: 4px 0 12px; cursor: text; white-space: nowrap; overflow-x: auto; line-height: 1.4; }
.rp-search:empty::before { content: attr(data-placeholder); color: #9ca3af; pointer-events: none; }
.rp-search:focus { outline: none; border-color: #2563eb; box-shadow: 0 0 0 3px rgba(37,99,235,.12); }
.rp-pick-list { max-height: 55vh; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; }
.rp-pick-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; width: 100%; text-align: left; background: #fff; border: 1px solid #e3e7ec; border-radius: 9px; padding: 10px 12px; cursor: pointer; font: inherit; }
.rp-pick-row:hover { background: #f4f8fd; border-color: #cfe0f5; }
.rp-pick-item { font-weight: 600; font-size: 14px; color: #1f2937; display: block; }
.rp-pick-vendor { font-size: 12.5px; color: #6b7280; }
.rp-pick-price { text-align: right; white-space: nowrap; }
.rp-pick-cur { font-weight: 700; color: #137333; font-size: 14px; display: block; }
.rp-pick-sub { font-size: 11px; color: #9ca3af; }
.rp-empty { color: #9ca3af; font-size: 13px; padding: 12px; }
.rp-wf-sub { font-size: 13px; color: #6b7280; margin-top: 2px; }
.rp-wf-grid { display: flex; gap: 16px; margin: 8px 0 6px; }
.rp-wf-col { flex: 1; border: 1px solid #e6e9ee; border-radius: 10px; padding: 12px 14px; }
.rp-wf-prev { background: #f7f8fa; }
.rp-wf-new { background: #f4f8fd; border-color: #cfe0f5; }
.rp-wf-h { font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: .03em; color: #6b7280; margin-bottom: 8px; }
.rp-wf-line { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; font-size: 13px; color: #4b5563; }
.rp-wf-line b { color: #1f2937; }
.rp-wf-field { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: #6b7280; font-weight: 600; margin-bottom: 8px; }
.rp-wf-field input { font: inherit; font-size: 14px; font-weight: 400; color: #1f2937; padding: 8px 10px; border: 1px solid #d5dae1; border-radius: 8px; }
#rp-change.rp-up { color: #a4262c; } #rp-change.rp-down { color: #137333; }
.rp-wf-specs { margin: 8px 0; font-size: 13px; }
.rp-wf-specs summary { cursor: pointer; color: #2563eb; }
.rp-wf-specrow { display: flex; gap: 10px; margin-top: 8px; }
.rp-wf-specrow label { flex: 1; display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: #6b7280; }
.rp-wf-specrow input { font: inherit; font-size: 13px; padding: 6px 9px; border: 1px solid #d5dae1; border-radius: 7px; }
.rp-wf-warn { background: #fff7ed; border: 1px solid #fed7aa; border-radius: 9px; padding: 10px 12px; font-size: 13px; color: #9a3412; margin: 8px 0; }
.rp-wf-warn label { display: block; margin-top: 6px; font-size: 12px; }

/* ===================== REPURCHASE PICKER (Phase 3) ===================== */
.rp-pick-tools { display: flex; gap: 10px; align-items: center; margin: 4px 0 12px; }
.rp-pick-tools .rp-search { flex: 1; margin: 0; }
.rp-pick-vendorlbl { font-size: 12px; color: #6b7280; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.rp-pick-vendorlbl select { font: inherit; font-size: 13px; padding: 6px 8px; border: 1px solid #d5dae1; border-radius: 7px; background: #fff; }
.rp-pick-body { max-height: 60vh; overflow-y: auto; }
.rp-sec { margin-bottom: 14px; }
.rp-sec-h { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: #6b7280; margin: 4px 0 8px; }
.rp-sec-n { color: #b6bcc6; font-weight: 600; }
.rp-sec-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.rp-card { text-align: left; background: #fff; border: 1px solid #e3e7ec; border-radius: 10px; padding: 10px 12px; cursor: pointer; font: inherit; display: flex; flex-direction: column; gap: 4px; }
.rp-card:hover { background: #f4f8fd; border-color: #cfe0f5; box-shadow: 0 2px 8px rgba(16,24,40,.06); }
.rp-card-top { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.rp-card-item { font-weight: 600; font-size: 13.5px; color: #1f2937; }
.rp-card-dim { font-weight: 400; font-size: 12px; color: #6b7280; }
.rp-card-cur { font-weight: 700; font-size: 13.5px; color: #137333; white-space: nowrap; }
.rp-card-mid { font-size: 12px; color: #6b7280; }
.rp-card-bot { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: center; font-size: 11.5px; color: #8a919c; }
.rp-card-diff.rp-up { color: #a4262c; font-weight: 600; }
.rp-card-diff.rp-down { color: #137333; font-weight: 600; }
.rp-card-count { margin-left: auto; }
@media (max-width: 640px) { .rp-sec-list { grid-template-columns: 1fr; } }

/* ===================== REPURCHASE Phase 4 (modes + vendor rows) ============ */
.rp-modes { display: inline-flex; gap: 2px; background: #eef0f3; border-radius: 9px; padding: 3px; margin: 2px 0 12px; }
.rp-mode { border: none; background: transparent; font: inherit; font-size: 13px; font-weight: 600; color: #6b7280; padding: 6px 14px; border-radius: 7px; cursor: pointer; }
.rp-mode.active { background: #fff; color: #1f2937; box-shadow: 0 1px 2px rgba(16,24,40,.08); }
.rp-vlist { display: flex; flex-direction: column; gap: 8px; max-height: 56vh; overflow-y: auto; }
.rp-vrow { text-align: left; background: #fff; border: 1px solid #e3e7ec; border-radius: 10px; padding: 11px 13px; cursor: pointer; font: inherit; display: flex; flex-direction: column; gap: 3px; }
.rp-vrow:hover { background: #f4f8fd; border-color: #cfe0f5; }
.rp-vrow-top { display: flex; align-items: center; gap: 8px; }
.rp-vrow-vendor { font-weight: 700; font-size: 14px; color: #1f2937; }
.rp-badge { font-size: 11px; font-weight: 600; border-radius: 999px; padding: 1px 8px; }
.rp-badge-pref { color: #7a4a12; background: #fdf1d8; }
.rp-badge-cheap { color: #137333; background: #eefaf1; }
.rp-vrow-price { font-size: 13.5px; color: #137333; font-weight: 600; }
.rp-vrow-norm { color: #6b7280; font-weight: 400; font-size: 12px; }
.rp-vrow-meta { font-size: 12px; color: #6b7280; }
.rp-vrow-spec { font-size: 11.5px; color: #9ca3af; }
.rp-specwarn { background: #fff7ed; border: 1px solid #fed7aa; border-radius: 9px; padding: 9px 12px; font-size: 12.5px; color: #9a3412; margin-bottom: 10px; }

/* ===================== REPURCHASE Phase 5 ===================== */
/* Favorites, preferred, unavailable, substitutes, product settings, table cols */

/* Picker card — favorite star + preferred/unavailable states */
.rp-card-topr { display: inline-flex; align-items: center; gap: 7px; }
.rp-fav { cursor: pointer; color: #d5dae1; font-size: 15px; line-height: 1; user-select: none; transition: color .1s; }
.rp-fav:hover { color: #f2b705; }
.rp-fav.on { color: #f2b705; }
.rp-card-unavail { opacity: .62; background: #fafafa; }
.rp-card-unavail:hover { opacity: .85; }
.rp-card-badge { display: inline-block; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .02em; color: #a4262c; background: #fdeeee; border-radius: 5px; padding: 0 5px; }

/* Workflow warning flags (unavailable / stale / expensive) */
.rp-wf-flags { display: flex; flex-direction: column; gap: 6px; margin: 4px 0 10px; }
.rp-wf-flag { background: #fff7ed; border: 1px solid #fed7aa; border-radius: 9px; padding: 8px 12px; font-size: 12.5px; color: #9a3412; }

/* Approved substitutes list in the workflow */
.rp-subs { margin: 4px 0 12px; }
.rp-sub-list { display: flex; flex-direction: column; gap: 7px; }
.rp-sub { text-align: left; background: #f7fbf8; border: 1px solid #d9ecdf; border-radius: 10px; padding: 9px 12px; cursor: pointer; font: inherit; display: flex; flex-direction: column; gap: 3px; }
.rp-sub:hover { background: #eefaf1; border-color: #b7e0c4; }
.rp-sub-top { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; }
.rp-sub-item { font-weight: 600; font-size: 13px; color: #1f2937; }
.rp-sub-cur { font-weight: 700; font-size: 13px; color: #137333; white-space: nowrap; }
.rp-sub-meta { font-size: 12px; color: #6b7280; }
.rp-sub-diff { font-size: 11.5px; color: #9a6a12; }

/* Product settings disclosure */
.rp-wf-settings { margin: 6px 0 4px; font-size: 13px; }
.rp-wf-settings > summary { cursor: pointer; color: #2563eb; }
.rp-set-toggles { display: flex; flex-wrap: wrap; gap: 8px 18px; margin: 10px 0 4px; align-items: center; }
.rp-set-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: #4b5563; cursor: pointer; }
.rp-set-field { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: #6b7280; }
.rp-set-field input, .rp-set-field select { font: inherit; font-size: 13px; padding: 5px 8px; border: 1px solid #d5dae1; border-radius: 7px; }
.rp-set-field input[type=number] { width: 90px; }
.rp-set-sub { display: flex; margin-top: 8px; }

/* Table: optional repurchase columns (hidden until toggled) + inline button */
.rp-cols-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: #4b5563; cursor: pointer; }
#material-prices-table .rp-col { display: none; }
#material-prices-table.show-rp-cols .rp-col { display: table-cell; }
.rp-row-btn { color: #2563eb; }
.rp-row-btn:hover { background: #e8f0fe; }
.rp-up { color: #a4262c; font-weight: 600; }
.rp-down { color: #137333; font-weight: 600; }
.rp-more-note { font-size: 12px; color: #8a919c; text-align: center; padding: 8px 4px 2px; }

/* ===================== MATERIAL PRICING — style refresh (approved mock) =====
   Restyle only: same structure, handlers, data. Palette matches Signmetry
   (navy #102842 primary, teal accents, blue repurchase, red price-rise). */

/* Toolbar: single-row grid on desktop; search gets the most width. */
#tab-material-pricing .jobs-controls { display: grid; grid-template-columns: minmax(200px, 1fr) 150px auto auto auto auto; gap: 9px; align-items: center; max-width: 1220px; }
#tab-material-pricing #material-price-search,
#tab-material-pricing #material-price-filter-status { height: 37px; border: 1px solid #d4dde7; border-radius: 8px; background: #fff; color: #405268; padding: 0 11px; outline: none; }
#tab-material-pricing #material-price-search:focus,
#tab-material-pricing #material-price-filter-status:focus { border-color: #0eb6b2; box-shadow: 0 0 0 3px rgba(14,182,178,.11); }
#tab-material-pricing #material-catalog-btn,
#tab-material-pricing #material-repurchase-btn { height: 37px; border: 1px solid #d4dde7; border-radius: 8px; background: #fff; color: #304055; padding: 0 11px; cursor: pointer; white-space: nowrap; }
#tab-material-pricing #material-catalog-btn:hover,
#tab-material-pricing #material-repurchase-btn:hover { border-color: #aebdcb; background: #fbfcfd; }
#tab-material-pricing #material-price-add-btn { height: 37px; border: 0; border-radius: 8px; padding: 0 14px; background: #102842; color: #fff; font-weight: 700; cursor: pointer; box-shadow: 0 4px 10px rgba(16,40,66,.13); }
#tab-material-pricing #material-price-add-btn:hover { background: #16324f; }

/* Segmented By product / All entries */
.mp-view { display: inline-flex; height: 37px; padding: 3px; border-radius: 9px; background: #edf1f5; }
.mp-view-btn { border: 0; border-radius: 7px; padding: 0 12px; background: transparent; color: #748195; font: inherit; font-size: 12px; font-weight: 700; cursor: pointer; white-space: nowrap; }
.mp-view-btn.active { background: #fff; color: #243246; box-shadow: 0 1px 3px rgba(28,47,67,.12); }

/* Table surface + compact rows */
#tab-material-pricing .table-wrap { max-width: 1220px; border: 1px solid #dce3eb; border-radius: 10px; background: #fff; overflow: hidden; }
#material-prices-table { table-layout: fixed; }
#material-prices-table th { height: 33px; padding: 0 10px; background: #f7f9fb; border-bottom: 1px solid #dfe6ee; color: #657387; font-size: 9px; font-weight: 800; letter-spacing: .045em; text-transform: uppercase; text-align: left; }
#material-prices-table td { height: 42px; padding: 7px 10px; border-bottom: 1px solid #edf1f5; color: #354358; font-size: 11px; vertical-align: middle; overflow: hidden; text-overflow: ellipsis; }
#material-prices-table tbody tr.mp-prod:last-child td,
#material-prices-table tbody tr.mp-entry-row:last-child td { border-bottom: 0; }
/* Columns: chevron | item | vendor | category | price | $/sq ft | last | rebuy */
#material-prices-table th:nth-child(1), #material-prices-table td:nth-child(1) { width: 30px; padding-left: 12px; padding-right: 0; }
#material-prices-table th:nth-child(2), #material-prices-table td:nth-child(2) { width: 40%; }
#material-prices-table th:nth-child(3), #material-prices-table td:nth-child(3) { width: 13%; }
#material-prices-table th:nth-child(4), #material-prices-table td:nth-child(4) { width: 14%; }
#material-prices-table th:nth-child(5), #material-prices-table td:nth-child(5) { width: 11%; }
#material-prices-table th:nth-child(6), #material-prices-table td:nth-child(6) { width: 9%; }
#material-prices-table th:nth-child(7), #material-prices-table td:nth-child(7) { width: 13%; }
#material-prices-table th:nth-child(8), #material-prices-table td:nth-child(8) { width: 44px; text-align: center; padding: 0; }
#material-prices-table td.mp-num, #material-prices-table th.mp-num { text-align: right; font-variant-numeric: tabular-nums; }
#material-prices-table tbody tr.mp-prod { cursor: pointer; }
#material-prices-table tbody tr.mp-prod:hover,
#material-prices-table tbody tr.mp-entry-row:hover { background: #f7fbfb; }

/* Item + size/count badge */
.mp-item strong { color: #243246; font-weight: 600; }
.mp-count { display: inline-block; margin-left: 6px; padding: 2px 5px; border-radius: 5px; background: #edf1f5; color: #7a8797; font-size: 9px; font-weight: 700; vertical-align: 1px; }

/* Price + increase indicator */
.mp-price { color: #243246; font-weight: 600; }
.mp-up { display: block; margin-top: 2px; color: #c3434e; font-size: 9px; font-weight: 700; }

/* Chevron expand button */
.mp-exp-btn { width: 25px; height: 25px; border: 0; border-radius: 6px; background: transparent; color: #9aa8b7; cursor: pointer; font: inherit; font-size: 15px; line-height: 1; transition: transform .15s ease; }
.mp-prod.mp-open .mp-exp-btn { transform: rotate(90deg); color: #087f86; }

/* Repurchase (blue) */
.rp-row-btn { width: 28px; height: 28px; border: 0; border-radius: 7px; background: transparent; color: #1266f1; cursor: pointer; font-size: 15px; }
.rp-row-btn:hover { background: #edf4ff; }

/* Keyboard focus visibility */
#tab-material-pricing :is(button, input, select):focus-visible { outline: 2px solid #0eb6b2; outline-offset: 2px; }

/* Expanded price-history row (chronological chain: oldest -> current) */
.mp-entries { cursor: default; }
.mp-entries > td { padding: 12px 16px 14px 38px; background: #f8fbfc; }
.mp-historyline { display: flex; align-items: center; gap: 8px; overflow-x: auto; }
.mp-historylabel { color: #66778a; font-size: 10px; font-weight: 700; margin-right: 5px; white-space: nowrap; }
.mp-purchase { min-width: 112px; border: 0; border-left: 2px solid #c7d5e1; padding: 0 0 0 8px; background: transparent; text-align: left; font: inherit; cursor: pointer; }
.mp-purchase.current { border-left-color: #d14a55; }
.mp-purchase:hover strong { text-decoration: underline; }
.mp-purchase strong { display: block; color: #273549; font-size: 11px; font-weight: 600; }
.mp-purchase span { display: block; margin-top: 2px; color: #8290a1; font-size: 9px; }
.mp-arrow { color: #9ca9b7; }

/* Muted inline note (All entries view) */
.mp-e-notes { color: #8290a1; font-weight: 400; }

/* Visually-hidden label for screen readers */
#tab-material-pricing .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }

/* Footer legend */
.mp-footer { display: flex; justify-content: space-between; gap: 12px; max-width: 1220px; padding: 9px 2px 0; color: #7d8c9c; font-size: 10px; }

/* Responsive middle range: the six-column control grid never wrapped, so with
   the sidebar (~230px) the row overflowed the page anywhere under ~1280px —
   the only horizontal-scroll offender in the 2026-09-12 sizing audit. Let the
   controls wrap onto a second row; the ≤760 block below still takes over on
   phones (it re-declares display:grid and hides the lower-priority tools). */
@media (max-width: 1280px) {
  #tab-material-pricing .jobs-controls { display: flex; flex-wrap: wrap; }
  #tab-material-pricing #material-price-search { flex: 1 1 240px; min-width: 180px; }
}

/* Responsive: search to its own row, hide lower-priority columns before scroll */
@media (max-width: 760px) {
  #tab-material-pricing .jobs-controls { grid-template-columns: 1fr auto auto; }
  #tab-material-pricing #material-price-search { grid-column: 1 / -1; }
  #tab-material-pricing #material-price-filter-status,
  #tab-material-pricing #material-catalog-btn,
  #tab-material-pricing #material-repurchase-btn { display: none; }
  #material-prices-table th:nth-child(4), #material-prices-table td:nth-child(4),
  #material-prices-table th:nth-child(6), #material-prices-table td:nth-child(6),
  #material-prices-table th:nth-child(7), #material-prices-table td:nth-child(7) { display: none; }
  #material-prices-table th:nth-child(2), #material-prices-table td:nth-child(2) { width: 50%; }
  #material-prices-table th:nth-child(3), #material-prices-table td:nth-child(3) { width: 21%; }
  #material-prices-table th:nth-child(5), #material-prices-table td:nth-child(5) { width: 23%; }
}

/* ===================== ESTIMATES — WORKFLOW (EST-WORKFLOW) =====================
   The estimates tracker carries two independent statuses per record: the sales
   stage (a board column) and pricing validity (a flag on the card). The styles
   below exist to keep those visually separate, and to keep unqualified value
   from reading like forecast. Semantic tokens only — brand red stays reserved
   for nav and primary actions. */

/* --- Report strip: four buckets, deliberately not blended into one number --- */
.est-pipeline { margin: 4px 0 14px; }
.est-pl-row { display: flex; gap: 10px; flex-wrap: wrap; }
.est-pl-cell {
  flex: 1 1 150px; min-width: 140px; text-align: left; cursor: default;
  background: var(--bg-surface); border: 1px solid var(--border-soft);
  border-radius: 10px; padding: 9px 12px; display: flex; flex-direction: column; gap: 1px;
  border-left: 3px solid var(--border-strong);
}
.est-pl-val { font-size: 17px; font-weight: 700; color: var(--text-heading); line-height: 1.2; }
.est-pl-label { font-size: 11.5px; color: var(--text-muted); }
.est-pl-count { font-size: 11px; color: var(--text-faint); }
/* Only the qualified bucket is styled as "good news". The rest are neutral or
   cautionary on purpose — they are real value, but they are not forecast. */
.est-pl-qualified { border-left-color: var(--semantic-green); }
.est-pl-hold      { border-left-color: var(--semantic-purple); }
.est-pl-unclass   { border-left-color: var(--semantic-amber); cursor: pointer; }
.est-pl-requal    { border-left-color: var(--semantic-amber); cursor: pointer; }
.est-pl-won       { border-left-color: var(--semantic-green); }
.est-pl-unclass:hover, .est-pl-requal:hover { background: #fffbeb; }
.est-pl-foot { font-size: 11.5px; color: var(--text-muted); margin-top: 6px; }
.est-pl-warns { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.est-pl-warn {
  font-size: 12px; font-weight: 600; cursor: pointer;
  background: #fffbeb; color: #92610a; border: 1px solid #fde8b8;
  border-radius: 999px; padding: 3px 11px;
}
.est-pl-warn:hover { background: #fef3c7; }
.est-pl-warn-hot { background: #fef2f2; color: #a4262c; border-color: #fbd5d5; }
.est-pl-warn-hot:hover { background: #fee2e2; }
.est-period-label { font-size: 13px; color: var(--text-muted); display: inline-flex; align-items: center; gap: 5px; }

/* --- Column kinds: parked value must not look like pipeline --- */
.est-col-hold    { background: #f7f5fd; border-color: #e4defa; }
.est-col-backlog { background: #fdfaf2; border-color: #f3e6c9; }
.est-col-note {
  font-size: 10.5px; color: var(--text-muted); padding: 5px 12px 0;
  font-style: italic; line-height: 1.35;
}

/* --- Card: next action is the loudest thing on it --- */
.est-card-next {
  margin-top: 7px; padding: 5px 8px; border-radius: 7px;
  background: #f1f5f9; border-left: 3px solid var(--border-strong);
  display: flex; flex-direction: column; gap: 2px;
}
.est-card-next-text { font-size: 12.5px; font-weight: 600; color: var(--text-body); line-height: 1.3; }
.est-card-due { font-size: 11px; font-weight: 700; color: var(--text-muted); }
.est-card-next.est-due-today   { background: #fffbeb; border-left-color: var(--semantic-amber); }
.est-card-next.est-due-today .est-card-due { color: #92610a; }
.est-card-next.est-due-overdue { background: #fef2f2; border-left-color: var(--semantic-rose); }
.est-card-next.est-due-overdue .est-card-due { color: #a4262c; }
/* An opportunity with no next step announces it rather than looking healthy. */
.est-card-next-missing {
  font-size: 12px; font-style: italic; color: #92610a;
  background: #fffbeb; border-left-color: var(--semantic-amber);
}
.est-card-overdue { border-color: #f6c9cb; }

.est-card-flags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
.est-price { font-size: 11px; font-weight: 600; border-radius: 999px; padding: 1px 8px; white-space: nowrap; }
.est-price-current { color: #146c43; background: #e7f5ec; }
.est-price-review  { color: #a4262c; background: #fbe0e1; }
.est-price-unknown { color: #5a6472; background: #eef0f3; }
.est-card-rev   { font-size: 11px; font-weight: 600; color: #6d28d9; background: #f3edfe; border-radius: 999px; padding: 1px 8px; }
.est-card-rev.est-due-overdue { color: #a4262c; background: #fbe0e1; }
.est-card-hold  { font-size: 11px; color: #6d28d9; background: #f3edfe; border-radius: 999px; padding: 1px 8px; }
.est-card-hold.est-due-overdue, .est-card-hold.est-due-today { color: #92610a; background: #fdf1d8; }
.est-card-triage { font-size: 11px; font-weight: 600; color: #92610a; background: #fdf1d8; border-radius: 999px; padding: 1px 8px; }
.est-card-heard { font-size: 11px; color: var(--text-faint); }
.est-card-owner-missing { color: #92610a; font-style: italic; }
.est-card-ver { font-size: 10px; font-weight: 700; color: #6d28d9; background: #f3edfe; border-radius: 4px; padding: 0 4px; margin-left: 4px; }

/* --- Next-actions queue --- */
.est-af-row { display: flex; gap: 6px; flex-wrap: wrap; margin: 10px 0 4px; }
.est-af {
  font-size: 12px; cursor: pointer; background: var(--bg-surface);
  border: 1px solid var(--border-soft); border-radius: 999px; padding: 4px 11px;
  color: var(--text-muted); display: inline-flex; align-items: center; gap: 6px;
}
.est-af:hover { border-color: var(--border-strong); }
.est-af.is-on { background: var(--brand-ink); color: #fff; border-color: var(--brand-ink); }
.est-af-n { font-weight: 700; font-size: 11px; opacity: .8; }
.est-af-tools { display: flex; align-items: center; gap: 14px; margin: 8px 0; }
.est-af-mine, .est-af-count { font-size: 12.5px; color: var(--text-muted); }
.est-af-mine { display: inline-flex; align-items: center; gap: 6px; }
.est-modal-actions { max-width: 1080px; }
.est-af-list { max-height: 58vh; overflow-y: auto; overflow-x: auto; }
.est-af-table { min-width: 860px; }
.est-af-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.est-af-table th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .03em;
  color: var(--text-muted); font-weight: 600; padding: 6px 8px;
  border-bottom: 1px solid var(--border-soft); position: sticky; top: 0; background: var(--bg-surface);
}
.est-af-table td { padding: 7px 8px; border-bottom: 1px solid #f1f4f8; vertical-align: top; }
.est-af-r { cursor: pointer; }
.est-af-r:hover { background: #f8fafc; }
/* A long next action must not spill into the due column — clamp it and keep
   the full text in the tooltip. */
.est-af-next { max-width: 280px; }
.est-af-clamp { display: block; max-width: 280px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.est-af-due { font-weight: 700; color: var(--text-muted); white-space: nowrap; }
.est-af-due.est-due-today { color: #92610a; }
.est-af-due.est-due-overdue { color: #a4262c; }
.est-af-missing { color: #92610a; font-style: italic; }
.est-af-ago { color: var(--text-faint); }

/* --- Detail drawer blocks --- */
.est-d-block {
  border: 1px solid var(--border-soft); border-radius: 10px;
  padding: 11px 13px; margin: 10px 0; background: var(--bg-surface);
}
.est-d-block-h {
  font-size: 12.5px; font-weight: 700; color: var(--text-heading);
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px;
}
.est-d-block-p { font-size: 12.5px; color: var(--text-body); margin: 0 0 8px; line-height: 1.45; }
.est-d-hint { font-size: 11px; color: var(--text-muted); margin: 6px 0 0; line-height: 1.4; }
.est-d-triage { border-left: 3px solid var(--semantic-amber); background: #fffbeb; }
.est-d-revision { border-left: 3px solid var(--semantic-purple); background: #faf8ff; }
.est-d-hold { border-left: 3px solid var(--semantic-purple); background: #f7f5fd; }
.est-d-next { border-left: 3px solid var(--action-blue); }
.est-d-pricing-review { border-left: 3px solid var(--semantic-rose); background: #fffafa; }
.est-d-pricing-unknown { border-left: 3px solid var(--border-strong); }
.est-d-pricing-current { border-left: 3px solid var(--semantic-green); }
.est-d-price-dates { display: flex; gap: 16px; flex-wrap: wrap; font-size: 12px; color: var(--text-muted); }
.est-d-price-actions { display: flex; gap: 8px; align-items: flex-end; flex-wrap: wrap; margin-top: 9px; }
.est-d-price-vt { font-size: 11.5px; color: var(--text-muted); display: flex; flex-direction: column; gap: 3px; }
.est-d-heard { font-size: 12px; color: var(--text-muted); margin-top: 4px; line-height: 1.45; }
.est-d-vlist { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }
.est-d-vlist li {
  display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap;
  font-size: 12px; color: var(--text-muted); padding: 4px 0; border-top: 1px solid #f1f4f8;
}
.est-d-vno { font-weight: 700; color: #6d28d9; }
.est-d-vamt { font-weight: 600; color: var(--text-body); }
.est-d-vreason { font-style: italic; }
.est-d-more > summary { font-size: 12.5px; font-weight: 600; color: var(--text-muted); cursor: pointer; padding: 6px 0; }
.est-d-more[open] > summary { margin-bottom: 4px; }

/* --- Classification modal --- */
.est-cl-options { display: flex; flex-direction: column; gap: 4px; }
.est-cl-opt {
  display: grid; grid-template-columns: auto 1fr; column-gap: 9px; align-items: start;
  padding: 9px 11px; border: 1px solid var(--border-soft); border-radius: 9px; cursor: pointer;
}
.est-cl-opt:hover { border-color: var(--border-strong); background: #f8fafc; }
.est-cl-opt:has(input:checked) { border-color: var(--action-blue); background: #f0fdfd; }
.est-cl-opt input { grid-row: 1 / span 2; margin-top: 3px; }
.est-cl-t { font-size: 13px; font-weight: 600; color: var(--text-heading); }
.est-cl-d { font-size: 12px; color: var(--text-muted); line-height: 1.4; }
.est-cl-fields {
  display: flex; flex-direction: column; gap: 9px;
  padding: 11px 13px 13px 34px; margin: -2px 0 6px;
  border-left: 2px solid var(--action-blue); background: #f8fafc; border-radius: 0 8px 8px 0;
}
.est-cl-fields[hidden] { display: none; }
.est-cl-fields label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--text-muted); font-weight: 600; }
.est-cl-fields input, .est-cl-fields textarea {
  font: inherit; font-size: 14px; font-weight: 400; color: var(--text-body);
  padding: 8px 10px; border: 1px solid #d5dae1; border-radius: 8px; background: #fff; width: 100%;
}
.est-cl-fields textarea { resize: vertical; }
.est-cl-fields input:focus, .est-cl-fields textarea:focus {
  outline: none; border-color: #2563eb; box-shadow: 0 0 0 3px rgba(37,99,235,.12);
}
.est-cl-fields .est-form-row { display: flex; gap: 10px; }
.est-cl-fields .est-form-row > label { flex: 1; }

/* --- Timeline note kinds: who moved matters --- */
.est-note-tag { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 2px; }
.est-note-customer { border-left: 3px solid var(--semantic-green); padding-left: 8px; }
.est-note-customer .est-note-tag { color: #146c43; }
.est-note-outbound { border-left: 3px solid var(--border-strong); padding-left: 8px; }
.est-note-outbound .est-note-tag { color: var(--text-muted); }
.est-note-system .est-note-tag { color: var(--text-faint); }
/* Adding the note-kind selector turns the composer into a stacked block; the
   original single-row flex collapsed the textarea to zero width. */
.est-note-form { flex-direction: column; align-items: stretch; gap: 6px; }
.est-note-form textarea { width: 100%; }
.est-note-kindrow { display: flex; gap: 8px; align-items: center; }
.est-note-kind { flex: 1; }
.est-note-kind select { width: 100%; font: inherit; font-size: 12.5px; padding: 6px 8px; border: 1px solid #d5dae1; border-radius: 8px; background: #fff; }
.est-note-form .est-d-hint { margin: 0; }

@media (max-width: 720px) {
  .est-pl-cell { flex: 1 1 100%; }
  .est-af-list { max-height: none; }
}

/* --- Automatic customer follow-ups (AUTO-FOLLOW-UP) ---------------------
   This feature mails customers with no human reviewing each send, so its UI
   leans deliberately sober: the warnings are loud, the "on" state is stated
   plainly, and nothing about it is styled as a celebratory success. */
.est-af-warn {
  background: #fffbeb; border: 1px solid #fde8b8; border-radius: 9px;
  padding: 9px 12px; margin: 4px 0 12px; font-size: 12.5px; color: #92610a;
  display: flex; flex-direction: column; gap: 4px; line-height: 1.45;
}
.est-af-master {
  display: flex; align-items: center; gap: 9px; padding: 11px 13px;
  border: 1px solid var(--border-strong); border-radius: 10px; cursor: pointer; font-size: 14px;
}
.est-af-master:has(input:checked) { border-color: var(--semantic-amber); background: #fffbeb; }
.est-af-facts {
  display: flex; gap: 18px; flex-wrap: wrap; margin: 10px 0;
  font-size: 12.5px; color: var(--text-muted);
}
.est-af-rules { margin: 6px 0 12px; }
.est-af-rules p { font-size: 12.5px; color: var(--text-muted); line-height: 1.5; margin: 0 0 6px; }
.est-af-rules b { color: var(--text-body); }
.est-af-h4 { font-size: 12.5px; margin: 14px 0 6px; color: var(--text-heading); }
.est-af-status-sent { color: #146c43; font-weight: 600; }
.est-af-status-failed { color: #a4262c; font-weight: 600; }
.est-af-status-skipped_not_configured,
.est-af-status-suppressed_test_site { color: var(--text-muted); font-style: italic; }

.est-d-autofollow { border-left: 3px solid var(--semantic-amber); }
.est-af-pill { font-size: 11px; font-weight: 700; border-radius: 999px; padding: 1px 9px; }
.est-af-pill-on { color: #92610a; background: #fdf1d8; }
.est-af-pill-off { color: var(--text-muted); background: #eef0f3; }
.est-af-locked { font-size: 12px; color: #a4262c; background: #fef2f2; border: 1px solid #fbd5d5; border-radius: 8px; padding: 7px 10px; line-height: 1.45; }
.est-af-bad { color: #a4262c; }
.est-af-testnote { font-size: 11.5px; color: var(--text-muted); margin: 6px 0 0; line-height: 1.45; }

/* ---------- TICKETS (Phase 2) ---------- */
.tickets-list { display: flex; flex-direction: column; gap: 8px; }
.tickets-loading, .tickets-empty, .tickets-error, .ticket-thread-empty {
  padding: 22px; text-align: center; color: #56606b; font-size: 14px;
}
.tickets-error { color: #c5221f; }
.ticket-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  width: 100%; text-align: left; padding: 12px 14px; cursor: pointer;
  background: #fff; border: 1px solid #e1e4e8; border-radius: var(--r-md);
  font: inherit; color: inherit;
}
.ticket-row:hover { background: #f8f9fa; border-color: #d0d4da; }
.ticket-row-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ticket-row-title {
  font-weight: 600; font-size: 14px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ticket-row-meta { font-size: 12px; color: #56606b; }
.ticket-msgs::before { content: '· '; }
.ticket-row-tags { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }

/* Status and severity pills. Status carries the colour; severity only shouts
   when it is worse than normal, so a queue of ordinary tickets stays calm. */
.ticket-status, .ticket-sev, .ticket-cat, .ticket-dup {
  display: inline-block; padding: 2px 9px; border-radius: 999px;
  font-size: 11px; font-weight: 600; white-space: nowrap;
}
.ticket-status-open          { background: #fdecea; color: #b3261e; }
.ticket-status-investigating { background: #fff4e5; color: #8a5300; }
.ticket-status-fixed         { background: #e6f4ea; color: #137333; }
.ticket-status-closed        { background: #eef0f3; color: #56606b; }
.ticket-status-wont_fix      { background: #eef0f3; color: #56606b; }
.ticket-sev-blocker { background: #b3261e; color: #fff; }
.ticket-sev-high    { background: #fdecea; color: #b3261e; }
.ticket-sev-low     { background: #eef0f3; color: #56606b; }
.ticket-cat { background: #eef2ff; color: #3730a3; font-weight: 500; }
.ticket-dup { background: #eef0f3; color: #56606b; font-weight: 500; }

/* File-a-ticket form */
.modal-content-narrow { width: min(560px, 92vw); }
.ticket-field { display: block; margin-bottom: 14px; }
.ticket-field > span { display: block; font-size: 12px; font-weight: 600; color: #56606b; margin-bottom: 5px; }
.ticket-field > span em { font-weight: 400; font-style: normal; color: #8a929b; }
.ticket-field input[type="text"], .ticket-field textarea, .ticket-field select {
  width: 100%; box-sizing: border-box; padding: 9px 11px; font: inherit; font-size: 14px;
  border: 1px solid #d0d4da; border-radius: 8px; background: #fff;
}
.ticket-field textarea { resize: vertical; }
.ticket-field-row { display: flex; gap: 12px; }
.ticket-field-row .ticket-field { flex: 1; }
.ticket-context-note {
  margin: 0 0 14px; font-size: 12px; color: #56606b;
  background: #f8f9fa; border: 1px solid #e1e4e8; border-radius: var(--r-md); padding: 9px 11px;
}

/* Ticket detail */
.ticket-detail-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin-bottom: 12px; }
.ticket-meta-by { font-size: 12px; color: #56606b; }
.ticket-detail-body {
  white-space: pre-wrap; font-size: 14px; line-height: 1.5;
  background: #f8f9fa; border: 1px solid #e1e4e8; border-radius: var(--r-md);
  padding: 11px 13px; margin-bottom: 12px;
}
.ticket-context { margin-bottom: 14px; font-size: 12px; }
.ticket-context summary { cursor: pointer; color: #56606b; font-weight: 600; }
.ticket-context > div { padding: 9px 0 0; color: #56606b; display: flex; flex-direction: column; gap: 4px; }
.ticket-context code { word-break: break-all; background: #f1f3f5; padding: 1px 5px; border-radius: 4px; }
.ticket-admin-controls { display: flex; gap: 14px; margin-bottom: 16px; }
.ticket-admin-controls label { font-size: 12px; font-weight: 600; color: #56606b; }
.ticket-admin-controls select {
  display: block; margin-top: 4px; padding: 7px 9px; font: inherit; font-size: 13px;
  border: 1px solid #d0d4da; border-radius: 8px; background: #fff;
}
.ticket-thread-heading { margin: 0 0 9px; font-size: 13px; text-transform: uppercase; letter-spacing: .04em; color: #56606b; }
.ticket-thread { max-height: 300px; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; margin-bottom: 12px; }
.ticket-msg { display: flex; gap: 9px; }
.ticket-msg-dot { width: 9px; height: 9px; border-radius: 50%; margin-top: 5px; flex-shrink: 0; }
.ticket-msg-head { font-size: 12px; font-weight: 600; }
.ticket-msg-head span { font-weight: 400; color: #8a929b; margin-left: 5px; }
.ticket-msg-body { font-size: 14px; white-space: pre-wrap; line-height: 1.45; }
.ticket-reply { display: flex; gap: 8px; align-items: flex-end; }
.ticket-reply textarea {
  flex: 1; padding: 9px 11px; font: inherit; font-size: 14px; resize: vertical;
  border: 1px solid #d0d4da; border-radius: 8px;
}
@media (max-width: 640px) {
  .ticket-row { flex-direction: column; align-items: flex-start; gap: 8px; }
  .ticket-field-row { flex-direction: column; gap: 0; }
}

/* TICKETS Phase 3: AI triage. Visually distinct from anything a person wrote —
   the tag is not decoration, it is the disclosure. */
.ticket-ai-summary {
  display: flex; align-items: baseline; gap: 9px; margin-bottom: 12px;
  padding: 10px 12px; font-size: 13px; line-height: 1.45;
  background: #f5f3ff; border: 1px solid #ddd6fe; border-radius: var(--r-md); color: #4c1d95;
}
.ticket-ai-tag {
  flex-shrink: 0; font-size: 10px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: #6d28d9; background: #ede9fe;
  padding: 2px 7px; border-radius: 999px;
}
.ticket-dup-link { cursor: pointer; border: none; font: inherit; }
.ticket-dup-link:hover { background: #dfe3e8; }
.ticket-retriage {
  align-self: flex-end; padding: 7px 12px; font: inherit; font-size: 12px; font-weight: 600;
  color: #6d28d9; background: #f5f3ff; border: 1px solid #ddd6fe;
  border-radius: 8px; cursor: pointer;
}
.ticket-retriage:hover:not(:disabled) { background: #ede9fe; }
.ticket-retriage:disabled { opacity: .6; cursor: default; }

/* ICONS (2026-09-12): inline SVG line icons (see the ICONS map at the top of
   app.js). Sized by the surrounding text, colored by currentColor. */
.ic { width: 1.05em; height: 1.05em; vertical-align: -0.16em; flex: none; }

/* DASH-LIVE-JOBS: photo-count badge on the job cards in the live rail */
.jshot-live-item { position: relative; }
.jshot-live-count {
  position: absolute; top: 6px; right: 6px;
  background: rgba(15, 23, 42, .82); color: #fff;
  font-size: 11px; font-weight: 700; border-radius: 999px; padding: 2px 8px;
}

/* ─── JOB→EST: move-to-estimates button + in-tracker banner ──────────────── */
/* Footer "Move to estimates" — a calm, positive secondary action next to Delete. */
#to-estimate-btn {
  background: #eef6fc; color: #1a56c4; border: 1px solid #d4e4f7;
  border-radius: 8px; padding: 8px 14px; font-size: 14px; font-weight: 600;
  cursor: pointer;
}
#to-estimate-btn:hover { background: #e2eefb; border-color: #b9d5f2; }

/* Banner shown at the top of a job that's already in the estimate tracker. */
.job-estimate-banner {
  background: #eef6fc; border: 1px solid #d4e4f7; border-radius: 12px;
  padding: 11px 14px; margin-bottom: 16px;
}
.job-est-banner-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap;
}
.job-est-banner-text { display: flex; flex-direction: column; gap: 2px; }
.job-est-banner-text strong { font-size: 14px; font-weight: 700; color: #12408a; }
.job-est-banner-text span { font-size: 13px; color: #1e3a5f; }
.job-est-banner-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.job-est-banner-actions button {
  border-radius: 8px; padding: 7px 12px; font-size: 13px; font-weight: 600; cursor: pointer;
  border: 1px solid #b9d5f2; background: #fff; color: #1a56c4;
}
.job-est-banner-actions button:hover { background: #f3f8fe; }
#job-est-return { color: var(--text-muted); border-color: var(--border-strong); }
#job-est-return:hover { background: var(--bg-page); }

/* Back-link in the estimate detail header ("From job #12 →"). */
.est-d-joblink {
  margin-top: 4px; padding: 0; border: none; background: none;
  color: #1a56c4; font-size: 12px; font-weight: 600; cursor: pointer;
}
.est-d-joblink:hover { text-decoration: underline; }

/* ---------- Calendar Agenda view (NAV-CONSOLIDATION 2a) ---------- */
/* The former Install tab, rendered on the calendar. It reuses .installs-list
   and .install-row wholesale — those styles moved with the markup and are
   still named for their origin rather than renamed, so the diff stays a
   relocation rather than a restyle. */
.cal-agenda { margin-top: 12px; }
.agenda-head {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 10px; margin-bottom: 12px;
}
.agenda-sub { margin: 0; font-size: 14px; color: #56606b; }
.agenda-filters { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.agenda-filters select {
  padding: 7px 10px; font: inherit; font-size: 13px;
  border: 1px solid #d0d4da; border-radius: 8px; background: #fff;
}
.agenda-show-done {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; color: #56606b; white-space: nowrap;
}
@media (max-width: 640px) {
  .agenda-head { flex-direction: column; align-items: stretch; }
  .agenda-filters select { flex: 1; }
}

/* Time off in the agenda (NAV-CONSOLIDATION 2b). Same row shape as a job so
   the list reads as one list; only the verb chip distinguishes them. */
.install-row-verb.verb-timeoff { background: #ede9fe; color: #5b21b6; }
.install-row.is-timeoff { background: #fcfbff; }
.install-row.is-timeoff:hover { background: #f5f3ff; }

/* ===========================================================================
   PERMITS — the "In Permit" panel in the job modal.

   The one thing this has to get right: the headline is the panel. A permit is
   a thing that sits still for weeks, so the failure is never a confusing
   screen, it is a screen nobody has a reason to open. Everything below the
   headline is reference material and is styled to recede.

   Three tones only. A five-step severity scale nobody can read at a glance is
   decoration, and this panel is competing with six other sections in the same
   modal.
   =========================================================================== */
.permit-section {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--border-soft, #e1e4e8);
}
.permit-card {
  border: 1px solid var(--border-soft, #e2e8f0);
  border-left: 4px solid var(--border-strong, #cbd5e1);
  border-radius: var(--r-md, 8px);
  padding: 12px 14px;
  background: var(--bg-surface, #fff);
}
.permit-card + .permit-card { margin-top: 10px; }
/* Somebody should pick up the phone today. */
.permit-card.is-chase   { border-left-color: var(--semantic-rose, #f43f5e); background: #fff7f8; }
/* Ours, but not yet late. */
.permit-card.is-ours    { border-left-color: var(--semantic-amber, #f59e0b); }
/* Waiting on somebody outside this building — real, but not actionable now. */
.permit-card.is-waiting { border-left-color: var(--semantic-purple, #8b5cf6); }

.permit-headline {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.permit-headline-main { flex: 1 1 260px; min-width: 0; }
.permit-headline-text {
  font-size: var(--fs-md, 14px);
  font-weight: 600;
  color: var(--text-heading, #0f172a);
  line-height: 1.35;
}
.permit-headline-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 4px;
  font-size: var(--fs-xs, 11px);
  color: var(--text-muted, #64748b);
}
.permit-ball { font-weight: 600; }
.is-chase .permit-clock strong { color: var(--semantic-rose, #f43f5e); }
.permit-number { font-variant-numeric: tabular-nums; }
.permit-headline-controls { display: flex; gap: 6px; flex-wrap: wrap; }
.permit-headline-controls select {
  font-size: var(--fs-sm, 13px);
  padding: 4px 6px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
  background: var(--bg-surface, #fff);
  color: var(--text-body, #1f2937);
  max-width: 180px;
}
/* The unincorporated-pocket warning. A "Winchester, CA" address may well file
   with the county, and finding that out at the counter costs a morning. */
.permit-note-warn {
  margin-top: 8px;
  padding: 6px 8px;
  font-size: var(--fs-xs, 11px);
  color: #92400e;
  background: #fffbeb;
  border: 1px solid #fde68a;
  border-radius: var(--r-sm, 4px);
}

.permit-conditions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 10px 0;
  padding: 8px 0;
  border-top: 1px dashed var(--border-soft, #eef1f4);
  border-bottom: 1px dashed var(--border-soft, #eef1f4);
  font-size: var(--fs-sm, 13px);
}
.permit-conditions-label { color: var(--text-muted, #64748b); }
.permit-condition {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  color: var(--text-body, #1f2937);
}
.permit-condition input { margin: 0; }

/* RESEARCH DRAFT. Deliberately does not look like the packet below it. The
   dashed edge and amber heading say "provisional" before anybody reads a word,
   because the failure mode of this feature is a list of suggestions being
   mistaken for a list of confirmed requirements. */
.permit-research:empty { display: none; }
.permit-research {
  margin: 8px 0;
  padding: 10px 12px;
  border: 1px dashed var(--semantic-amber, #f59e0b);
  border-radius: var(--radius-md, 8px);
  background: var(--bg-page, #f8fafc);
}
.permit-research-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
}
.permit-research-title {
  font-size: var(--fs-sm, 13px); font-weight: 600;
  color: var(--semantic-amber, #f59e0b);
}
.permit-research-summary, .permit-research-notes {
  margin: 6px 0; font-size: var(--fs-sm, 13px); color: var(--text-muted, #64748b);
}
.permit-research-items { display: flex; flex-direction: column; gap: 2px; margin: 8px 0; }
.permit-research-item {
  display: grid; grid-template-columns: auto 1fr auto; gap: 6px;
  align-items: baseline; padding: 3px 0; font-size: var(--fs-sm, 13px);
}
.permit-research-who {
  font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b);
  text-transform: lowercase;
}
/* Detail drops to its own row under the label rather than squeezing it. */
.permit-research-detail {
  grid-column: 2 / -1;
  font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b);
}
.permit-research-actions { display: flex; gap: 10px; align-items: center; }
/* The one thing that must not be scrolled past: what it could not work out. */
.permit-research-unknowns {
  margin: 8px 0 4px; padding: 6px 10px;
  border-left: 3px solid var(--semantic-amber, #f59e0b);
  font-size: var(--fs-sm, 13px);
}
.permit-research-unknowns-title { font-weight: 600; color: var(--text-heading, #0f172a); }
.permit-research-unknowns ul { margin: 4px 0 0; padding-left: 18px; color: var(--text-muted, #64748b); }
.permit-research-sources, .permit-research-nosource {
  margin-top: 8px; font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b);
  display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline;
}
.permit-research-sources a { color: var(--text-link, #2563eb); text-decoration: underline; }
.permit-research-nosource { color: var(--semantic-amber, #f59e0b); }

/* BUSINESS LICENCES. A table of five columns that has to stay scannable at a
   glance — the whole point is spotting the expired row without reading. */
.licence-grid { display: flex; flex-direction: column; margin: 8px 0; }
.licence-row {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1.4fr) minmax(0, 1fr) auto auto;
  gap: 10px; align-items: baseline;
  padding: 5px 8px; font-size: var(--fs-sm, 13px);
  border-left: 3px solid transparent;
  border-bottom: 1px solid var(--border-soft, #f1f5f9);
}
.licence-row.is-head {
  font-size: var(--fs-xs, 11px); font-weight: 600; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-muted, #64748b);
  border-bottom: 1px solid var(--border-soft, #e2e8f0);
}
.licence-city { font-weight: 600; }
.licence-number { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--fs-xs, 11px); }
.licence-when { color: var(--text-muted, #64748b); }
/* The open-permit count is what makes an expired row urgent rather than untidy,
   so it is the one number that gets weight. */
.licence-permits { font-weight: 700; text-align: right; }
.licence-row.is-expired { border-left-color: var(--semantic-rose, #f43f5e); }
.licence-row.is-expired .licence-when { color: var(--semantic-rose, #f43f5e); font-weight: 600; }
.licence-row.is-expiring { border-left-color: var(--semantic-amber, #f59e0b); }
.licence-row.is-expiring .licence-when { color: var(--semantic-amber, #f59e0b); font-weight: 600; }
.licence-row.is-unknown .licence-when { color: var(--semantic-amber, #f59e0b); font-style: italic; }
.licence-add { margin-top: 6px; }
.licence-suggest-lapsed { color: var(--semantic-rose, #f43f5e); font-weight: 600; }
.licence-editor {
  margin-top: 10px; padding: 10px 12px;
  border: 1px solid var(--border-soft, #e2e8f0); border-radius: var(--radius-md, 8px);
  background: var(--bg-page, #f8fafc);
}
.licence-editor-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px;
}
.licence-editor-grid label {
  display: flex; flex-direction: column; gap: 3px;
  font-size: var(--fs-xs, 11px); font-weight: 600; color: var(--text-muted, #64748b);
}
.licence-editor-grid .licence-f-wide { grid-column: 1 / -1; }
.licence-editor-grid input, .licence-editor-grid select {
  font-size: var(--fs-sm, 13px); padding: 5px 7px; font-weight: 400;
  border: 1px solid var(--border-soft, #e2e8f0); border-radius: var(--radius-sm, 6px);
  background: var(--bg-card, #fff); color: var(--text-body, #334155);
}
.licence-editor-actions { display: flex; gap: 12px; margin-top: 10px; }
@media (max-width: 560px) {
  /* Number and permit count fall away first; city and status are the row. */
  .licence-row { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) auto; }
  .licence-number, .licence-row.is-head span:nth-child(2) { display: none; }
}

/* SHEET IMPORT. The preview table is the safety feature, so it gets room to
   be read rather than being squeezed under the textarea. */
.permit-import-body { padding: 8px 2px 4px; }
#permit-import-text {
  width: 100%; box-sizing: border-box; resize: vertical;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--fs-xs, 11px); line-height: 1.5;
  padding: 8px; border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--radius-md, 8px); background: var(--bg-card, #fff);
  color: var(--text-body, #334155);
}
.permit-import-actions { display: flex; gap: 12px; align-items: center; margin: 8px 0; }
.permit-import-summary { font-size: var(--fs-sm, 13px); font-weight: 600; margin: 8px 0 6px; }
/* Six columns do not fit a phone. The table scrolls inside this box rather
   than widening the Permits tab, which would put a horizontal scrollbar on the
   whole page to show one date column. */
.permit-import-scroll { overflow-x: auto; margin-bottom: 4px; }
.permit-import-table { width: 100%; min-width: 520px; border-collapse: collapse; font-size: var(--fs-xs, 11px); }
.permit-import-table th {
  text-align: left; font-weight: 600; color: var(--text-muted, #64748b);
  border-bottom: 1px solid var(--border-soft, #e2e8f0); padding: 4px 6px;
}
.permit-import-table td { padding: 3px 6px; border-bottom: 1px solid var(--border-soft, #f1f5f9); }
/* A row that changes an existing permit is marked, because overwriting one is a
   different act from filling in a blank. */
.permit-import-table tr.is-update td:first-child { border-left: 3px solid var(--semantic-amber, #f59e0b); }
.permit-import-table tr.is-create td:first-child { border-left: 3px solid transparent; }
.permit-import-bad {
  margin-top: 10px; padding: 8px 10px; font-size: var(--fs-sm, 13px);
  border-left: 3px solid var(--semantic-rose, #f43f5e); color: var(--text-body, #334155);
}
.permit-import-bad ul { margin: 4px 0 0; padding-left: 18px; color: var(--text-muted, #64748b); }

.permit-packet { display: flex; flex-direction: column; gap: 2px; }
.permit-item {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  border-bottom: 1px dashed var(--border-soft, #eef1f4);
  font-size: var(--fs-sm, 13px);
}
.permit-item:last-of-type { border-bottom: none; }
.permit-item-status {
  font-size: var(--fs-xs, 11px);
  padding: 3px 4px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
  background: var(--bg-surface, #fff);
  color: var(--text-body, #1f2937);
}
.permit-item-main { min-width: 0; }
.permit-item-label { color: var(--text-body, #1f2937); }
.permit-item-detail {
  font-size: var(--fs-xs, 11px);
  color: var(--text-muted, #64748b);
  margin-top: 1px;
}
.permit-item-optional { color: var(--text-faint, #94a3b8); }
.permit-item.is-done .permit-item-label { color: var(--text-muted, #64748b); }
/* Struck, not hidden — an item somebody decided doesn't apply is a decision,
   and it should stay visible as one. */
.permit-item.is-na .permit-item-label { text-decoration: line-through; color: var(--text-faint, #94a3b8); }
.permit-item.is-na .permit-item-detail { display: none; }
.permit-item-who {
  font-size: var(--fs-xs, 11px);
  padding: 2px 6px;
  border-radius: 999px;
  white-space: nowrap;
}
.permit-who-shop     { background: #eef2ff; color: #4338ca; }
.permit-who-customer { background: #ecfdf5; color: #047857; }
.permit-who-landlord { background: #fef3c7; color: #92400e; }
.permit-item-remove {
  background: none;
  border: none;
  color: var(--text-faint, #94a3b8);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  padding: 0 2px;
}
.permit-item-remove:hover { color: var(--semantic-rose, #f43f5e); }

.permit-add-item, .permit-add-note {
  display: flex;
  gap: 6px;
  margin-top: 8px;
  flex-wrap: wrap;
}
.permit-add-item input, .permit-add-note input {
  flex: 1 1 180px;
  min-width: 0;
  font-size: var(--fs-sm, 13px);
  padding: 5px 8px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
}
.permit-add-item select {
  font-size: var(--fs-sm, 13px);
  padding: 5px 6px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
}

.permit-details, .permit-timeline-wrap { margin-top: 10px; }
.permit-details > summary, .permit-timeline-wrap > summary {
  font-size: var(--fs-sm, 13px);
  color: var(--text-muted, #64748b);
  cursor: pointer;
  padding: 4px 0;
}
.permit-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 8px;
  padding: 8px 0;
}
.permit-field { display: flex; flex-direction: column; gap: 2px; }
.permit-field span {
  font-size: var(--fs-xs, 11px);
  color: var(--text-muted, #64748b);
}
.permit-field input {
  font-size: var(--fs-sm, 13px);
  padding: 5px 8px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
  min-width: 0;
}
.permit-timeline { display: flex; flex-direction: column; gap: 2px; padding: 4px 0; }
.permit-event {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  gap: 8px;
  padding: 4px 0;
  font-size: var(--fs-xs, 11px);
  border-bottom: 1px dashed var(--border-soft, #eef1f4);
}
.permit-event:last-child { border-bottom: none; }
.permit-event-when { color: var(--text-faint, #94a3b8); }
.permit-event-what { color: var(--text-body, #1f2937); }
.permit-event-who { color: var(--text-muted, #64748b); white-space: nowrap; }

@media (max-width: 640px) {
  .permit-headline-controls { width: 100%; }
  .permit-headline-controls select { flex: 1 1 auto; max-width: none; }
  .permit-item { grid-template-columns: auto 1fr auto; }
  .permit-item-remove { grid-column: 3; }
  .permit-item-who { grid-column: 2; justify-self: start; }
}

/* The document that satisfies a packet line. Small and quiet — the label is
   what you read down the list; the file is what you reach for once. */
.permit-item-file {
  margin-top: 3px;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-xs, 11px);
}
.permit-item-file a { color: var(--action-blue-dark, #12b6b8); word-break: break-all; }
.permit-item-file select {
  font-size: var(--fs-xs, 11px);
  padding: 2px 4px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
  background: var(--bg-surface, #fff);
  color: var(--text-muted, #64748b);
  max-width: 220px;
}
.permit-item-unlink {
  background: none;
  border: none;
  padding: 0;
  color: var(--text-faint, #94a3b8);
  cursor: pointer;
  font-size: var(--fs-xs, 11px);
  text-decoration: underline;
}
.permit-item-unlink:hover { color: var(--semantic-rose, #f43f5e); }
.permit-item.is-na .permit-item-file { display: none; }

/* ===========================================================================
   PERMITS — the chase queue (Permits tab).

   Grouped by whose ball it is, ours first. The visual weight follows that:
   the "On us" group reads as work, the city group reads as a watch list. Same
   three tones as the job-modal panel so a permit looks like itself wherever
   you meet it.
   =========================================================================== */
.permit-queue { display: flex; flex-direction: column; gap: 22px; padding-bottom: 40px; }

.permit-group-header {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 8px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border-soft, #e2e8f0);
}
.permit-group-header h3 {
  margin: 0;
  font-size: var(--fs-lg, 18px);
  color: var(--text-heading, #0f172a);
}
.permit-group-count {
  font-size: var(--fs-xs, 11px);
  font-weight: 600;
  color: var(--text-muted, #64748b);
  background: var(--bg-page, #f8fafc);
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: 999px;
  padding: 1px 7px;
  vertical-align: middle;
}
.permit-group-blurb { font-size: var(--fs-sm, 13px); color: var(--text-muted, #64748b); }
/* The group that is actually work gets the emphasis. */
.permit-group[data-ball="shop"] .permit-group-header h3 { color: var(--brand-ink, #1f2937); }
.permit-group[data-ball="settled"] { opacity: 0.72; }
/* NEEDS A CITY: the same amber as the inline "No city set" marker on a row, so
   the group and the thing it collects read as one signal rather than two. Only
   the heading is tinted — the rows keep their own border, because a permit that
   needs a city can also be one that needs chasing and that must still show. */
.permit-group[data-ball="unassigned"] .permit-group-header h3 { color: var(--semantic-amber, #f59e0b); }

.permit-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 14px;
  padding: 10px 14px;
  margin-bottom: 6px;
  background: var(--bg-surface, #fff);
  border: 1px solid var(--border-soft, #e2e8f0);
  border-left: 4px solid var(--border-strong, #cbd5e1);
  border-radius: var(--r-md, 8px);
  box-shadow: var(--shadow-sm, 0 1px 2px rgba(15, 23, 42, 0.04));
}
.permit-row.is-chase   { border-left-color: var(--semantic-rose, #f43f5e); }
.permit-row.is-ours    { border-left-color: var(--semantic-amber, #f59e0b); }
.permit-row.is-waiting { border-left-color: var(--semantic-purple, #8b5cf6); }

.permit-row-main { min-width: 0; }
.permit-row-top {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.permit-row-company {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: var(--fs-md, 14px);
  font-weight: 600;
  color: var(--text-heading, #0f172a);
  cursor: pointer;
  text-align: left;
}
.permit-row-company:hover { color: var(--action-blue-dark, #12b6b8); text-decoration: underline; }
.permit-row-invoice, .permit-row-jur, .permit-row-num {
  font-size: var(--fs-xs, 11px);
  color: var(--text-muted, #64748b);
}
.permit-row-num { font-variant-numeric: tabular-nums; }
/* A permit with no jurisdiction can't be chased properly — say so rather than
   rendering an empty gap where the city should be. */
.permit-row-jur.is-missing { color: var(--semantic-amber, #f59e0b); font-weight: 600; }
.permit-row-headline {
  font-size: var(--fs-sm, 13px);
  color: var(--text-body, #1f2937);
  margin-top: 2px;
}

.permit-row-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
  font-size: var(--fs-xs, 11px);
  color: var(--text-muted, #64748b);
  white-space: nowrap;
}
.permit-row-over {
  font-weight: 700;
  color: var(--semantic-rose, #f43f5e);
  background: #fff1f2;
  border-radius: 999px;
  padding: 2px 7px;
}
/* The consequence: an install already on the calendar that this is holding up. */
.permit-row-holding {
  color: var(--semantic-purple, #8b5cf6);
  background: #f5f3ff;
  border-radius: 999px;
  padding: 2px 7px;
}

.permit-row-actions { display: flex; align-items: center; gap: 6px; }
.permit-row-stage {
  font-size: var(--fs-sm, 13px);
  padding: 5px 6px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
  background: var(--bg-surface, #fff);
  color: var(--text-body, #1f2937);
  max-width: 160px;
}
.permit-row-note-btn, .permit-row-note-save {
  font-size: var(--fs-xs, 11px);
  padding: 5px 8px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
  background: var(--bg-surface, #fff);
  color: var(--text-muted, #64748b);
  cursor: pointer;
  white-space: nowrap;
}
.permit-row-note-btn:hover, .permit-row-note-save:hover { color: var(--text-body, #1f2937); }
.permit-row-note {
  grid-column: 1 / -1;
  display: flex;
  gap: 6px;
  padding-top: 8px;
  border-top: 1px dashed var(--border-soft, #eef1f4);
}
.permit-row-note input {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--fs-sm, 13px);
  padding: 5px 8px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
}

/* The sidebar count of permits needing a chase. Counts chases, not open
   permits — a number that never drops is a number people stop seeing. */
.sidebar-badge {
  margin-left: auto;
  font-size: var(--fs-xs, 11px);
  font-weight: 700;
  min-width: 18px;
  text-align: center;
  color: #fff;
  background: var(--semantic-rose, #f43f5e);
  border-radius: 999px;
  padding: 1px 6px;
}

@media (max-width: 860px) {
  .permit-row { grid-template-columns: 1fr; gap: 8px; }
  .permit-row-meta { justify-content: flex-start; }
  .permit-row-actions { flex-wrap: wrap; }
  .permit-row-stage { flex: 1 1 auto; max-width: none; }
}

/* ===========================================================================
   PERMITS — the submittal package.

   "Very few offices take paper" (Mark, 2026-09-13), so this is not a print
   block: it produces the files a portal upload or an email needs. The line
   that earns its place is the one saying what is NOT in the package — a
   submittal that silently omits the structural calcs bounces, and the bounce
   costs a plan-check cycle.
   =========================================================================== */
.permit-submittal {
  margin-top: 10px;
  padding: 10px 12px;
  background: var(--bg-page, #f8fafc);
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-md, 8px);
}
.permit-submittal-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.permit-submittal-title {
  font-size: var(--fs-sm, 13px);
  font-weight: 600;
  color: var(--text-heading, #0f172a);
}
.permit-submittal-state { font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b); }
.permit-submittal-state.is-complete { color: #047857; font-weight: 600; }
.permit-submittal-state.is-partial { color: var(--semantic-amber, #f59e0b); font-weight: 600; }

.permit-submittal-list {
  margin: 8px 0 0;
  padding-left: 20px;
  font-size: var(--fs-xs, 11px);
  color: var(--text-body, #1f2937);
}
.permit-submittal-list li { margin-bottom: 2px; }
.permit-submittal-list code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--bg-surface, #fff);
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: 3px;
  padding: 0 4px;
}
/* The original name, kept visible so nobody wonders whether the right file
   went in — renaming silently would be its own small betrayal. */
.permit-submittal-was { color: var(--text-faint, #94a3b8); }

.permit-submittal-missing {
  margin-top: 8px;
  padding: 8px 10px;
  background: #fffbeb;
  border: 1px solid #fde68a;
  border-radius: var(--r-sm, 4px);
  font-size: var(--fs-xs, 11px);
  color: #92400e;
}
.permit-submittal-missing ul { margin: 4px 0 0; padding-left: 18px; }
.permit-submittal-missing em { color: #b45309; }

.permit-submittal-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 10px;
}
.permit-submittal-dl {
  font-size: var(--fs-sm, 13px);
  font-weight: 600;
  padding: 6px 12px;
  border-radius: var(--r-sm, 4px);
  background: var(--action-blue, #16c7c9);
  color: #fff;
  text-decoration: none;
  white-space: nowrap;
}
.permit-submittal-dl:hover { background: var(--action-blue-dark, #12b6b8); }
.permit-submittal-dl.is-disabled {
  background: var(--border-soft, #e2e8f0);
  color: var(--text-faint, #94a3b8);
  pointer-events: none;
}
.permit-transmittal-wrap { margin-top: 8px; }
.permit-transmittal-wrap > summary {
  font-size: var(--fs-xs, 11px);
  color: var(--text-muted, #64748b);
  cursor: pointer;
}
.permit-transmittal {
  margin: 6px 0 0;
  padding: 10px;
  background: var(--bg-surface, #fff);
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--fs-xs, 11px);
  color: var(--text-body, #1f2937);
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 320px;
  overflow-y: auto;
}

/* ===========================================================================
   PERMITS — the clock where people already look.

   A kanban card in the "In Permit" column used to carry a company name and
   nothing else. One line now: stage, city, how long, whose ball. The sentence
   lives in the title attribute — on a board of twenty cards a sentence each is
   wallpaper, but it is worth having a hover away.
   =========================================================================== */
.kanban-card-permit {
  margin-top: 4px;
  padding: 2px 6px;
  font-size: 10px;
  line-height: 1.4;
  border-radius: var(--r-sm, 4px);
  border-left: 3px solid var(--border-strong, #cbd5e1);
  background: var(--bg-page, #f8fafc);
  color: var(--text-muted, #64748b);
  white-space: normal;
  word-break: break-word;
}
.kanban-card-permit.is-chase {
  border-left-color: var(--semantic-rose, #f43f5e);
  background: #fff1f2;
  color: #9f1239;
  font-weight: 600;
}
.kanban-card-permit.is-ours {
  border-left-color: var(--semantic-amber, #f59e0b);
  background: #fffbeb;
  color: #92400e;
}
.kanban-card-permit.is-waiting { border-left-color: var(--semantic-purple, #8b5cf6); }
/* The permit has landed but the job is still parked in permit — a nudge to
   move it on, not an alarm. */
.kanban-card-permit.is-settled {
  border-left-color: var(--semantic-green, #10b981);
  background: #ecfdf5;
  color: #047857;
}

/* ---------------------------------------------------------------------------
   Learned lead times. The number a customer gets told should come from what
   these cities have done to OUR packets, not from the website's promise.
   --------------------------------------------------------------------------- */
/* Scoped to this tab rather than added to the global palette: the mockup's soft
   teal and rose have no existing token, and two of the three names I first
   reached for (--brand-teal, --bg-card) do not exist at all — they were riding
   their fallbacks. These three are local, named for where they are used. */
#tab-permits {
  --permit-teal: var(--action-blue, #16C7C9);
  --permit-teal-soft: #EAF5F4;
  --permit-rose-soft: #FFF1F2;
}

/* PERMITS WORKSPACE — from the approved permit-workspace mockup. The mockup's
   own palette is mapped onto this app's existing CSS variables rather than
   copied as hex: the sidebar and teal accent already exist here, and a second
   set of colour constants is how two parts of one app drift apart. */
.permit-ws-header {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 18px;
}
.permit-ws-title {
  font-size: 27px; line-height: 1.2; letter-spacing: -.8px;
  margin: 0 0 4px; font-weight: 600; color: var(--text-heading, #0f172a);
}
.permit-ws-sub { margin: 0; color: var(--text-muted, #64748b); }
.permit-ws-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

/* Filters. Counts come from the rows on screen, so they cannot disagree. */
.permit-filters { display: flex; gap: 7px; flex-wrap: wrap; margin: 0 0 16px; }
.permit-filter {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 11px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--border-soft, #e2e8f0);
  background: var(--bg-surface, #fff); color: var(--text-muted, #64748b);
  font-size: var(--fs-xs, 11px); font-weight: 600;
}
.permit-filter:hover { color: var(--text-heading, #0f172a); }
.permit-filter.is-active {
  background: var(--text-heading, #0f172a); color: var(--bg-surface, #fff);
  border-color: var(--text-heading, #0f172a);
}
.permit-filter-count { opacity: .75; font-variant-numeric: tabular-nums; }

/* Untracked: one collapsed line, never a stack of cards pushing work down. */
.permit-untracked {
  margin: 0 0 16px; padding: 10px 14px;
  background: var(--bg-surface, #fff);
  border: 1px solid var(--border-soft, #e2e8f0); border-radius: 8px;
}
.permit-untracked.hidden { display: none; }
.permit-untracked-summary {
  cursor: pointer; font-size: var(--fs-sm, 13px); font-weight: 600;
  color: var(--semantic-amber, #f59e0b);
}
.permit-untracked-body { padding-top: 12px; }

/* The two halves. The detail is given slightly more room than the list — it is
   where the reading happens; the list only has to be scannable. */
.permit-workspace {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: 16px; align-items: start;
}
.permit-list {
  border: 1px solid var(--border-soft, #e2e8f0); border-radius: 9px;
  background: var(--bg-surface, #fff); overflow: hidden;
}
.permit-list-head {
  padding: 11px 15px; font-size: var(--fs-xs, 11px); letter-spacing: 1px;
  text-transform: uppercase; color: var(--text-muted, #64748b);
  border-bottom: 1px solid var(--border-soft, #e2e8f0);
}
.permit-list-sep {
  padding: 9px 15px; font-size: var(--fs-xs, 11px); letter-spacing: 1px;
  text-transform: uppercase; color: var(--text-muted, #64748b);
  background: var(--bg-page, #f8fafc);
  border-top: 1px solid var(--border-soft, #e2e8f0);
  border-bottom: 1px solid var(--border-soft, #e2e8f0);
}
.permit-list-empty, .permit-detail-empty {
  padding: 18px 15px; margin: 0;
  color: var(--text-muted, #64748b); font-size: var(--fs-sm, 13px);
}

/* A row is a button: keyboard reaches it, Enter and Space select it, and the
   pressed state is what a screen reader reads out. */
.permit-row-pick {
  display: block; width: 100%; text-align: left; cursor: pointer;
  border: 0; border-bottom: 1px solid var(--border-soft, #f1f5f9);
  background: var(--bg-surface, #fff); color: var(--text-body, #334155);
  padding: 14px 15px;
  /* Reserve the selected edge so selecting does not shift the text sideways. */
  box-shadow: inset 3px 0 transparent;
}
.permit-row-pick:last-child { border-bottom: 0; }
.permit-row-pick:hover { background: var(--bg-page, #f8fafc); }
.permit-row-pick:focus-visible { outline: 2px solid var(--permit-teal); outline-offset: -2px; }
.permit-row-pick.is-selected {
  background: var(--permit-teal-soft);
  box-shadow: inset 3px 0 var(--permit-teal);
}
.permit-row-name {
  display: block; font-size: var(--fs-sm, 13px); font-weight: 600;
  color: var(--text-heading, #0f172a); margin-bottom: 3px;
}
.permit-row-meta { display: block; font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b); }
.permit-row-nocity { color: var(--semantic-amber, #f59e0b); font-weight: 600; }
.permit-row-foot {
  display: flex; justify-content: space-between; align-items: center;
  gap: 8px; margin-top: 11px; font-size: var(--fs-xs, 11px);
}
.permit-row-stage {
  background: var(--bg-page, #f8fafc); color: var(--text-muted, #64748b);
  border-radius: 4px; padding: 3px 7px;
}
.permit-row-owner { color: var(--text-muted, #64748b); }
.permit-row-late { color: var(--semantic-rose, #f43f5e); font-weight: 700; }

/* Detail pane */
.permit-detail-pane {
  background: var(--bg-surface, #fff);
  border: 1px solid var(--border-soft, #e2e8f0); border-radius: 9px;
  padding: 20px; min-width: 0;
}
.permit-detail-eyebrow {
  font-size: var(--fs-xs, 11px); letter-spacing: 1px;
  color: var(--permit-teal); margin-bottom: 7px;
}
.permit-detail-title {
  font-size: 19px; line-height: 1.35; letter-spacing: -.3px;
  margin: 0 0 5px; font-weight: 600; color: var(--text-heading, #0f172a);
}
.permit-detail-meta { color: var(--text-muted, #64748b); font-size: var(--fs-sm, 13px); }
.permit-detail-actions { display: flex; gap: 12px; align-items: center; margin-top: 10px; flex-wrap: wrap; }
.permit-detail-siblings {
  margin: 0 0 12px; font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b);
}

/* Progress. Unfilled bars for holds and terminal states — see the mapping in
   app.js for why a withdrawn permit fills nothing. */
.permit-steps { display: flex; gap: 4px; margin: 18px 0 5px; }
.permit-steps span { height: 4px; flex: 1; border-radius: 4px; background: var(--border-soft, #e2e8f0); }
.permit-steps span.is-done { background: var(--permit-teal); }
.permit-stepnames {
  display: flex; justify-content: space-between;
  font-size: 10px; color: var(--text-muted, #64748b); margin-bottom: 6px;
}
.permit-step-state {
  display: inline-block; margin-bottom: 14px; padding: 2px 8px; border-radius: 4px;
  font-size: var(--fs-xs, 11px); font-weight: 700;
  background: var(--semantic-amber, #f59e0b); color: #fff;
}
.permit-step-note { margin-bottom: 14px; font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b); }

/* Next action — the block the whole redesign is pointed at. */
.permit-next {
  border-radius: 7px; background: var(--permit-teal-soft);
  padding: 14px; margin: 14px 0 18px;
}
.permit-next small { font-size: 10px; letter-spacing: 1px; color: var(--permit-teal); }
.permit-next strong { display: block; font-size: var(--fs-md, 14px); margin: 5px 0; color: var(--text-heading, #0f172a); }
.permit-next p { margin: 0; font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b); }
.permit-next.is-late { background: var(--permit-rose-soft); }
.permit-next.is-late small { color: var(--semantic-rose, #f43f5e); }
.permit-next.is-late .permit-next-due { color: var(--semantic-rose, #f43f5e); font-weight: 700; }
/* An empty next action says it is empty rather than inventing one. */
.permit-next.is-empty { background: var(--bg-page, #f8fafc); }
.permit-next.is-empty small { color: var(--text-muted, #64748b); }
.permit-next-due.is-missing { font-style: italic; }

@media (max-width: 900px) {
  /* List above detail: at this width two columns leave neither readable. */
  .permit-workspace { grid-template-columns: 1fr; }
  .permit-ws-title { font-size: 22px; }
}
@media (max-width: 560px) {
  .permit-ws-actions { width: 100%; }
  .permit-search { flex: 1; min-width: 0; }
  .permit-detail-pane { padding: 15px; }
}

/* THE FOUR VIEWS. A row of buttons rather than more drawers: the tab had eight
   collapsible sections and the queue was lost among them. */
.permit-views {
  display: flex; gap: 4px; flex-wrap: wrap;
  margin: 0 0 18px;
  border-bottom: 1px solid var(--border-soft, #e2e8f0);
}
.permit-view-btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 14px; border: 0; background: none; cursor: pointer;
  font-size: var(--fs-sm, 13px); font-weight: 600;
  color: var(--text-muted, #64748b);
  /* Sits ON the container border so the active tab joins the panel below it. */
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.permit-view-btn:hover { color: var(--text-heading, #0f172a); }
.permit-view-btn.is-active {
  color: var(--text-heading, #0f172a);
  border-bottom-color: var(--brand-teal, #14b8a6);
}
/* The badge carries the severity of what it counts, in the same two colours the
   rows inside use — a grey pill saying "5" would not say which five. */
.permit-view-count {
  min-width: 18px; padding: 1px 6px; border-radius: 999px;
  font-size: var(--fs-xs, 11px); font-weight: 700; text-align: center;
  background: var(--bg-page, #f8fafc); color: var(--text-muted, #64748b);
  border: 1px solid var(--border-soft, #e2e8f0);
}
.permit-view-count.is-expired, .permit-view-count.is-chase {
  background: var(--semantic-rose, #f43f5e); color: #fff; border-color: transparent;
}
.permit-view-count.is-expiring {
  background: var(--semantic-amber, #f59e0b); color: #fff; border-color: transparent;
}
.permit-work-controls { display: contents; }
.permit-work-controls.hidden { display: none; }
@media (max-width: 560px) {
  /* Labels stay; only the padding gives way, so three buttons still fit a phone. */
  .permit-view-btn { padding: 9px 9px; }
}

.permit-turnaround { margin: 0 0 22px; }
.permit-turnaround-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.permit-turnaround-head h3 {
  margin: 0;
  font-size: var(--fs-md, 14px);
  color: var(--text-heading, #0f172a);
}
.permit-turnaround-sub { font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b); }
.permit-turnaround-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 8px;
}
.permit-turnaround-cell {
  padding: 8px 10px;
  background: var(--bg-surface, #fff);
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-md, 8px);
}
.permit-turnaround-city {
  font-size: var(--fs-xs, 11px);
  font-weight: 600;
  color: var(--text-muted, #64748b);
}
.permit-turnaround-days {
  font-size: var(--fs-xl, 22px);
  font-weight: 700;
  color: var(--text-heading, #0f172a);
  line-height: 1.1;
}
.permit-turnaround-days span { font-size: var(--fs-sm, 13px); font-weight: 600; color: var(--text-muted, #64748b); }
.permit-turnaround-n { font-size: 10px; color: var(--text-muted, #64748b); }
.permit-turnaround-range { font-size: 10px; color: var(--text-faint, #94a3b8); margin-top: 1px; }
/* A thin sample must not LOOK like a measurement — the number is dimmed to
   match the sentence under it, because a bold figure gets quoted. */
.permit-turnaround-cell.is-anecdotal .permit-turnaround-days,
.permit-turnaround-cell.is-thin .permit-turnaround-days { color: var(--text-muted, #64748b); }
.permit-turnaround-cell.is-anecdotal { border-style: dashed; }
.permit-turnaround-cell.is-anecdotal .permit-turnaround-n { color: var(--semantic-amber, #f59e0b); }

/* ===========================================================================
   PERMITS — per-jurisdiction templates.

   Two facts belong to the CITY rather than to the job: which checklist it
   starts from, and the standing things worth remembering about filing there.
   They share one strip under the permit header for that reason.

   Note the "standard packet" state is styled as a normal state, not a warning.
   Nothing is missing until a city has actually told us something, and the only
   way it tells us is somebody filing there and capturing what they learned.
   =========================================================================== */
.permit-template-line {
  margin-top: 8px;
  padding: 6px 8px;
  border-radius: var(--r-sm, 4px);
  background: var(--bg-page, #f8fafc);
  border: 1px solid var(--border-soft, #e2e8f0);
}
.permit-template-line.is-city { border-left: 3px solid var(--action-blue, #16c7c9); }
.permit-template-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  font-size: var(--fs-xs, 11px);
}
.permit-template-src { color: var(--text-muted, #64748b); }
.permit-template-line.is-city .permit-template-src { color: var(--text-body, #1f2937); font-weight: 600; }
.permit-city-portal { color: var(--action-blue-dark, #12b6b8); white-space: nowrap; }
.permit-save-template-btn { margin-left: auto; white-space: nowrap; }
/* The standing facts about filing in this city — counter hours, the thing they
   always ask for. Worth reading once per job, not once per line. */
.permit-city-notes {
  margin-top: 6px;
  padding: 6px 8px;
  font-size: var(--fs-xs, 11px);
  color: #1e40af;
  background: #eff6ff;
  border: 1px solid #bfdbfe;
  border-radius: var(--r-sm, 4px);
}

/* The city-template list on the Permits tab. */
.permit-templates { margin-top: 26px; }
.permit-templates > summary {
  font-size: var(--fs-md, 14px);
  font-weight: 600;
  color: var(--text-heading, #0f172a);
  cursor: pointer;
  padding: 6px 0;
}
.permit-templates-count {
  font-size: var(--fs-xs, 11px);
  font-weight: 600;
  color: var(--text-muted, #64748b);
  background: var(--bg-page, #f8fafc);
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: 999px;
  padding: 1px 7px;
}
.permit-templates-intro {
  font-size: var(--fs-sm, 13px);
  color: var(--text-muted, #64748b);
  margin: 4px 0 12px;
  max-width: 70ch;
}
.permit-template-card {
  padding: 10px 12px;
  margin-bottom: 8px;
  background: var(--bg-surface, #fff);
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-md, 8px);
}
.permit-template-card-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.permit-template-meta { font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b); }
.permit-template-delete {
  margin-left: auto;
  font-size: var(--fs-xs, 11px);
  padding: 3px 8px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
  background: var(--bg-surface, #fff);
  color: var(--text-muted, #64748b);
  cursor: pointer;
}
.permit-template-delete:hover { color: var(--semantic-rose, #f43f5e); border-color: #fecdd3; }
.permit-template-items {
  margin: 0;
  padding-left: 18px;
  font-size: var(--fs-xs, 11px);
  color: var(--text-body, #1f2937);
  columns: 2;
  column-gap: 24px;
}
.permit-template-items li { margin-bottom: 2px; break-inside: avoid; }
.permit-template-who, .permit-template-cond {
  margin-left: 5px;
  font-size: 10px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--bg-page, #f8fafc);
  color: var(--text-muted, #64748b);
}
.permit-template-fields {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 8px;
  margin-top: 10px;
}
.permit-template-fields label { display: flex; flex-direction: column; gap: 2px; }
.permit-template-fields span { font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b); }
.permit-template-fields input {
  font-size: var(--fs-sm, 13px);
  padding: 5px 8px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
  min-width: 0;
}
@media (max-width: 640px) {
  .permit-template-items { columns: 1; }
  .permit-template-fields { grid-template-columns: 1fr; }
  .permit-save-template-btn { margin-left: 0; }
}

/* ===========================================================================
   PERMITS — sharing the submittal package.

   Sits under the package block because it is the same artifact by a different
   route: the zip for a portal upload, a link for the plan checker or landlord
   who would rather click. Nothing here fires on its own — a link is minted
   only on a click, and a PIN is shown exactly once.
   =========================================================================== */
.permit-shares {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed var(--border-soft, #e2e8f0);
}
.permit-shares-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.permit-shares-title {
  font-size: var(--fs-sm, 13px);
  font-weight: 600;
  color: var(--text-heading, #0f172a);
}
.permit-shares-hint { font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b); margin: 0; }

.permit-share-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 7px 0;
  border-bottom: 1px dashed var(--border-soft, #eef1f4);
}
.permit-share-row:last-child { border-bottom: none; }
.permit-share-main { flex: 1 1 240px; min-width: 0; }
.permit-share-url {
  width: 100%;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--fs-xs, 11px);
  padding: 4px 6px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
  background: var(--bg-page, #f8fafc);
  color: var(--text-body, #1f2937);
}
.permit-share-meta {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 3px;
  font-size: 10px;
}
.permit-share-pin { background: #eef2ff; color: #4338ca; border-radius: 999px; padding: 1px 6px; }
.permit-share-nodl { background: var(--bg-page, #f8fafc); color: var(--text-muted, #64748b); border-radius: 999px; padding: 1px 6px; }
.permit-share-until { color: var(--text-muted, #64748b); }
.permit-share-expired { color: var(--semantic-rose, #f43f5e); font-weight: 600; }
/* The record of what went where — the thing that answers "we never got it". */
.permit-share-sent { margin-top: 3px; font-size: 10px; color: #047857; }
.permit-share-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.permit-share-email-form {
  flex: 1 1 100%;
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  padding-top: 8px;
}
.permit-share-email-form input {
  flex: 1 1 160px;
  min-width: 0;
  font-size: var(--fs-sm, 13px);
  padding: 5px 8px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
}
.permit-share-send {
  font-size: var(--fs-xs, 11px);
  font-weight: 600;
  padding: 5px 12px;
  border: none;
  border-radius: var(--r-sm, 4px);
  background: var(--action-blue, #16c7c9);
  color: #fff;
  cursor: pointer;
  white-space: nowrap;
}
.permit-share-send:hover { background: var(--action-blue-dark, #12b6b8); }

/* ===========================================================================
   PERMIT OFFICES — the standing knowledge about a city.

   Separate from the packet template on purpose: the office is how you DEAL
   with a city (counter, portal, hours, who answers), the template is what that
   city wants IN the packet. They are learned at different times — the office
   on the first phone call, the template only after a filing comes back.
   =========================================================================== */
.permit-office {
  margin-top: 8px;
  padding: 8px 10px;
  border-radius: var(--r-sm, 4px);
  background: var(--bg-page, #f8fafc);
  border: 1px solid var(--border-soft, #e2e8f0);
  border-left: 3px solid var(--semantic-purple, #8b5cf6);
  font-size: var(--fs-xs, 11px);
}
/* No office saved yet reads as a prompt, not a fault — it is the normal state
   for a city nobody has rung. */
.permit-office.is-missing {
  border-left-color: var(--border-strong, #cbd5e1);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  color: var(--text-muted, #64748b);
}
.permit-office-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.permit-office-row strong { font-size: var(--fs-sm, 13px); color: var(--text-heading, #0f172a); }
.permit-office-how { color: var(--text-body, #1f2937); font-weight: 600; }
.permit-office-portal { color: var(--action-blue-dark, #12b6b8); white-space: nowrap; }
.permit-office-edit, .permit-office-add { margin-left: auto; white-space: nowrap; }
.permit-office-facts {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 3px;
  color: var(--text-muted, #64748b);
}
.permit-office-hours { color: #92400e; }
.permit-office-contacts {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 4px;
  padding-top: 4px;
  border-top: 1px dashed var(--border-soft, #eef1f4);
}
.permit-office-contact { color: var(--text-body, #1f2937); }
.permit-office-contact em { font-style: normal; color: var(--text-faint, #94a3b8); }
/* What we still don't know is the actionable half — a half-filled office is
   normal after one filing, and naming the gaps is what gets them filled. */
.permit-office-gaps {
  margin-top: 4px;
  color: var(--semantic-amber, #f59e0b);
  font-weight: 600;
}

/* The people, inside the office editor. */
.permit-office-people {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft, #e2e8f0);
}
.permit-office-people h3 { margin: 0 0 8px; font-size: var(--fs-sm, 13px); }
.permit-office-contact-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  padding: 6px 0;
  border-bottom: 1px dashed var(--border-soft, #eef1f4);
  font-size: var(--fs-sm, 13px);
}
.permit-office-contact-row:last-child { border-bottom: none; }
.permit-office-role {
  font-size: var(--fs-xs, 11px);
  background: var(--bg-page, #f8fafc);
  border-radius: 999px;
  padding: 1px 6px;
  color: var(--text-muted, #64748b);
}
.permit-office-contact-meta { font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b); }
.permit-office-contact-note { font-size: var(--fs-xs, 11px); color: var(--text-faint, #94a3b8); }
.permit-office-contact-del {
  background: none; border: none; color: var(--text-faint, #94a3b8);
  cursor: pointer; font-size: 16px; line-height: 1; padding: 0 4px;
}
.permit-office-contact-del:hover { color: var(--semantic-rose, #f43f5e); }
.permit-office-contact-add {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 6px;
  margin-top: 10px;
}
.permit-office-contact-add input {
  font-size: var(--fs-sm, 13px);
  padding: 5px 8px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
  min-width: 0;
}
.permit-office-contact-add button {
  font-size: var(--fs-xs, 11px);
  font-weight: 600;
  padding: 5px 12px;
  border: none;
  border-radius: var(--r-sm, 4px);
  background: var(--action-blue, #16c7c9);
  color: #fff;
  cursor: pointer;
}

/* The directory on the Permits tab. */
.permit-office-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 8px;
  margin-bottom: 10px;
}
.permit-office-card {
  padding: 10px 12px;
  background: var(--bg-surface, #fff);
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-md, 8px);
  cursor: pointer;
}
.permit-office-card:hover { border-color: var(--border-strong, #cbd5e1); }
.permit-office-card-name {
  font-size: var(--fs-sm, 13px);
  font-weight: 600;
  color: var(--text-heading, #0f172a);
}
.permit-office-card-how { font-size: var(--fs-xs, 11px); color: var(--text-body, #1f2937); margin-top: 2px; }
.permit-office-card-meta, .permit-office-card-people {
  font-size: 10px; color: var(--text-muted, #64748b); margin-top: 2px;
}
.permit-office-card-gaps { font-size: 10px; color: var(--semantic-amber, #f59e0b); margin-top: 3px; }
.permit-office-card-ok { font-size: 10px; color: #047857; margin-top: 3px; }
@media (max-width: 640px) {
  .permit-office-edit, .permit-office-add { margin-left: 0; }
}

/* The office editor opens ON TOP of the job modal — you reach it from a
   permit panel, with the job still open behind. Both carry .modal (z-index
   100), and the job modal comes later in the document, so on a tie it painted
   over this one and the dialog was invisible. Seen, not theorised.

   5000 sits above .modal and deliberately BELOW #confirm-modal (10000), so the
   "delete this office?" confirmation still lands on top of the editor that
   raised it. */
#permit-office-modal { z-index: 5000; }

/* Where the city facts went. A pointer costs one line and saves somebody
   hunting for inputs that used to be here. */
.permit-template-moved {
  margin-top: 8px;
  font-size: var(--fs-xs, 11px);
  color: var(--text-muted, #64748b);
}

/* The "we can fill these in for you" block. Styled as a SUGGESTION, not as a
   setup step: the values came off council websites, and the visual weight
   should not imply this shop has verified them. Disappears once there is
   nothing left to add. */
.permit-office-suggest {
  margin-top: 14px;
  padding: 10px 12px;
  background: #f5f3ff;
  border: 1px dashed #c4b5fd;
  border-radius: var(--r-md, 8px);
}
.permit-office-suggest-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.permit-office-suggest-head strong { font-size: var(--fs-sm, 13px); color: #4c1d95; }
.permit-office-suggest-why {
  margin: 4px 0 8px;
  font-size: var(--fs-xs, 11px);
  color: #5b21b6;
  max-width: 72ch;
}
.permit-office-suggest-row {
  padding: 6px 0;
  border-top: 1px dashed #ddd6fe;
  font-size: var(--fs-xs, 11px);
}
.permit-office-suggest-name { font-weight: 600; color: var(--text-heading, #0f172a); }
.permit-office-suggest-fields { color: var(--text-body, #1f2937); }

/* A suggested TEMPLATE is not a suggested office. The office rows carry five
   short labelled fields and read fine joined with separators; a template row
   carries the whole packet — twenty lines on Temecula — and the same inline
   spans ran them into one unbroken sentence:
   "Sign permit applicationSite plan showing sign locationScaled elevation…".

   So each pack is its own drawer, closed, and its lines are a real list. The
   provenance on each line (`detail`) was being dropped entirely, which is what
   made the banner's own claim about counts unbackable — it is the only place
   that says where a line came from, so it belongs on the line. */

/* Deliberately NOT display:flex. Chrome drops the disclosure triangle the
   moment a summary becomes a flex container, which leaves fifteen rows that
   open and nothing saying they do — measured here, marker content went
   `normal` with no triangle drawn. The count is an inline span instead. */
.permit-suggest-pack > summary { cursor: pointer; }
.permit-suggest-pack-count { margin-left: 8px; color: var(--text-muted, #64748b); }
.permit-suggest-lines {
  margin: 6px 0 2px;
  padding: 0 0 0 18px;
  display: grid;
  gap: 6px;
}
.permit-suggest-lines > li { color: var(--text-body, #1f2937); }
.permit-suggest-line-label { font-weight: 600; }
.permit-suggest-line-when {
  margin-left: 6px;
  color: var(--permit-teal, #0f766e);
  white-space: nowrap;
}
/* On its own line, not trailing the label — a packet line's label is the thing
   you scan for and its provenance is the thing you read once. */
.permit-suggest-line-detail {
  display: block;
  color: var(--text-muted, #64748b);
  max-width: 72ch;
}
.permit-office-suggest-url {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--text-muted, #64748b);
  word-break: break-all;
}
/* Where it came from, kept visible — this is the difference between a lead and
   a fact, and it should not need a hover. */
.permit-office-suggest-src { color: var(--text-faint, #94a3b8); font-style: italic; }

/* The office form is long enough that its footer fell below the fold — measured
   at 1440x860: 894px of content into a 791px scrollport, with Save and Cancel
   100px past the bottom edge and no cue that scrolling would reach them. A
   dialog whose confirm button is invisible on open is a broken dialog, however
   correct its overflow behaviour.

   Pinned to the bottom of the scrollport instead, so it is reachable at any
   viewport height rather than only where the content happens to fit. The solid
   background is load-bearing: fields scroll UNDER this. The side margins cancel
   the form's own 32px padding (22px when narrow) so the bar spans the dialog
   edge to edge — they must track that padding, or the bar overhangs and the
   dialog scrolls sideways, which is exactly what a -24px guess did here. */
#permit-office-form footer {
  position: sticky;
  bottom: 0;
  background: #fff;
  margin: 18px -32px 0;
  padding: 14px 32px;
  border-top: 1px solid #e1e4e8;
}

@media (max-width: 640px) {
  /* Track the narrow form padding above. */
  #permit-office-form footer { margin-left: -22px; margin-right: -22px; padding-left: 22px; padding-right: 22px; }
}

/* ===========================================================================
   BUSINESS DOCUMENTS — the shop's own paperwork, filed once.

   The visual job here is the expiry. A folder of PDFs is easy; what stops a
   bounced submittal is noticing that the insurance certificate lapsed, so
   status is the loudest thing on each card.
   =========================================================================== */
.shop-doc-warn-pip {
  margin-left: 6px;
  font-size: var(--fs-xs, 11px);
  font-weight: 700;
  color: #fff;
  background: var(--semantic-rose, #f43f5e);
  border-radius: 999px;
  padding: 1px 7px;
}
.shop-doc-warnings { margin-bottom: 10px; display: flex; flex-direction: column; gap: 4px; }
.shop-doc-warning {
  padding: 7px 10px;
  border-radius: var(--r-sm, 4px);
  font-size: var(--fs-sm, 13px);
}
.shop-doc-warning.is-expired { background: #fff1f2; border: 1px solid #fecdd3; color: #9f1239; }
.shop-doc-warning.is-expiring { background: #fffbeb; border: 1px solid #fde68a; color: #92400e; }
.shop-doc-warning.is-no-expiry-recorded { background: var(--bg-page, #f8fafc); border: 1px solid var(--border-soft, #e2e8f0); color: var(--text-muted, #64748b); }

.shop-doc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 8px;
  margin-bottom: 10px;
}
.shop-doc-card {
  padding: 10px 12px;
  background: var(--bg-surface, #fff);
  border: 1px solid var(--border-soft, #e2e8f0);
  border-left: 3px solid var(--semantic-green, #10b981);
  border-radius: var(--r-md, 8px);
}
.shop-doc-card.is-expired { border-left-color: var(--semantic-rose, #f43f5e); background: #fff7f8; }
.shop-doc-card.is-expiring { border-left-color: var(--semantic-amber, #f59e0b); }
.shop-doc-card.is-no-expiry-recorded { border-left-color: var(--border-strong, #cbd5e1); }
/* Retired documents stay readable — a permit that was filed against one still
   points at it, and it should not look broken. */
.shop-doc-card.is-retired { opacity: 0.6; }
.shop-doc-card-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.shop-doc-card-head a {
  font-size: var(--fs-sm, 13px);
  font-weight: 600;
  color: var(--action-blue-dark, #12b6b8);
}
.shop-doc-kind { font-size: 10px; color: var(--text-muted, #64748b); }
.shop-doc-status { font-size: var(--fs-xs, 11px); margin-top: 2px; color: var(--text-muted, #64748b); }
.shop-doc-card.is-expired .shop-doc-status { color: #9f1239; font-weight: 700; }
.shop-doc-card.is-expiring .shop-doc-status { color: #92400e; font-weight: 600; }
.shop-doc-fields {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  margin-top: 8px;
  flex-wrap: wrap;
}
.shop-doc-fields label { display: flex; flex-direction: column; gap: 2px; flex: 1 1 120px; }
.shop-doc-fields span { font-size: 10px; color: var(--text-muted, #64748b); }
.shop-doc-fields input {
  font-size: var(--fs-xs, 11px);
  padding: 4px 6px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
  min-width: 0;
}
.shop-doc-retire {
  font-size: var(--fs-xs, 11px);
  padding: 4px 10px;
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: var(--r-sm, 4px);
  background: var(--bg-surface, #fff);
  color: var(--text-muted, #64748b);
  cursor: pointer;
  white-space: nowrap;
}
.shop-doc-retired { margin-bottom: 10px; }
.shop-doc-retired > summary { font-size: var(--fs-xs, 11px); color: var(--text-muted, #64748b); cursor: pointer; }
.shop-doc-add { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* A packet line satisfied by a shop-wide document rather than a job file. */
.permit-item-biz {
  font-size: 10px;
  background: #eef2ff;
  color: #4338ca;
  border-radius: 999px;
  padding: 1px 6px;
}
.permit-item-exp { font-size: 10px; color: var(--text-muted, #64748b); }
.permit-item-exp.is-expired { color: var(--semantic-rose, #f43f5e); font-weight: 700; }

/* The "no permit yet" line on a job that is not in the permit bucket. One quiet
   line, deliberately not a bordered panel: most jobs never need a permit —
   banners, wraps, most interior work — and an empty section on every one of
   them is how the sections that matter get scrolled past. */
.permit-start-hint {
  margin: 0;
  font-size: var(--fs-xs, 11px);
  color: var(--text-muted, #64748b);
}

/* Jobs in the "In Permit" column with no permit record. Sits ABOVE "On us":
   a job nobody is tracking is worse than one that is tracked and late, because
   the late one is at least visible. Dashed, to read as an absence rather than
   as another stage. */
.permit-untracked .permit-group-header h3 { color: #92400e; }
.permit-row.is-untracked {
  border-style: dashed;
  border-left: 4px dashed var(--semantic-amber, #f59e0b);
  background: #fffbeb;
}
.permit-row.is-untracked .permit-row-headline { color: #92400e; }
.permit-adopt-one {
  font-size: var(--fs-xs, 11px);
  font-weight: 600;
  padding: 5px 12px;
  border: none;
  border-radius: var(--r-sm, 4px);
  background: var(--semantic-amber, #f59e0b);
  color: #fff;
  cursor: pointer;
  white-space: nowrap;
}
.permit-adopt-one:hover { background: #d97706; }

/* PORTAL CHECK-IN: when a human last read the city's portal. Sits beside the
   stage clock because it answers the neighbouring question — that one says how
   long the permit has been here, this says how long since anyone looked. */
.permit-portal-chip {
  color: var(--text-muted, #64748b);
  border: 1px solid var(--border-soft, #e2e8f0);
  border-radius: 999px;
  padding: 1px 7px;
}
/* Stale reads as a problem, because it is one: the permit may have moved and
   nobody would know. */
.permit-portal-chip.is-stale {
  color: #92400e;
  background: #fffbeb;
  border-color: #fde68a;
  font-weight: 600;
}
.permit-portal-btn { white-space: nowrap; }

/* An action inside a toast — today only Undo. Sits before the close button so
   tab order reaches the useful control first. */
.toast-action {
  background: none;
  border: 1px solid currentColor;
  border-radius: var(--r-sm, 4px);
  color: inherit;
  font: inherit;
  font-size: var(--fs-xs, 11px);
  font-weight: 700;
  padding: 3px 10px;
  margin-left: 10px;
  cursor: pointer;
  opacity: 0.85;
  white-space: nowrap;
}
.toast-action:hover { opacity: 1; }

/* ---- Provenance: suggested vs recorded ------------------------------------
   A deliberately QUIET badge. It marks a row as transcribed-but-unchecked,
   which is a caveat, not an alarm — the loud states in this app are reserved
   for a permit that is actually stuck or a licence that has actually lapsed.
   Slate rather than amber for exactly that reason. */
.permit-prov-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--bg-page);
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .01em;
  vertical-align: middle;
  white-space: nowrap;
}
.permit-prov-line {
  margin-top: 4px;
  color: var(--text-muted);
  font-size: 12px;
}

/* An expired licence nobody has confirmed: muted, not red. The date came off a
   summary sheet, so the honest claim is "check this", and only confirming it
   promotes the row to the danger state the .is-expired rule paints. */
.licence-row.is-expired.is-unconfirmed { border-left-color: var(--border-strong); }
.licence-row.is-expired.is-unconfirmed .licence-when {
  color: var(--text-muted);
  font-weight: 500;
}
.permit-office-card.is-unconfirmed {
  border-style: dashed;
}

/* ---- Inspection strip ------------------------------------------------------
   Appears only once there is something to say. `.is-chasing` is the state that
   justifies the whole block: a date that has passed with no result recorded,
   or an inspection that failed. */
.permit-inspection {
  margin: 10px 0;
  padding: 10px 12px;
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--border-strong);
  border-radius: 8px;
  background: var(--bg-page);
}
.permit-inspection.is-chasing { border-left-color: var(--semantic-amber); }
.permit-inspection-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.permit-inspection-line { color: var(--text-body); font-size: 13px; }
.permit-inspection.is-chasing .permit-inspection-line { color: var(--semantic-amber); font-weight: 600; }
.permit-inspection-line.is-none { color: var(--text-faint); }
.permit-inspection-fields {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 8px;
}
.permit-inspection-fields label {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 11px;
  color: var(--text-muted);
}
.permit-inspection-fields input,
.permit-inspection-fields select {
  font-size: 13px;
  padding: 4px 6px;
  border: 1px solid var(--border-soft);
  border-radius: 6px;
  background: var(--bg-surface);
  color: var(--text-body);
}
.permit-inspection-notes { flex: 1 1 260px; }
.permit-inspection-notes input { width: 100%; }

/* ---- "Needs chasing" chip --------------------------------------------------
   A filter, not a status light: it is hidden entirely at zero rather than
   sitting there reading 0, because a control that is always present and always
   says nothing is one people stop reading. */
.permit-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--bg-surface);
  color: var(--text-body);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.permit-chip:hover { border-color: var(--semantic-amber); }
.permit-chip.is-on {
  background: var(--semantic-amber);
  border-color: var(--semantic-amber);
  color: #fff;
}
.permit-chip-count {
  min-width: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--semantic-amber);
  color: #fff;
  font-size: 11px;
  text-align: center;
}
.permit-chip.is-on .permit-chip-count { background: rgba(255, 255, 255, .28); }

/* The human-written next action on a queue row. Quieter than the headline it
   sits under — it is the detail you read once the row has your attention. */
.permit-row-next {
  margin-top: 3px;
  font-size: 12px;
  color: var(--text-muted);
}
.permit-row-next-label { font-weight: 700; color: var(--text-body); margin-right: 4px; }
.permit-row-next-due { margin-left: 6px; font-style: italic; }
.permit-row-next.is-late { color: var(--semantic-rose); }
.permit-row-next.is-late .permit-row-next-label { color: var(--semantic-rose); }

/* Next action — sits directly under the headline, because the person who has
   just come off the phone with the city is looking there. */
.permit-next-action {
  display: flex;
  gap: 10px;
  align-items: flex-end;
  margin: 8px 0 4px;
  flex-wrap: wrap;
}
.permit-next-action label {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 11px;
  color: var(--text-muted);
  flex: 1 1 220px;
}
.permit-next-action .permit-next-due { flex: 0 0 150px; }
.permit-next-action input {
  font-size: 13px;
  padding: 5px 8px;
  border: 1px solid var(--border-soft);
  border-radius: 6px;
  background: var(--bg-surface);
  color: var(--text-body);
}

/* Permits search — sits in the controls row with the chip. */
.permit-search {
  min-width: 240px;
  padding: 5px 10px;
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  background: var(--bg-surface);
  color: var(--text-body);
  font-size: 13px;
}
.permit-search:focus { outline: none; border-color: var(--action-blue); }

/* The dashboard permit card. Amber only when something is actually being
   chased — at zero it is a plain card, not a green "all clear" badge. */
.metric-card.metric-permits.is-chasing .metric-value { color: var(--semantic-amber); }

/* Permit filters inside the In Permit kanban column. Small and quiet — they
   sit above a stack of cards and must not out-shout them. */
.kanban-permit-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0 0 6px;
}
.kanban-permit-filter {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  background: var(--bg-surface);
  color: var(--text-muted);
  font-size: 10px;
  font-weight: 600;
  cursor: pointer;
}
.kanban-permit-filter span { color: var(--text-faint); }
.kanban-permit-filter:hover { border-color: var(--border-strong); color: var(--text-body); }
.kanban-permit-filter.is-on {
  background: var(--brand-ink);
  border-color: var(--brand-ink);
  color: #fff;
}
.kanban-permit-filter.is-on span { color: rgba(255, 255, 255, .7); }
