/* Accurate Daily Pace Report — dense, screenshot-friendly layout. Light theme default. */
:root {
  --navy: #0A1F5C; --navy-2: #14233f; --blue: #1f57c3; --gold: #FFD700; --ink: #14233f; --muted: #5b6b86;
  --line: #d6dee9; --bg: #eef2f7; --card: #ffffff; --yellow: #fff6cc; --yellow-line: #e7d77a;
  --grid: #000;  /* ONE inner cell-gridline color for every report table (huddle/DPR/pace/backlog/AR/callboard) — keep them uniform; the dark Jeff prefers */
  --good: #117a3d; --good-bg: #e3f5ea; --bad: #b3261e; --bad-bg: #fbe6e4; --warn: #9a6a00;
  --radius: 12px; --shadow: 0 1px 3px rgba(20,35,63,.08), 0 1px 2px rgba(20,35,63,.06);
}
[data-theme="dark"] {
  --navy:#0A1F5C; --ink:#e8eef9; --muted:#9fb0cc; --line:#2a3a5a; --bg:#0c1426; --card:#111c34;
  --yellow:#3a350f; --yellow-line:#5c5320; --good-bg:#0f2c1c; --bad-bg:#2e1513;
}
* { box-sizing: border-box; }
html, body { margin: 0; }
body { font-family: Calibri, "Segoe UI", system-ui, sans-serif; color: var(--ink); background: var(--bg); }
.boot { min-height: 100vh; display: grid; place-items: center; color: var(--muted); }
a { color: var(--blue); }

/* ---------- app shell: navy sidebar + light topbar + main (matches Level 10 / Board Report) ---------- */
.shell { display: grid; grid-template-columns: 232px 1fr; grid-template-rows: 56px 1fr;
  grid-template-areas: "side top" "side main"; height: 100vh; }

.sidebar { grid-area: side; background: var(--navy); color: #cdd8ee; overflow-y: auto;
  padding: 12px 0; display: flex; flex-direction: column; }
.sidebar .spacer { flex: 1; }
.sidebar .brand-link { display: block; }
.sidebar .brand { padding: 8px 16px 4px; }
.sidebar .brand img { max-width: 100%; height: auto; display: block; background: #fff; border-radius: 8px; padding: 10px; }
.brand-build { color: #8ea3c8; font-size: 11px; text-align: center; padding: 4px 14px 8px; letter-spacing: .2px; }
.sidebar .back-link { display: block; color: #cdd8ee; text-decoration: none; font-size: 13px;
  padding: 2px 16px 10px; opacity: .85; }
.sidebar .back-link:hover { opacity: 1; }
.sidebar .nav-group { color: #7f93bb; font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  padding: 14px 18px 4px; border-top: 1px solid rgba(255,255,255,.10); }
.sidebar nav a { display: block; padding: 10px 18px; color: #b9c6e3; text-decoration: none; font-size: 14px;
  border-left: 3px solid transparent; cursor: pointer; }
.sidebar nav a:hover { background: rgba(255,255,255,.06); color: #fff; }
.sidebar nav a.active { background: rgba(255,255,255,.10); color: var(--gold); border-left-color: var(--gold); font-weight: 600; }
.sidebar nav a.soon { color: #56688c; font-style: italic; }
.sidebar nav a.soon:hover { color: #7d8fb3; }
.sidebar nav a .soon-tag { font-size: 9px; text-transform: uppercase; letter-spacing: .05em; opacity: .7; margin-left: 4px; }
/* Sidebar tab tags (Jeff 6/28): gold "Daily" on the office's daily tabs, a red live count of reviews still
   needing attribution, and a white owner tag on AR Report. Only office/admin log in, so all see them. */
.sidebar nav a .nav-pill { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px;
  font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: .03em; vertical-align: middle; line-height: 1.5; }
.sidebar nav a .nav-pill-daily { background: var(--gold); color: #0A1F5C; }
.sidebar nav a .nav-pill-count { background: var(--bad); color: #fff; letter-spacing: 0; }
.sidebar nav a .nav-pill-owner { background: #36a7ff; color: #002360; box-shadow: 0 0 0 1px rgba(255,255,255,.5); }
.sidebar nav a .nav-pill[hidden] { display: none; }
/* Drag-to-reorder tabs (⠿ grip), like Level 10 (Jeff 6/26). */
.sidebar nav a { cursor: grab; }
.sidebar nav a .nav-grip { color: #6b7da3; margin-right: 8px; font-size: 12px; cursor: grab; }
.sidebar nav a:hover .nav-grip { color: #9fb0d4; }
.sidebar nav a.dragging { opacity: .5; }
.nav-role { color: #8ea3c8; font-size: 11px; padding: 10px 18px 4px; }

.topbar { grid-area: top; display: flex; align-items: center; gap: 12px; padding: 0 18px;
  background: var(--card); border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 20; }
.topbar .title { font-weight: 700; font-size: 15px; color: var(--ink); }
.topbar .spacer { flex: 1; }
.topbar select { font: inherit; padding: 7px 10px; border-radius: 8px; border: 1px solid var(--line);
  background: var(--card); color: var(--ink); font-weight: 600; }
.topbar button { font: inherit; cursor: pointer; padding: 7px 12px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink); font-weight: 600; }
.topbar button:hover { border-color: var(--blue); }
.topbar .menu-btn { display: none; }
/* cross-report switcher (admins) */
.topbar .report-link { font: inherit; text-decoration: none; padding: 7px 12px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink); font-weight: 600; white-space: nowrap; }
.topbar .report-link:hover { border-color: var(--blue); color: var(--blue); }
.topbar .report-link.home { background: var(--navy); color: #fff; border-color: var(--navy); }
.topbar .report-link.home:hover { color: #fff; }
.role-badge { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; padding: 3px 8px;
  border-radius: 999px; background: #1f57c3; color: #fff; }
.role-badge.viewer { background: #44557a; } .role-badge.csr { background: #1f8a5b; } .role-badge.admin { background: #b3681e; }

.main { grid-area: main; overflow-y: auto; padding: 18px 22px 40px; }
.main #dpr { width: 1180px; max-width: 100%; margin: 0 auto; display: flex; flex-direction: column; gap: 14px; }

@media (max-width: 1100px) {
  .shell { grid-template-columns: 1fr; grid-template-areas: "top" "main"; }
  .sidebar { position: fixed; z-index: 30; left: 0; top: 56px; bottom: 0; width: 232px;
    transform: translateX(-100%); transition: transform .2s; box-shadow: var(--shadow); }
  .sidebar.open { transform: none; }
  .topbar .menu-btn { display: inline-block; }
}

/* ---------- auth / gate ---------- */
.auth, .gate { min-height: 100vh; display: grid; place-items: center; padding: 24px; }
.auth-card { width: 420px; max-width: 100%; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 28px; box-shadow: var(--shadow); text-align: center; }
.auth-logo-img { max-width: 250px; width: 100%; height: auto; display: block; margin: 0 auto 14px; }
.auth-card h1 { font-size: 22px; margin: 0 0 8px; }
.auth-card p { color: var(--muted); margin: 0 0 16px; }
.auth-card input { width: 100%; font: inherit; padding: 10px 12px; border: 1px solid var(--line);
  border-radius: 8px; margin-bottom: 10px; }
.btn { font: inherit; cursor: pointer; border-radius: 8px; padding: 10px 16px; font-weight: 600; border: 0; width: 100%; }
.btn-primary { background: var(--navy); color: #fff; } .btn-ghost { background: transparent; border: 1px solid var(--line); color: var(--ink); }

/* ---------- cards ---------- */
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); overflow: hidden; }
.card > h2 { font-size: 13px; text-transform: uppercase; letter-spacing: .06em; color: #fff;
  background: var(--navy); margin: 0; padding: 8px 14px; }
.card .body { padding: 12px 14px; }
.section-band.hud-band { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
/* Repull button on the huddle section bands (Jeff 7/1) */
.hud-repull { background: #fff; color: var(--navy); border: 0; border-radius: 6px; padding: 3px 10px; font-size: 12px;
  font-weight: 700; cursor: pointer; white-space: nowrap; line-height: 1.4; }
.hud-repull:hover { background: #eef3fb; }
.hud-repull:disabled { opacity: .6; cursor: default; }
/* Refresh OUTCOME, patched onto the button for ~8s so the team can SEE the pull finished (Jeff 7/9: "I can see
   that it's working, but there's nothing that tells me when it's done"). Green = the snapshot changed and the
   page re-rendered. Amber = the office-PC helper never reported a fresh pull, so nothing on screen moved. */
.hud-repull.rp-ok { background: #117a3d; color: #fff; }
.hud-repull.rp-ok:hover { background: #0e6634; }
.hud-repull.rp-warn { background: #fff2d6; color: #8a5a00; }
.hud-repull.rp-warn:hover { background: #ffe9bd; }
/* Refresh IN PROGRESS — a spinning icon + a live elapsed-seconds counter (text set in JS), so "Refreshing…"
   visibly WORKS and never reads as hung (Jeff 7/10: "it says refreshing but no indication it's still going").
   Stays full-opacity though disabled, so it looks active, not greyed out. */
.hud-repull.rp-busy, .hud-repull.rp-busy:disabled { opacity: 1; background: #eaf1fb; color: var(--navy); cursor: progress; }
.hud-repull.rp-busy::before { content: "\21bb"; display: inline-block; margin-right: 5px; font-weight: 800;
  animation: rp-spin 0.8s linear infinite; }
@keyframes rp-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .hud-repull.rp-busy::before { animation: none; } }
/* Per-job flyout refresh icon (Jeff 7/11) — one per TGL row; a leader who just fixed this bid's Lead Generated By
   in ServiceTitan re-pulls ONLY this job (light single-job pull) instead of the whole-report Refresh. Borderless
   so the spinning glyph reads as an icon, not a rotating box. Reuses the rp-spin keyframe above. */
.jrf { border: 0; background: transparent; color: var(--muted); font-size: 13px; line-height: 1; padding: 0 2px;
  cursor: pointer; vertical-align: baseline; }
.jrf:hover { color: var(--navy); }
.jrf:disabled { cursor: default; }
.jrf.jrf-spin { display: inline-block; animation: rp-spin 0.8s linear infinite; color: var(--navy); }
.jrf.jrf-ok { color: var(--good); }
.jrf.jrf-warn { color: var(--bad); }
.jrf-tech.jrf-flash { background: #fff2c6; border-radius: 3px; box-shadow: 0 0 0 2px #fff2c6; transition: background .3s; }
@media (prefers-reduced-motion: reduce) { .jrf.jrf-spin { animation: none; } }
.section-band { background: var(--navy-2); color: #fff; border-radius: 8px; padding: 6px 12px;
  font-weight: 700; display: flex; justify-content: space-between; align-items: center; }
.day-pill { font-size: 12px; background: #1f57c3; padding: 2px 10px; border-radius: 999px; }

/* ---------- rounded table panel (matches Level 10 + the Board report — uniform look across all reports) ----------
   Each report table sits in a .tbl-wrap so it reads as its own rounded white panel inside the card, like
   Level 10's scorecard. overflow-y:hidden makes the 10px radius actually CLIP square corners (navy headers +
   the black-bordered Huddle/Pace/Callboard tables) so every table rounds; overflow-x:auto keeps wide tables
   horizontally scrollable. The .scroll variant gives a table its own vertical scroll box. (Jeff 6/26.) */
.tbl-wrap { overflow-x: auto; overflow-y: hidden; background: #fff; border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow); padding: 0; }
.tbl-wrap.scroll { max-height: 80vh; overflow: auto; }

/* ---------- Production — Month to Date (Daily Huddle) ---------- */
/* 2-line headers (white-space:normal on thead) tighten the columns so all 11 measurables fit with no
   horizontal scroll (Jeff 6/25). Data cells stay nowrap — the numbers are short. */
.prod-tbl { border-collapse: collapse; width: 100%; font-size: 11.5px; }
.prod-tbl th, .prod-tbl td { border: 1px solid var(--grid); padding: 4px 6px; text-align: center; white-space: nowrap; }
.prod-tbl thead th { background: var(--navy-2); color: #fff; font-weight: 700; font-size: 10.5px; line-height: 1.15; white-space: normal; vertical-align: middle; }
.prod-tbl .prod-lbl { text-align: left; font-weight: 700; }
.prod-tbl tbody .prod-lbl { background: var(--card); }
.prod-tbl thead .prod-lbl { background: var(--navy-2); color: #fff; }
.prod-tbl tr.prod-goal td { color: var(--muted); }
.prod-tbl tr.prod-actual td { font-weight: 700; }
.prod-tbl td.prod-good { color: var(--good); }
.prod-tbl td.prod-bad { color: var(--bad); }
/* derivation flyout affordance on the Actual row (lights up once production_mtd.detail exists) */
.prod-tbl td.prod-cell-drill { cursor: pointer; text-decoration: underline dotted; text-underline-offset: 2px; }
.prod-tbl td.prod-cell-drill:hover { background: rgba(31,87,195,0.12); }
/* Rounded frame on ALL FOUR corners — the bottom two were square (Jeff 6/28). border-collapse borders paint
   OVER the wrap's rounded clip, so the navy header rounded at top but the table's own black border stayed a
   square 90° at the bottom. Fix: the table sheds its OUTER edges and the .tbl-wrap's own 1px border (now black,
   already radius:12 + clipped) becomes the rounded frame; inner gridlines stay 1px black. overflow-x:auto is
   untouched so the 12-column table still scrolls on narrow screens. */
#prodCard .tbl-wrap { border-color: var(--grid); }
#prodCard .prod-tbl { border: 0; }
#prodCard .prod-tbl tr > *:first-child { border-left: 0; }
#prodCard .prod-tbl tr > *:last-child { border-right: 0; }
#prodCard .prod-tbl thead tr:first-child > * { border-top: 0; }
#prodCard .prod-tbl tbody tr:last-child > * { border-bottom: 0; }
/* MTD / QTD window — two separate buttons in the card header (Jeff 6/25) */
.prod-band-l { display: inline-flex; align-items: center; gap: 10px; }
.prod-btns { display: inline-flex; gap: 6px; }
.prod-btn { background: rgba(255,255,255,0.10); color: #cdd8ee; border: 1px solid rgba(255,255,255,0.35); border-radius: 6px; padding: 3px 15px; font-size: 12px; font-weight: 700; cursor: pointer; letter-spacing: .3px; }
.prod-btn:hover:not(:disabled) { background: rgba(255,255,255,0.18); }
.prod-btn.on { background: #1f57c3; color: #fff; border-color: #1f57c3; }
.prod-btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* ---------- header ---------- */
.header-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: 14px; }
.highlights { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.highlights li { background: var(--yellow); border: 1px solid var(--yellow-line); border-radius: 8px;
  padding: 7px 10px; font-weight: 600; }
.counts { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; text-align: center; }
.counts .cell { border: 1px solid var(--line); border-radius: 8px; padding: 8px 4px; }
.counts .cell .k { font-size: 11px; color: var(--muted); text-transform: uppercase; }
.counts .cell .v { font-size: 22px; font-weight: 800; }

/* ---------- daily performance (6 dept cards) ---------- */
.daily-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.dept-card { border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.dept-card .name { background: var(--navy-2); color: #fff; font-weight: 700; padding: 6px 10px; font-size: 13px; }
.dept-card .dyn { display: flex; justify-content: space-between; align-items: baseline; padding: 8px 10px; background: #f4f7fc; }
.dept-card .dyn .label { font-size: 11px; color: var(--muted); text-transform: uppercase; }
.dept-card .dyn .val { font-size: 20px; font-weight: 800; color: var(--navy); }
.dept-card .kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--line); }
.dept-card .kpis div { background: var(--card); padding: 6px 4px; text-align: center; }
.dept-card .kpis .k { font-size: 10px; color: var(--muted); display: block; }
.dept-card .kpis .v { font-weight: 700; }

/* ---------- pace grid (metrics x departments) ---------- */
table.pace { width: 100%; border-collapse: collapse; font-size: 13px; }
table.pace th, table.pace td { border: 1px solid var(--grid); padding: 5px 8px; text-align: right; white-space: nowrap; }
table.pace th { background: var(--navy-2); color: #fff; font-weight: 600; text-align: center; }
table.pace td.row-label, table.pace th.row-label { text-align: left; font-weight: 600; background: #f4f7fc; color: var(--ink); }
/* HEADER (top-left / column-header) BU cell = dark blue + white text — the row-DATA labels stay light.
   (Jeff: "the business unit header needs to be dark blue with white text." 6/22.) */
table.pace th.row-label { background: var(--navy-2); color: #fff; }
table.pace td.total { background: #eef3fb; font-weight: 700; }
table.pace tr.spacer td { border: 0; padding: 2px; }
/* Grouped tables (Daily Performance rows + the Pace grid columns) — the Daily-Huddle look: BLACK cell
   borders + WHITE spacer columns/rows between department groups (Elec · HVAC · Plumbing · Install ·
   Company), so each group reads as one bordered block. (Jeff 6/22.) */
table.pace.pace-grid th, table.pace.pace-grid td { border: 1px solid var(--grid); }
table.pace.pace-grid col.pg-sp { width: 12px; }
table.pace.pace-grid th.sp, table.pace.pace-grid td.sp { background: #fff !important; border: 0; padding: 0; }
table.pace.pace-grid tr.spacer td, table.pace.pace-grid tr.dp-gap td { border: 0; background: #fff; }
table.pace.pace-grid tr.dp-gap td { height: 9px; padding: 0; }
/* X'd cells → clean WHITE blank space (no tint, no border; collapse shows only the filled neighbours' edges) */
table.pace.pace-grid td.pg-blank { background: #fff !important; border: 0; }
/* Revenue Budget row stands out — bold values + a dark-blue label (Jeff 6/22: it was hard to pick out) */
table.pace.pace-grid tr.pace-emph td { font-weight: 800; }
table.pace.pace-grid tr.pace-emph td.row-label { background: var(--navy-2); color: #fff; }
/* HVAC Sales — black borders around the (green) boxes (Jeff 6/22) */
table.pace.hvac-tbl th, table.pace.hvac-tbl td { border-color: var(--grid); }

/* ---- Rounded "card" grid (matches the Daily Huddle): one <table>, but each BU group reads as its own
   rounded card. border-collapse:separate lets the corner cells round; directional borders (right+bottom on
   every cell, left on the first column, top on the top row) keep shared edges single — no doubling. The 4
   card-corner cells get a radius. (Jeff 6/27.) */
table.pace.rgrid { border-collapse: separate; border-spacing: 0; }
table.pace.rgrid th, table.pace.rgrid td { border: 0; }
/* thin internal gridlines on every card cell (so cells delineate, like the Daily Huddle) */
table.pace.rgrid .rc    { border-right: 1px solid var(--grid); border-bottom: 1px solid var(--grid); }
/* HEAVIER navy outer edges = the card border (matches the Daily Huddle's 2px navy frame) */
table.pace.rgrid .rc-l  { border-left: 2px solid var(--navy); }
table.pace.rgrid .rc-t  { border-top: 2px solid var(--navy); }
table.pace.rgrid .rc-r  { border-right: 2px solid var(--navy); }
table.pace.rgrid .rc-b  { border-bottom: 2px solid var(--navy); }
table.pace.rgrid .rc-tl { border-top-left-radius: 9px; }
table.pace.rgrid .rc-tr { border-top-right-radius: 9px; }
table.pace.rgrid .rc-bl { border-bottom-left-radius: 9px; }
table.pace.rgrid .rc-br { border-bottom-right-radius: 9px; }
/* gap rows/cols between cards = transparent space (the white card body shows through) */
table.pace.rgrid tr.dp-gap td, table.pace.rgrid td.sp, table.pace.rgrid th.sp { border: 0; background: transparent; padding: 0; }
table.pace.rgrid tr.dp-gap td { height: 10px; }
table.pace.rgrid col.pg-sp { width: 12px; }
table.pace.rgrid td.pg-blank { background: transparent; }   /* X'd-out cells stay clean white — no internal gridlines */
table.pace.rgrid td.pg-blank.pg-blank-b { border-bottom: 1px solid var(--grid); }   /* ...except ONE line at the very bottom of each white run, closing it off before the revenue rows (Jeff 6/27) */
/* a .tbl-wrap holding a rounded-card grid shouldn't add its own frame — the cards ARE the frame */
.tbl-wrap.tbl-plain { border: 0; box-shadow: none; background: transparent; }
/* clip a non-rgrid table's square corners to the wrap's rounded radius (kills the white corner triangles) */
.tbl-wrap.tbl-clip { overflow: hidden; }

/* REINS milestone bubble — compact "on pace vs goal" pill (green = hitting, red = missing); replaces the
   Company Total row at the bottom of each REINS card. (Jeff 6/27.) */
.rbub { margin-top: 10px; border: 2px solid var(--navy); border-radius: 12px; padding: 7px 12px; text-align: center; color: #fff; line-height: 1.15; }
.rbub.good { background: #117a3d; }
.rbub.bad  { background: #b3261e; }
.rbub-top  { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; opacity: .92; }
.rbub-pct  { font-size: 25px; font-weight: 800; }
.rbub-sub  { font-size: 11px; opacity: .94; }
/* The three REINS milestone bubbles laid out as a single row on the Daily Scoreboard. (Jeff 6/28.) */
.rbub-row { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 6px; }
.rbub-row .rbub { flex: 1 1 0; min-width: 200px; margin-top: 0; }
/* Month-to-date / Quarter-to-date row labels above each set of REINS bubbles. Dark + bold so they read as
   headers, not faded captions. (Jeff 6/28.) */
.rbub-sub-label { margin-top: 14px; font-size: 13px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .04em; color: var(--ink); }
.rbub-sub-label span { font-weight: 600; text-transform: none; letter-spacing: 0; opacity: .7; }

/* ---- Daily Scoreboard: department bubbles, APB-style (Jeff 6/28). Four trade-tinted rounded cards: a
   headline value + sub + optional pace pill, then a row of mini-stats. Backgrounds are forced light (like
   .cp-box) so the numbers stay readable in the evening screenshot regardless of theme. ---- */
.sb-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-top: 12px; }
@media (max-width: 1100px) { .sb-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px)  { .sb-grid { grid-template-columns: 1fr; } }
/* Phone: the Slack shot is read on a phone, so shrink the wide data tables to fit the screen — every column
   visible, no horizontal scroll/clip, no pinch-zoom. Long headers wrap so columns stay narrow; the numbers
   themselves stay on one line. Desktop (>620px) is untouched. (Jeff 6/29.) */
@media (max-width: 620px) {
  table.pace { font-size: 11px; }
  table.pace th, table.pace td { padding: 3px 4px; }
  table.pace th { white-space: normal; }
  .main { padding: 12px 8px 30px; }
  .sb-subhead { font-size: 12px; }
}
/* The whole bubble is filled with the dept color via the .bu-* tint class on .sb-card (Jeff 6/28). */
.sb-card { display: flex; flex-direction: column; background: #fff; border: 2px solid var(--navy);
  border-radius: 14px; overflow: hidden; box-shadow: 0 10px 24px -14px rgba(0,20,60,.35); }
.sb-head { padding: 8px 12px; font-size: 15px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .04em; color: var(--bu-ink); border-bottom: 1px solid rgba(20,35,63,.22); }
.sb-hero { text-align: center; padding: 12px 10px 4px; }
.sb-rev { font-size: 26px; font-weight: 800; color: var(--navy); line-height: 1.05; }
.sb-goal { margin-top: 3px; font-size: 12px; font-weight: 600; color: var(--muted); }
.sb-pace { margin: 8px 10px 0; border-radius: 10px; padding: 5px 8px; text-align: center;
  font-size: 12px; font-weight: 700; color: #fff; }
.sb-pace.good { background: #117a3d; } .sb-pace.bad { background: #b3261e; }
.sb-pace .sb-gap { margin-left: 6px; font-weight: 800; white-space: nowrap; }
.sb-stats { display: flex; margin-top: auto; border-top: 1px solid var(--grid); }
.sb-stat { flex: 1 1 0; padding: 8px 6px; text-align: center; border-right: 1px solid var(--grid); }
.sb-stat:last-child { border-right: 0; }
.sb-stat-v { font-size: 17px; font-weight: 800; color: var(--navy); line-height: 1.1; }
.sb-stat-v.dp-good { color: #117a3d; } .sb-stat-v.dp-bad { color: #b3261e; }
.sb-stat-sub { display: block; margin-top: 1px; font-size: 10px; font-weight: 700; color: var(--muted); }
.sb-stat-k { margin-top: 3px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); }
/* Clickable bottom-row count → flies out the records behind it (memberships / reviews / recalls). (Jeff 6/28.) */
.sb-stat-drill { cursor: pointer; }
.sb-stat-drill .sb-stat-v { text-decoration: underline dotted; text-decoration-color: var(--navy); text-underline-offset: 3px; }
.sb-stat-drill:hover { background: rgba(0,0,0,0.06); }
/* Small section sub-label inside a card (Memberships row in Today's Performance). Dark + bold so it reads
   as a header, not a faded caption. (Jeff 6/28.) */
.sb-subhead { margin-top: 14px; font-size: 13px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .04em; color: var(--ink); }
/* Small muted note appended to a huddle row label (e.g. "Actual - Total Revenue (colored vs Dynamic Budget)")
   — normal weight + lighter so it reads as a caption, not part of the bold label. (Jeff 6/28.) */
.hk-note { font-weight: 400; font-size: 11px; color: var(--muted); text-transform: none; letter-spacing: 0; }
/* How far the reviewed day missed its dynamic budget — a small second line under the actual revenue (Jeff 7/1). */
table.huddle-rep .hk-miss { display: block; font-size: 10px; font-weight: 700; letter-spacing: -.2px; line-height: 1.1; margin-top: 1px; }
/* Memberships sold today = one rounded bubble per department (Office incl.) — the company's membership push.
   The WHOLE bubble is filled with the dept color (the .bu-* tint class on .sb-mem). (Jeff 6/28.) */
.sb-memrow { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-top: 6px; }
.sb-mem { border: 2px solid var(--navy); border-radius: 12px; overflow: hidden; text-align: center; box-shadow: var(--shadow); }
.sb-mem-head { padding: 6px 5px 0; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; }
.sb-mem-v { padding: 4px 0 0; font-size: 28px; font-weight: 800; color: var(--navy); line-height: 1; }
.sb-mem-k { padding: 2px 0 8px; font-size: 10px; font-weight: 700; text-transform: uppercase; opacity: .72; }
@media (max-width: 720px) { .sb-memrow { grid-template-columns: repeat(2, 1fr); } }

/* Company — Monthly Revenue Pace (huddle bottom): the company-total revenue roll-up that replaced the
   duplicated wide Pace summary. (Jeff 6/27.) */
.cp-row { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 12px; }
.cp-box { flex: 1; min-width: 130px; text-align: center; background: #f4f7fc; border: 2px solid var(--navy); border-radius: 10px; padding: 12px 10px; }
.cp-box .cp-v { font-size: 22px; font-weight: 800; color: var(--navy); }
.cp-box .cp-k { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); font-weight: 700; margin-top: 4px; }
.cp-verdict { margin-top: 12px; border-radius: 12px; padding: 11px 16px; text-align: center; font-weight: 800; font-size: 16px; color: #fff; }
.cp-verdict.good { background: #117a3d; }
.cp-verdict.bad  { background: #b3261e; }
/* Per-department Monthly Revenue & Pace bubble at the bottom of each Daily-Huddle card (Jeff 6/27): green =
   on pace to hit the month's goal, red = behind. Compact pill that sits inside the card's bottom cell. */
.hbub { border-radius: 9px; padding: 5px 7px; color: #fff; line-height: 1.25; }
.hbub.good { background: #117a3d; } .hbub.bad { background: #b3261e; }
.hbub.mp-new { background: #14233f; }   /* new month, day 1 — neutral navy (not behind, just nothing produced yet) — Jeff 7/1 */
.hbub-line { display: flex; justify-content: space-between; gap: 8px; font-size: 11px; }
.hbub-line span { opacity: .82; }
.hbub-line b { font-weight: 800; }
.hbub-short { font-size: 12.5px; font-weight: 800; text-align: center; margin-top: 3px; padding-top: 3px; border-top: 1px solid rgba(255,255,255,.35); }
/* HVAC dept roll-up: revenue + pace arrow on ONE centered line (Jeff 6/29). */
.hbub-1line { display: flex; align-items: baseline; justify-content: center; gap: 4px; font-size: 13px; font-weight: 800; white-space: nowrap; }
.hbub-1line b { font-size: 15px; }
.hbub-arrow { font-weight: 800; }
/* Reviews detail — per-review list (Date · Dept · Technician · Rating · Customer · Platform). Technician
   + Customer left-aligned (these rules come after the .dp center rule, so equal specificity → they win). */
table.pace.reviews-detail { font-size: 12px; }
table.pace.reviews-detail td.rl-left, table.pace.reviews-detail th.rl-left { text-align: left; }
/* Goal coloring is TEXT-only (no whole-cell fill) so the trade tints read cleanly + the doc scans fast (Jeff 6/21) */
.beat { color: var(--good); font-weight: 700; } .miss { color: var(--bad); font-weight: 700; }
table.pace tr.hl-row td { font-weight: 800; }
/* Daily Performance: BU rows × metrics, numbers CENTERED, value text colored vs goal (legacy DPR look) */
table.pace.dp td:not(.row-label), table.pace.dp th:not(.row-label) { text-align: center; }
table.pace.dp td.dp-good { color: var(--good); font-weight: 700; }
table.pace.dp td.dp-bad { color: var(--bad); font-weight: 700; }
table.pace.dp td.dp-dyn { color: var(--navy); font-weight: 800; }
[data-theme="dark"] table.pace.dp td.dp-dyn { color: #cfe0ff; }
table.pace.dp td.dp-budget { color: var(--ink); }   /* daily budget = a static target; dark/normal-weight so it's legible, while the bold-navy Dynamic Budget stays the hero (Jeff 6/27) */
table.pace.dp td.dp-na { color: var(--muted); }
table.pace th .th-sub { font-size: 10px; font-weight: 600; opacity: .8; }
table.pace.dp tr.dp-total td { background: #eef3fb; font-weight: 800; border-top: 2px solid var(--navy-2); }
table.pace.dp tr.dp-total td.row-label { background: #e2e9f6; }
[data-theme="dark"] table.pace.dp tr.dp-total td { background: #16223c; }
/* AAP (membership) sales boxes in the header — Office + the three trade departments (4 across) */
.aap-counts { grid-template-columns: repeat(4, 1fr); }
.aap-counts .cell .v { font-size: 20px; }
/* membership conversion rate — one big box spanning the whole AAP section */
.aap-conv { display: flex; flex-direction: column; align-items: center; gap: 3px; margin-top: 12px;
  padding: 10px 14px; border-radius: 10px; background: var(--navy); color: #fff; text-align: center; }
.aap-conv span { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: #cdd8ee; font-weight: 700; }
.aap-conv strong { font-size: 28px; font-weight: 800; }   /* the % — centered, the focal point */
.aap-conv .aap-conv-calc { font-size: 12px; text-transform: none; letter-spacing: 0; color: #b9c6e3; font-weight: 600; }
/* Reviews & Recalls (formerly "Profit-Sharing Scorecard"): Reviews (narrow) + Recalls (wide), side by side, wraps on small screens */
.ps-row { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 12px; }
.ps-col { flex: 1; min-width: 260px; } .ps-col.ps-wide { flex: 1.8; min-width: 340px; }
.ps-h { font-weight: 700; font-size: 13px; margin-bottom: 6px; }
.ps-h span { color: var(--muted); font-weight: 600; font-size: 11px; margin-left: 4px; }
table.pace tr.hl-row td.row-label { background: #e9f0fb; color: var(--navy); }
/* Leads & Top Campaigns: give each source row its own non-trade accent so it's not just text; BLACK
   borders so the grid stays crisp once the cells are colored (Jeff 6/22). */
table.pace.leads-tbl th, table.pace.leads-tbl td { border-color: var(--grid); }
/* Lead-source row tints (Jeff 6/28): Leads = pink-rose, Outbound = green, TGL = orange. Online/Flips retired. */
table.pace.leads-tbl tr.lead-leads td,    table.pace.leads-tbl tr.lead-leads td.row-label    { background: #F7D2DF; }  /* pink rose */
table.pace.leads-tbl tr.lead-outbound td, table.pace.leads-tbl tr.lead-outbound td.row-label { background: #CFE9D6; }  /* green */
table.pace.leads-tbl tr.lead-tgl td,      table.pace.leads-tbl tr.lead-tgl td.row-label      { background: #FBDDB5; }  /* orange */
/* Top Campaigns medal ranking: #1 gold, #2 silver, #3 bronze (Jeff 6/28) */
table.pace.leads-tbl tr.camp-1 td, table.pace.leads-tbl tr.camp-1 td.row-label { background: #F2DA8A; }  /* gold (#1) */
table.pace.leads-tbl tr.camp-2 td, table.pace.leads-tbl tr.camp-2 td.row-label { background: #D5D9DD; }  /* silver (#2) */
table.pace.leads-tbl tr.camp-3 td, table.pace.leads-tbl tr.camp-3 td.row-label { background: #E6B380; }  /* bronze (#3) */
table.pace.leads-tbl tr.dp-gap td { height: 16px; }   /* a touch more white space between the Leads / Top-Campaigns cards (Jeff 6/27) */
.coming-soon { text-align: center; padding: 8px 8px 28px; }
.coming-soon .section-band { text-align: left; }

/* ---------- Backlog (sold, not yet installed — grouped by scheduled month) ---------- */
/* Trade colors (Jeff's convention, matched to the board report's Target-Margins table):
   Electrical = yellow, HVAC = green, Plumbing = blue/water. */
:root { --bu-electrical: #FFF2CC; --bu-hvac: #C6E0B4; --bu-plumbing: #BDD7EE; --bu-ink: #14233f;
        --bu-office: #FCDDB3; }   /* Office = soft orange (neutral — NOT red, which reads as "bad"). Jeff 6/22. */
/* Trade tint on ANY cell/box/row that NAMES a business unit — one color system across the whole DPR:
   Electrical = yellow, HVAC = green, Plumbing = blue, Office = orange (matches the board report's
   Target-Margins table). !important so it wins over the navy headers / gray row-labels / sticky cells
   these classes land on. Company Total keeps its summary styling. (Jeff 6/21–22.) */
.bu-electrical { background: var(--bu-electrical) !important; color: var(--bu-ink) !important; }
.bu-hvac       { background: var(--bu-hvac) !important;       color: var(--bu-ink) !important; }
.bu-plumbing   { background: var(--bu-plumbing) !important;   color: var(--bu-ink) !important; }
.bu-office     { background: var(--bu-office) !important;     color: var(--bu-ink) !important; }
/* Background-ONLY trade tint (no forced text color) — for full data ROWS (Daily Performance, Recalls)
   and full data COLUMNS (the Pace grid), where each cell's own green/red goal text must still show. */
table.pace.dp tr.bu-electrical td { background: var(--bu-electrical); }
table.pace.dp tr.bu-hvac td       { background: var(--bu-hvac); }
table.pace.dp tr.bu-plumbing td   { background: var(--bu-plumbing); }
table.pace.dp tr.bu-office td     { background: var(--bu-office); }   /* Reviews "Office" row (orange, like AAP) */
.bu-bg-electrical { background: var(--bu-electrical); }
.bu-bg-hvac       { background: var(--bu-hvac); }
.bu-bg-plumbing   { background: var(--bu-plumbing); }
/* Keep NON-goal cells' text dark on the tint in both light + dark themes; goal cells keep their own
   green/red/navy (the :not() excludes them so the signal still pops). */
table.pace.dp tr.bu-electrical td:not(.dp-good):not(.dp-bad):not(.dp-dyn),
table.pace.dp tr.bu-hvac td:not(.dp-good):not(.dp-bad):not(.dp-dyn),
table.pace.dp tr.bu-plumbing td:not(.dp-good):not(.dp-bad):not(.dp-dyn),
table.pace.dp tr.bu-office td:not(.dp-good):not(.dp-bad):not(.dp-dyn),
table.pace.dp td.bu-bg-electrical:not(.beat):not(.miss),
table.pace.dp td.bu-bg-hvac:not(.beat):not(.miss),
table.pace.dp td.bu-bg-plumbing:not(.beat):not(.miss) { color: var(--bu-ink); }
/* top summary = Daily-Huddle look: BLACK cell borders, thin WHITE spacer columns between trade groups,
   navy/white headers (like the rest + the Company column), pastel trade tint on DATA cells only, numbers
   centered. */
table.pace.bl-summary { border-collapse: collapse; }
table.pace.bl-summary th, table.pace.bl-summary td { border: 1px solid var(--grid); }
table.pace.bl-summary td:not(.row-label):not(.bl-sp), table.pace.bl-summary th:not(.row-label):not(.bl-sp) { text-align: center; }
table.pace.bl-summary th { font-weight: 700; }   /* dept headers stay navy/white via base table.pace th */
table.pace.bl-summary td.bl-col-electrical { background: var(--bu-electrical); color: var(--bu-ink); }
table.pace.bl-summary td.bl-col-hvac { background: var(--bu-hvac); color: var(--bu-ink); }
table.pace.bl-summary td.bl-col-plumbing { background: var(--bu-plumbing); color: var(--bu-ink); }
/* white spacer columns between trade groups (no borders → a clean white gap, like the huddle) */
table.pace.bl-summary col.bl-sp { width: 12px; }
table.pace.bl-summary col.bl-lbl { width: 96px; }
table.pace.bl-summary th.bl-sp, table.pace.bl-summary td.bl-sp { background: #fff; border: 0; padding: 0; }
/* list */
table.pace.bl-list td, table.pace.bl-list th { text-align: left; }
table.pace.bl-list td.c, table.pace.bl-list th.c { text-align: center; }
table.pace.bl-list td.r, table.pace.bl-list th.r { text-align: right; }
/* month / TBD group header row spanning the table */
table.pace.bl-list tr.bl-group td { background: var(--navy-2); color: #fff; font-weight: 700;
  text-align: left; letter-spacing: .02em; }
table.pace.bl-list tr.bl-group td.r { text-align: right; }
/* Hold rows: NEUTRAL gray tint (not yellow — yellow now means "Electrical" in this tab's color system,
   so a yellow Hold row read as an electrical job). Status column still says "Hold". */
table.pace.bl-list tr.bl-hold td { background: #eef1f5; color: var(--bu-ink); }
/* Stalled rows: AMBER flag — sold work parked with no upcoming appointment (last appt long past). Status
   reads "Stalled since MM/YY" so the team chases the big ones (Jeff 6/22). */
table.pace.bl-list tr.bl-stalled td { background: #fce6c5; color: var(--bu-ink); }
table.pace.bl-list tr.bl-stalled td.bl-stat { color: #9a6a00; font-weight: 700; white-space: nowrap; }
/* dept badge chips — same trade colors as the top section so the tab is one color system */
.bl-badge { display: inline-block; font-size: 11px; font-weight: 700; padding: 1px 8px; border-radius: 999px;
  color: var(--bu-ink); letter-spacing: .02em; white-space: nowrap; border: 1px solid rgba(20,35,63,.18); }
.bl-badge.bl-electrical { background: var(--bu-electrical); }
.bl-badge.bl-hvac { background: var(--bu-hvac); }
.bl-badge.bl-plumbing { background: var(--bu-plumbing); }

/* ---------- Pace Report (wide daily-entries grid + summary, mirrors the legacy sheet) ---------- */
table.pace-report { font-size: 11px; }
table.pace-report th, table.pace-report td { padding: 3px 6px; }
/* sticky left "Day" column so dept columns scroll under it */
table.pace-report th.row-label, table.pace-report td.row-label {
  position: sticky; left: 0; z-index: 3; min-width: 78px; box-shadow: 1px 0 0 var(--line); }
table.pace-report thead th.row-label { z-index: 4; }
/* dept-group separators: a heavier left border on the first column of each group */
table.pace-report th.grp, table.pace-report td.grp { border-left: 2px solid var(--navy-2); }
table.pace-report thead tr:first-child th { font-size: 12px; }
/* weekend (reported, not in pace) rows muted + italic */
table.pace-report tr.weekend td { color: var(--muted); font-style: italic; }
table.pace-report tr.weekend td.row-label { font-style: italic; }
/* week-total rows */
table.pace-report tr.wk-total td { background: #f4f7fc; font-weight: 700; border-top: 1px solid var(--navy-2); }
table.pace-report tr.wk-total td.row-label { background: #e9eef7; }
/* summary block at the bottom */
table.pace-report tr.pr-divider td { background: var(--navy-2); color: #fff; font-weight: 700;
  text-align: left; padding: 5px 10px; position: sticky; left: 0; }
table.pace-report tr.sum-row td { background: #fbfcfe; }
table.pace-report tr.sum-row td.row-label { background: #eef3fb; }
/* goal coloring — company summary only: green = pace at/above budget, red = behind. TEXT-only (keeps the
   sum-row background; colored text reads against it), so no whole-cell fill (Jeff 6/21). */
table.pace-report tr.sum-row td.beat { color: var(--good); font-weight: 700; }
table.pace-report tr.sum-row td.miss { color: var(--bad); font-weight: 700; }
/* the Pace row is the headline — make the whole row stand out as a band */
table.pace-report tr.pace-hl td { font-weight: 800; border-top: 2px solid var(--navy); border-bottom: 2px solid var(--navy); }
table.pace-report tr.pace-hl td.row-label { background: var(--navy); color: #fff; }
/* drillable daily cells */
table.pace-report td.drill { cursor: pointer; }
table.pace-report td.drill:hover { outline: 2px solid var(--blue); outline-offset: -2px; background: #eaf1ff; }

/* Revenue $ cells that fly out the jobs behind them (Jeff 7/9): the Daily Scorecard's Revenue column, the
   management DPR's Daily Revenue column, and the Pace grid's Revenue Total row. Dotted underline signals
   clickable without disturbing the green/red goal tint the cell already carries. */
td.rjd { cursor: pointer; text-decoration: underline dotted rgba(0, 0, 0, .45); text-underline-offset: 3px; }
td.rjd:hover { outline: 2px solid var(--blue); outline-offset: -2px; }
/* Monthly Department Scoreboard hero $: sits on a saturated dept-colored card, so use a light underline. */
.sb-rev-drill { cursor: pointer; border-bottom: 2px dotted rgba(255, 255, 255, .55); }
.sb-rev-drill:hover { border-bottom-color: #fff; }
/* Huddle "Actual Total - Jobs Run" totals that drill to the ServiceTitan jobs behind the count (Jeff 6/24).
   Dark-navy cells with white text → a dotted underline signals clickable; white outline on hover. */
table.huddle-rep td.hdrill { cursor: pointer; text-decoration: underline dotted; text-decoration-color: currentColor; text-underline-offset: 3px; }
table.huddle-rep td.hdrill:hover { outline: 2px solid currentColor; outline-offset: -2px; }
/* "Sold Revenue" — sold work going to the backlog, ONE centered cell per group (Jeff 6/24; recolored to the
   light-blue fill + centered per group, 7/1). Sits right above the 🏆 Won the Day row. The 🎉 label still calls
   it out so the team celebrates the sale even when daily revenue looks low. */
table.huddle-rep tr.sr-row td { background: #e9f0fb; color: var(--navy); font-weight: 800; }
table.huddle-rep tr.sr-row td.sp { background: #fff; }   /* keep the BU gaps white — no fill bleed (Jeff 6/26) */
table.huddle-rep td.sr-lbl { background: #fff; color: var(--ink); font-weight: 800; }
table.huddle-rep td.sr-cell { text-align: center; }
/* Huddle's Company-Summary block: center the numbers (matches the huddle's other tables); labels stay left. */
table.pace.hud-pace td:not(.row-label) { text-align: center; }

/* ---------- Daily Huddle (1:1 replica; black cell borders, white BU separators, equal columns) ---------- */
/* width:100% stretches the fixed columns proportionally so the table fills the card and lines up with the
   full-width navy section-band header (Jeff 6/26 — no more right-side gap). */
table.huddle-rep { border-collapse: separate; border-spacing: 0; table-layout: fixed; width: 100%; font-size: 11.5px; }
table.huddle-rep col.c-lbl { width: 208px; }
table.huddle-rep col.c-data { width: 58px; }     /* equal Maint / Service / Revenue / Jobs / … columns */
table.huddle-rep col.c-data2 { width: 116px; }    /* top HVAC Install (1 col) = 2× so it lines up with the bottom's Revenue+Jobs */

/* Pace Report: mirrored horizontal scrollbar above the table (synced in JS) so you can scroll right
   from the top without scrolling down to the table's own bar. */
.pr-scroll-top { overflow-x: auto; overflow-y: hidden; }
.pr-scroll-top > div { height: 1px; }

/* Rounded frame on ALL FOUR corners of the Pace tables (live / month / annual) — SAME fix as #prodCard
   (Jeff 6/28), re-applied here (Jeff 7/10; the annual table's corners looked unclosed). With
   border-collapse the table's own square black outer borders paint OVER the .pr-scroll-body wrapper's
   rounded 12px clip, so the corners never round. Fix: the table sheds its OUTER edges and the wrapper's own
   1px border (made black + already radius:12 + overflow clips it) becomes the rounded frame; inner
   gridlines stay 1px black. If you ever see square/unclosed corners on a bordered report table in a rounded
   .tbl-wrap, THIS is the fix — don't hand-round individual corners. */
.pr-scroll-body { border-color: var(--grid); }
table.pace-report { border: 0; }
table.pace-report thead tr:first-child > * { border-top: 0; }
table.pace-report tbody tr:last-child > * { border-bottom: 0; }
table.pace-report tr > *:first-child { border-left: 0; }
table.pace-report tr > *:last-child { border-right: 0; }

/* Pace tab mode bar: This Month (live) · closed months · Annual. */
.pace-modebar { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.pace-mode-btn { font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; border-radius: 999px;
  padding: 5px 14px; border: 1px solid var(--line); background: var(--card); color: var(--ink); }
.pace-mode-btn:hover { border-color: var(--navy); }
.pace-mode-btn.active { background: var(--navy); color: #fff; border-color: var(--navy); }
table.pace-report.annual-rollup td.row-label { min-width: 84px; }
table.huddle-rep col.c-sp { width: 13px; }        /* minimal-width white column between business units */
table.huddle-rep th, table.huddle-rep td { padding: 4px 6px;
  text-align: center; white-space: nowrap; color: #14233f; overflow: hidden; }   /* all numbers centered */
table.huddle-rep th { background: var(--navy-2); color: #fff; font-weight: 600; text-align: center; }
table.huddle-rep .hk { text-align: left; font-weight: 600; position: sticky; left: 0; z-index: 2; border-bottom: 1px solid var(--grid); }   /* inner row gridline on the colored label column so the pink/purple/green sections match the data cells' borders (Jeff 6/27); the last row's .hb-b navy edge still overrides */
table.huddle-rep th.hk { background: var(--navy-2); }
table.huddle-rep .sp { background: #fff; padding: 0; }   /* white gap between the BU cards */
/* Each BU group = its own rounded card (Jeff 6/26 "bubble" look). Soft-gray borders via the right+bottom
   technique (border-spacing 0 → no doubling): every group cell gets right+bottom, the card's left/top edges add
   .hb-l/.hb-t, and the 4 corner cells round. The white .sp spacer columns are the gaps between cards. */
table.huddle-rep .hb { border-right: 1px solid var(--grid); border-bottom: 1px solid var(--grid); }   /* thin gridlines INSIDE each card so the cells delineate (Jeff 6/26 — they were blending on the light-blue fills) */
/* Navy card OUTLINE — the perimeter edges (left/top/right/bottom) so each card stands out separately, like the
   backlog cards; the soft-gray gridlines above stay INSIDE the card (Jeff 6/26). */
table.huddle-rep .hb-l { border-left: 2px solid var(--navy); }
table.huddle-rep .hb-r { border-right: 2px solid var(--navy); }
table.huddle-rep .hb-t { border-top: 2px solid var(--navy); }
table.huddle-rep .hb-b { border-bottom: 2px solid var(--navy); }
table.huddle-rep .hb-rtl { border-top-left-radius: 8px; }
table.huddle-rep .hb-rtr { border-top-right-radius: 8px; }
table.huddle-rep .hb-rbl { border-bottom-left-radius: 8px; }
table.huddle-rep .hb-rbr { border-bottom-right-radius: 8px; }
/* a WHITE N/A cell borders only the side facing a colored cell (white-to-white stays clean) — Jeff 6/26 */
table.huddle-rep .hb-bb { border-bottom: 1px solid var(--grid); }
table.huddle-rep .hb-rr { border-right: 1px solid var(--grid); }
table.huddle-rep .hb-ll { border-left: 1px solid var(--grid); }   /* left divider for a yellow cell whose white left-neighbor never drew one (Jeff 6/29) */
/* AAP "Made/Missed Goal" status shrunk so it fits + centers in the narrow AAP column (Jeff 6/26) */
table.huddle-rep .hgoal { font-size: 9.5px; letter-spacing: -.2px; }
/* Always-on yellow input cells (Excel-style entry). The input fills the cell; one click focuses it. */
table.huddle-rep td.hcell-in { padding: 0; }
table.huddle-rep input.hin { width: 100%; box-sizing: border-box; border: 0; background: transparent;
  text-align: center; font: inherit; color: inherit; padding: 4px 6px; margin: 0; -moz-appearance: textfield; }
table.huddle-rep input.hin:focus { outline: 2px solid var(--blue); outline-offset: -2px; background: #fffbe6; }

/* Daily Huddle: company "daily goal vs actual revenue" bubble below the top section (Jeff 6/23).
   One long pill — GREEN when we made the day's revenue goal, RED when we fell short. */
.huddle-goal { margin-top: 14px; padding: 12px 26px; border-radius: 999px; color: #fff;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px 22px;
  box-shadow: 0 2px 8px rgba(0,0,0,.18); text-align: center; }
.huddle-goal.hg-good { background: #117a3d; }
.huddle-goal.hg-bad { background: #b3261e; }
.huddle-goal .hg-pair { display: inline-flex; align-items: baseline; gap: 9px; }
.huddle-goal .hg-lbl { font-weight: 600; opacity: .9; text-transform: uppercase; letter-spacing: .05em; font-size: 12px; }
.huddle-goal .hg-val { font-size: 21px; font-weight: 800; }
.huddle-goal .hg-vs { opacity: .6; font-weight: 600; font-size: 13px; }
.huddle-goal .hg-tag { padding: 3px 13px; border-radius: 999px; background: rgba(255,255,255,.22);
  font-size: 13px; font-weight: 700; }

/* ---------- 3-Day Call Board (faithful sheet rebuild; YELLOW = office-entered, BLUE = calculated) ----------
   Thin black cell borders + white spacer columns between the label and each day — same look as the Daily Huddle. */
table.callboard { width: 100%; border-collapse: collapse; font-size: 12px; table-layout: fixed; }
/* 3-Day Call Board — each day a rounded card (navy outline + rounded corners), matching the other reports. (Jeff 6/27.) */
table.callboard.rgrid { border-collapse: separate; border-spacing: 0; }
table.callboard.rgrid th, table.callboard.rgrid td { border: 0; }
table.callboard.rgrid .rc   { border-right: 1px solid var(--grid); border-bottom: 1px solid var(--grid); }
table.callboard.rgrid .rc-l { border-left: 2px solid var(--navy); }
table.callboard.rgrid .rc-t { border-top: 2px solid var(--navy); }
table.callboard.rgrid .rc-r { border-right: 2px solid var(--navy); }
table.callboard.rgrid .rc-b { border-bottom: 2px solid var(--navy); }
table.callboard.rgrid .rc-tl { border-top-left-radius: 9px; }
table.callboard.rgrid .rc-tr { border-top-right-radius: 9px; }
table.callboard.rgrid .rc-bl { border-bottom-left-radius: 9px; }
table.callboard.rgrid .rc-br { border-bottom-right-radius: 9px; }
table.callboard.rgrid .sp { border: 0; }
table.callboard col.cb-lbl { width: 150px; } table.callboard col.cb-data { width: 60px; } table.callboard col.cb-sp { width: 12px; }
table.callboard th, table.callboard td { border: 1px solid var(--grid); padding: 3px 6px; text-align: center;
  white-space: nowrap; color: #14233f; overflow: hidden; }
table.callboard th { background: var(--navy-2); color: #fff; font-weight: 600; }
table.callboard th.cb-dayhead { font-size: 13px; }
table.callboard th.cb-sub { font-size: 10.5px; font-weight: 600; background: var(--navy); white-space: normal; line-height: 1.1; }
/* business-unit / row headers = dark blue with white text (Jeff 6/22) */
table.callboard td.row-label, table.callboard th.row-label { text-align: left; font-weight: 600; background: var(--navy-2); color: #fff;
  position: sticky; left: 0; z-index: 2; box-shadow: 1px 0 0 #000; }
table.callboard td.row-label .cb-mut { color: #b9c6e3; }   /* "Glendora" sublabel stays legible on navy */
/* white spacer column between the label and each day (mirrors the huddle's BU gaps) */
table.callboard .sp { background: #fff; border-top: 0; border-bottom: 0; padding: 0; }
/* YELLOW = office-entered; borderless in-cell input until hover/focus (reads like a spreadsheet) */
table.callboard td.cb-y { background: var(--yellow); }
table.callboard td.cb-y input.cb-in { font: inherit; width: 100%; min-width: 0; border: 1px solid transparent; background: transparent;
  border-radius: 4px; padding: 2px 3px; text-align: center; color: #14233f; }
table.callboard td.cb-y input.cb-in:hover { border-color: var(--yellow-line); }
table.callboard td.cb-y input.cb-in:focus { border-color: var(--blue); background: #fff; outline: none; }
/* BLUE = auto / calculated */
table.callboard td.cb-b { background: #e3ecfb; color: var(--navy); font-weight: 600; }
/* Jobs Needed: colored TEXT on the blue (calculated) cell — red = behind / need more, green = met or
   ahead. No whole-cell red/green fill anymore (Jeff 6/21). */
table.callboard td.cb-need { font-weight: 700; background: #e3ecfb; }
table.callboard td.cb-behind { color: var(--bad); }
table.callboard td.cb-met, table.callboard td.cb-ahead { color: var(--good); }
/* not-applicable cells (gray, never a value) */
table.callboard td.cb-na { background: #e7ebf1; }
/* like the Daily Huddle, the board keeps its meaning-carrying colors in both themes */
table.callboard .cb-mut { color: #6f86ad; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; }
/* weather: temp tints + the HVAC business read (good = green, slow = amber) */
table.callboard td.cb-hot { background: #fbe0cf; color: #8a3b12; }
table.callboard td.cb-cold { background: #d6ebfa; color: #14517a; }
table.callboard td.cb-wx-good { background: #e3f5ea; color: #14633a; }
table.callboard td.cb-wx-slow { background: #fff2cf; color: #7a5a00; }
/* footnote legend chips */
.cb-leg-red, .cb-leg-grn { font-weight: 700; padding: 0 4px; border-radius: 4px; color: #fff; }
.cb-leg-red { background: #e06666; } .cb-leg-grn { background: #6aa84f; }
/* admin jobs-per-tech targets (the seasonal knob behind Min. Bdgt) */
.cb-targets { margin-top: 12px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; background: #f4f7fc; }
[data-theme="dark"] .cb-targets { background: #0f1830; }
.cb-targets-h { font-weight: 700; font-size: 12px; margin-bottom: 8px; color: var(--ink); }
.cb-targets-h .cb-mut { color: var(--muted); margin-left: 6px; }
.cb-targets-row { display: flex; flex-wrap: wrap; gap: 10px; }
.cb-tgt { display: flex; flex-direction: column; gap: 3px; font-size: 11px; color: var(--muted); font-weight: 600; }
.cb-tgt span { white-space: nowrap; }
.cb-tgt-in { width: 64px; font: inherit; padding: 4px 6px; border: 1px solid var(--line); border-radius: 6px;
  text-align: center; background: var(--card); color: var(--ink); font-weight: 700; }
.cb-tgt-in:focus { border-color: var(--blue); outline: none; }

/* ---------- drill-down modal (the ServiceTitan jobs behind a cell) ---------- */
/* FLEX, not grid (Jeff 7/9). This was `display:grid; place-items:center`, whose single auto-sized column takes
   the modal's MAX-CONTENT width (880px). The modal's `max-width:100%` then resolved against that 880px column,
   so it never clamped: on a 390px phone the overlay measured 390px but the modal still rendered 880px and the
   right-hand Revenue column sat ~490px off-screen with no way to scroll to it. Flex centering makes the
   percentage resolve against the overlay's real width. `min-width:0` lets the modal shrink below its content. */
/* `max-width:100vw` matters as much as the flex switch: `inset:0` sizes the overlay to the containing block,
   which the page's 750px content widens on a phone, so the centered modal was pushed half off-screen (measured
   left=195px on a 375px display) even once its own width was clamped. 100vw stays the real screen width. On
   desktop this never binds, so the modal still centers at 880px. */
.modal-ov { position: fixed; inset: 0; max-width: 100vw; background: rgba(10,20,40,.55);
  display: flex; align-items: center; justify-content: center; z-index: 100;
  padding: clamp(8px, 2vw, 20px); }   /* shrinks on phones without depending on a media query firing */
/* Clamp to the VISUAL viewport, not just the overlay. The DPR page's own content is ~750px wide (the topbar's
   min-content), which widens the containing block a fixed-position overlay resolves `100%` against — measured
   750px on a 390px phone. `100vw` stays 390px there, so min() of the two is correct in both cases, and on
   desktop `width:880px` still wins because it is smaller than either bound. */
.modal { background: var(--card); color: var(--ink); border-radius: 12px; box-shadow: 0 12px 44px rgba(0,0,0,.32);
  width: 880px; max-width: min(100%, calc(100vw - 16px)); min-width: 0; max-height: 86vh;
  display: flex; flex-direction: column; }
.modal-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
  padding: 13px 18px; background: var(--navy); color: #fff; border-radius: 12px 12px 0 0; }
.modal-head .small.muted { color: #cdd8ee; }
.modal-head .x { background: transparent; border: 1px solid rgba(255,255,255,.4); color: #fff;
  border-radius: 8px; padding: 4px 10px; cursor: pointer; font: inherit; }
.modal-body { padding: 14px 18px; overflow: auto; -webkit-overflow-scrolling: touch; }
table.drill-table { width: 100%; border-collapse: collapse; font-size: 13px; }
table.drill-table th, table.drill-table td { border-bottom: 1px solid var(--line); padding: 6px 9px;
  text-align: left; white-space: nowrap; }
table.drill-table th { color: var(--muted); font-weight: 600; }
/* Money never wraps — a $ split across two lines is unreadable, and it's the column people came for. */
table.drill-table td.r, table.drill-table th.r { text-align: right; white-space: nowrap; }
table.drill-table td.c, table.drill-table th.c { text-align: center; }
table.drill-table tr.drill-open td { background: var(--yellow); }
/* An EXPIRED callback: still a recall job (keeps its ↺), but the original completed >180 days earlier so it
   never scores against the recall rate (Jeff 7/9). Faded, with the age on hover — the flyout's Recall total
   counts only the solid ones, which is what makes it tie to the department's Recall cell. */
table.drill-table .recall-expired { opacity: .38; cursor: help; }
table.drill-table tr.drill-total td { font-weight: 700; border-top: 2px solid var(--navy); color: var(--ink); }
/* Per-day subtotal row inside a multi-day (weekend/holiday) drill — lighter than the grand total. (Jeff 6/29.) */
table.drill-table tr.drill-subtotal td { font-weight: 700; background: #eef2f7; border-top: 1px solid var(--navy-2); color: var(--ink); }
/* Per-department subtotal row (Service vs Maintenance) — a touch stronger than a day subtotal. (Jeff 6/29.) */
table.drill-table tr.drill-dept td { font-weight: 800; background: #dde6f1; border-top: 1px solid var(--navy); color: var(--navy); }
table.drill-table .ok { color: var(--good); font-weight: 700; }
table.drill-table .no { color: var(--warn); font-weight: 700; }
/* Production-revenue flyout: actual vs dept goal (green/red, like the card's Actual row), muted goal, total row */
table.drill-table td.good { color: var(--good); font-weight: 700; }
table.drill-table td.bad { color: var(--bad); font-weight: 700; }
table.drill-table td.gm { color: var(--muted); }
/* "JT Missing" — ServiceTitan returned no job type, so the row has no reason AND the Tech-to-Call exclusion
   (which keys off the job type) could not have run on it. Amber chip: needs a human to look, not an error. */
table.drill-table .jt-missing { display: inline-block; font-size: 11px; font-weight: 700; color: #8a5a00;
  background: #fff2d6; border: 1px solid #e6cf9a; border-radius: 4px; padding: 1px 6px; cursor: help; }
table.drill-table td.tot { font-weight: 700; border-top: 2px solid var(--navy-2); }
.drill-admin { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line);
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.drill-admin input { font: inherit; width: 120px; padding: 6px 8px; border: 1px solid var(--line); border-radius: 6px; }

/* Revenue flyout table (Jeff 7/9). `table-layout: fixed` + a colgroup makes the table lay out to the MODAL's
   width instead of its own content width, so the Revenue column's right edge can never leave the screen — on a
   phone the content min-width was ~544px inside a 359px modal and the $ column fell off. The narrow columns are
   sized in em (they scale with the font-size drop below); Customer absorbs the remainder and wraps. Deliberately
   scoped to .drill-rev so the other flyouts (huddle, production, AR) keep their auto layout. */
table.drill-rev { table-layout: fixed; width: 100%; }
/* The base .drill-table rule sets `white-space: nowrap` on EVERY cell. Inside a fixed-layout table that made a
   long customer name ("Wheeler Steffen Prop Mgmt (Lily Eibert)", 192px of text in an 88px cell) render on one
   line and paint straight over the Lead Tech column. Text columns wrap; only the $ keeps nowrap. */
table.drill-rev th, table.drill-rev td { white-space: normal; overflow-wrap: anywhere; }
table.drill-rev td.r, table.drill-rev th.r { white-space: nowrap; }
table.drill-rev col.c-job  { width: 5.6em; }
table.drill-rev col.c-date { width: 4.6em; }
table.drill-rev col.c-tech { width: 5.8em; }
table.drill-rev col.c-rev  { width: 6em; }
/* Customer (col.c-cust) is intentionally unsized — it takes whatever is left. */

/* Phones (Jeff 7/9): reclaim horizontal room so all five flyout columns fit without a sideways scroll —
   Job # / Date / Customer / Lead Tech / Revenue. The $ never wraps (td.r is nowrap above). NOTE: this query
   is a bonus, not the fix — the DPR page's own 750px content can widen the layout viewport a media query
   evaluates against, so the fix above must hold without it. */
@media (max-width: 640px) {
  .modal-ov { padding: 8px; }
  .modal { max-height: 92vh; }
  .modal-head { padding: 11px 12px; }
  .modal-body { padding: 10px 12px; }
  table.drill-table { font-size: 11.5px; }
  table.drill-table th, table.drill-table td { padding: 5px 6px; }
}
.drill-admin .btn { background: var(--navy); color: #fff; border: 0; border-radius: 8px;
  padding: 7px 14px; font-weight: 600; cursor: pointer; width: auto; }
.ovr { position: relative; } .ovr::after { content: "✎"; position: absolute; top: 1px; right: 2px; font-size: 9px; color: var(--warn); }

/* ---------- editable ---------- */
.editable { cursor: text; background: var(--yellow); border-bottom: 1px dashed var(--yellow-line); }
[data-role="viewer"] .editable { cursor: default; background: transparent; border-bottom: 0; }
.edit-input { font: inherit; width: 100%; border: 1px solid var(--blue); border-radius: 6px; padding: 4px 6px; }
.muted { color: var(--muted); } .small { font-size: 12px; }

/* ---------- print / screenshot ---------- */
body.print { background: #fff; }
.shell.print { display: block; height: auto; }
body.print .sidebar, body.print .topbar, body.print .no-print { display: none !important; }
body.print #main { padding: 0; background: #fff; }
body.print #dpr { width: 1180px; max-width: 100%; margin: 0 auto; gap: 10px; }
@media (max-width: 1220px) { .main #dpr { width: 100%; } .daily-grid { grid-template-columns: repeat(2, 1fr); }
  table.pace { font-size: 12px; } .header-grid { grid-template-columns: 1fr; } }

/* ---------- AR Report (cross-app, shared with Level 10) ---------- */
.ar-dpr .ov-sub { font-size: 18px; font-weight: 800; color: var(--navy); margin: 4px 0 10px; padding-bottom: 6px; border-bottom: 2px solid var(--gold); }
.ar-dpr .ar-sum-row { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }
.ar-dpr .ar-sum-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; font-weight: 700; }
.ar-dpr .ar-sum-val { font-size: 30px; font-weight: 800; color: var(--navy); line-height: 1.05; }
.ar-dpr .ar-sum-dates { font-size: 12.5px; color: var(--ink); margin-top: 4px; }
.ar-dpr .ar-sum-buckets { display: flex; gap: 10px; margin-left: auto; flex-wrap: wrap; }
.ar-dpr .ar-box { min-width: 96px; text-align: center; border-radius: 10px; padding: 8px 14px; border: 1px solid rgba(0,0,0,.10); user-select: none; }
.ar-dpr .ar-box-lbl { font-size: 11px; font-weight: 700; color: #14233f; opacity: .8; }
.ar-dpr .ar-box-val { font-size: 18px; font-weight: 800; color: #14233f; margin-top: 1px; }
.ar-dpr .ar-box-cur { background: #e2efd9; } .ar-dpr .ar-box-30 { background: #ffe699; }
.ar-dpr .ar-box-60 { background: #ffc9a0; } .ar-dpr .ar-box-90 { background: #f4a3a3; }
.ar-dpr .ar-age { padding: 1px 7px; border-radius: 6px; font-size: 11px; font-weight: 700; color: #14233f; white-space: nowrap; }
.ar-dpr .ar-age.ar-cur { background: #cfe8bd; } .ar-dpr .ar-age.ar-b30 { background: #ffe699; }
.ar-dpr .ar-age.ar-b60 { background: #ffc9a0; } .ar-dpr .ar-age.ar-b90 { background: #f4a3a3; }
.ar-dpr td.ar-bal90 { color: #b42318; font-weight: 700; }
/* Navy rounded frame + grid inner lines so the card corners read BLUE like the other report tables (Jeff 6/28):
   separate borders (right+bottom on every cell, navy 2px on the 4 outer edges) + radii on the 4 corner cells. */
.ar-dpr table.ar-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12px; background: #fff; color: #14233f; }
.ar-dpr table.ar-table th, .ar-dpr table.ar-table td { border-right: 1px solid var(--grid); border-bottom: 1px solid var(--grid); padding: 4px 9px; text-align: center; white-space: nowrap; }
.ar-dpr table.ar-table th:first-child, .ar-dpr table.ar-table td:first-child { border-left: 2px solid var(--navy); }
.ar-dpr table.ar-table th:last-child, .ar-dpr table.ar-table td:last-child { border-right: 2px solid var(--navy); }
.ar-dpr table.ar-table thead th { position: sticky; top: 0; background: var(--navy); color: #fff; font-weight: 600; z-index: 1; border-top: 2px solid var(--navy); border-bottom: 2px solid var(--navy); }
.ar-dpr table.ar-table tbody tr:last-child td { border-bottom: 2px solid var(--navy); }
.ar-dpr table.ar-table thead th:first-child { border-top-left-radius: 10px; }
.ar-dpr table.ar-table thead th:last-child { border-top-right-radius: 10px; }
.ar-dpr table.ar-table tbody tr:last-child td:first-child { border-bottom-left-radius: 10px; }
.ar-dpr table.ar-table tbody tr:last-child td:last-child { border-bottom-right-radius: 10px; }
.ar-dpr .tbl-wrap.scroll { border: 0; box-shadow: none; background: transparent; }   /* the navy table frame IS the card edge now */
.ar-dpr table.ar-table tbody tr:nth-child(even) td { background: #fafbfd; }
.ar-dpr table.ar-table tr.total-row td { background: #b9c4d6; font-weight: 700; }
.ar-dpr table.ar-table a { color: var(--blue); font-weight: 700; text-decoration: none; }
.ar-dpr .ov-input { font: inherit; padding: 4px 8px; border: 1px solid var(--line); border-radius: 6px; background: #fff; color: var(--ink); max-width: 100%; }
/* Reviews: full review text expander — preview + click to "drop out" the rest, so it can be read inline (Jeff 6/28) */
.ar-dpr td.rev-note-cell { white-space: nowrap; max-width: 340px; }
.ar-dpr .rev-open { font: inherit; font-size: 12px; text-align: left; background: none; border: 0; padding: 0; color: var(--ink); cursor: pointer; max-width: 330px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle; text-decoration: underline dotted; text-underline-offset: 2px; }
.ar-dpr .rev-open:hover { color: var(--blue); }
.rev-modal-text { font-size: 14px; line-height: 1.55; color: var(--ink); white-space: pre-wrap; }
/* Reviews: "Earned by" tech input + roster dropdown (pick exact names, add multiple) */
.ar-dpr .rev-tech-wrap { display: flex; gap: 4px; align-items: center; }
.ar-dpr .rev-tech-in { width: 150px; font-size: 12px; }
.ar-dpr .rev-tech-add { font: inherit; font-size: 12px; padding: 4px 2px; border: 1px solid var(--line); border-radius: 6px; background: #fff; color: var(--ink); cursor: pointer; max-width: 54px; }
