/* ==========================================================================
   Dufour Job Book - design system (redevelopment, 2026-07-27)
   Direction: LIGHT workspace, DARK chrome, ONE yellow accent used sparingly.
   Derived from the agreed Sales Pipeline concept. Every colour is a token;
   no component may invent its own.
   ========================================================================== */

:root{
  /* chrome + brand */
  --chrome:#111827;
  --chrome-2:#1B2432;
  --brand-yellow:#F2E519;
  --yellow-hover:#D9C900;
  --yellow-soft:#FDFAC7;

  /* surfaces */
  --app-bg:#F9FAFB;
  --surface:#FFFFFF;
  --surface-warm:#FAF6E1;
  --border:#E5E7EB;
  --border-strong:#D6DAE1;

  /* text */
  --text:#111827;
  --text-muted:#4B5563;
  --text-invert:#FFFFFF;

  /* semantic */
  --won:#16833D;
  --won-bg:#E7F5EC;
  --due:#B4832E;
  --due-bg:#FBF1DC;
  --overdue:#DC3545;
  --overdue-bg:#FDECEE;
  --info-bg:#EEF2F7;

  /* shape + depth */
  --r-card:10px;
  --r-pill:999px;
  --r-input:6px;
  --shadow:0 1px 2px rgba(17,24,39,.04), 0 4px 12px rgba(17,24,39,.06);
  --shadow-lift:0 2px 6px rgba(17,24,39,.08), 0 12px 28px rgba(17,24,39,.10);

  --sidebar-w:236px;
  --sidebar-w-collapsed:72px;
  --font:'Poppins',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
}

*{ box-sizing:border-box; }
html,body{ margin:0; padding:0; }
body{
  font-family:var(--font);
  background:var(--app-bg);
  color:var(--text);
  font-size:14px;
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
}
body.booting > .app,
body.booting > .mobile-topbar{ display:none; }
.hidden{ display:none !important; }
a{ color:inherit; }

/* utility label: small caps is where the industrial character lives */
.label,.tag,.section-note,.kpi-card .label{
  font-size:10.5px; font-weight:600; letter-spacing:.09em; text-transform:uppercase;
  color:var(--text-muted);
}

/* ============================ SHELL ============================ */
.app{ display:flex; min-height:100vh; }

.sidebar{
  width:var(--sidebar-w); flex:0 0 var(--sidebar-w);
  background:var(--chrome); color:var(--text-invert);
  display:flex; flex-direction:column; position:sticky; top:0; height:100vh;
  transition:width .18s ease, flex-basis .18s ease;
}
.brand{ padding:24px 20px 20px; border-bottom:1px solid rgba(255,255,255,.08); position:relative; }
.brand-logo-big{ width:100%; max-width:148px; height:auto; display:block; transition:max-width .18s ease; }
.login-logo{ width:40px; height:40px; object-fit:contain; border-radius:6px; }

/* --------------------------- sidebar collapse ---------------------------- */
.sidebar-collapse-btn{
  position:absolute; top:15px; right:10px; width:24px; height:24px; border-radius:6px;
  display:flex; align-items:center; justify-content:center;
  border:1px solid rgba(255,255,255,.18); background:rgba(255,255,255,.06);
  color:rgba(255,255,255,.75); cursor:pointer; transition:background .12s ease,color .12s ease;
}
.sidebar-collapse-btn:hover{ background:rgba(255,255,255,.16); color:#fff; }
.sidebar-collapse-btn svg{ transition:transform .18s ease; }
.sidebar.collapsed{ width:var(--sidebar-w-collapsed); flex:0 0 var(--sidebar-w-collapsed); }
.sidebar.collapsed .brand{ padding:18px 8px 14px; }
.sidebar.collapsed .brand-logo-big{ max-width:34px; margin:0 auto; }
.sidebar.collapsed .sidebar-collapse-btn{ position:static; margin:8px auto 0; transform:none; }
.sidebar.collapsed .sidebar-collapse-btn svg{ transform:rotate(180deg); }
.sidebar.collapsed .navlist{ padding:12px 8px; }
.sidebar.collapsed .navlist button{ justify-content:center; padding:11px 0; gap:0; }
.sidebar.collapsed .navlist button .lbl{ display:none; }
.sidebar.collapsed .sidebar-foot{ padding:12px 6px 16px; }
.sidebar.collapsed .user-card{ justify-content:center; padding:8px 0; }
.sidebar.collapsed .user-meta,
.sidebar.collapsed .user-signout{ display:none; }
/* the content column reflows automatically since .sidebar is flex:0 0 <w> */

.navlist{ padding:12px 10px; display:flex; flex-direction:column; gap:2px; flex:1; overflow-y:auto; }
.navlist button{
  position:relative; display:flex; align-items:center; gap:11px;
  background:transparent; border:0; color:rgba(255,255,255,.72);
  font-family:var(--font); font-size:13.5px; font-weight:500;
  padding:10px 12px; border-radius:8px; cursor:pointer; text-align:left; width:100%;
  transition:background .12s ease,color .12s ease;
}
.navlist button:hover{ background:rgba(255,255,255,.07); color:#fff; }
.navlist button.active{ background:rgba(255,255,255,.10); color:#fff; font-weight:600; }
/* the vertical yellow selection bar from the concept */
.navlist button.active::before{
  content:''; position:absolute; left:0; top:9px; bottom:9px; width:3px;
  border-radius:0 3px 3px 0; background:var(--brand-yellow);
}
.navlist button .ico{
  display:flex; align-items:center; justify-content:center;
  width:16px; height:16px; flex:0 0 auto; opacity:.85;
}
.navlist button:hover .ico,
.navlist button.active .ico{ opacity:1; }

.sidebar-foot{
  padding:12px 12px 16px; border-top:1px solid rgba(255,255,255,.08);
}
.user-card{
  display:none; align-items:center; gap:9px; padding:8px 6px; border-radius:10px;
}
.user-avatar{
  width:32px; height:32px; border-radius:50%; flex:0 0 auto;
  background:var(--brand-yellow); color:var(--chrome);
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font); font-weight:700; font-size:13px;
}
.user-meta{ flex:1; min-width:0; }
.user-name{ font-size:13px; font-weight:600; color:#fff; line-height:1.3; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.user-sub{ font-size:11px; color:rgba(255,255,255,.45); line-height:1.3; }
.user-signout{
  flex:0 0 auto; width:28px; height:28px; border-radius:7px; border:0; background:transparent;
  color:rgba(255,255,255,.5); display:flex; align-items:center; justify-content:center; cursor:pointer;
}
.user-signout:hover{ background:rgba(255,255,255,.12); color:#fff; }

.content{ flex:1; min-width:0; padding:26px 30px 60px; }

/* view header */
.view-head{
  display:flex; align-items:flex-start; justify-content:space-between; gap:16px;
  margin-bottom:20px; flex-wrap:wrap;
}
.view-head h2{ font-size:23px; font-weight:700; margin:0; letter-spacing:-.015em; }
.view-head .sub{ color:var(--text-muted); font-size:13px; margin-top:3px; }

/* ============================ CARDS ============================ */
.card{
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--r-card); padding:18px; box-shadow:var(--shadow);
  margin-bottom:16px;
}
.card h3{
  font-size:13px; font-weight:700; margin:0 0 14px; letter-spacing:-.01em;
  display:flex; align-items:center; justify-content:space-between; gap:10px;
}
.card-head-row{ display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:14px; }

.grid-2{ display:grid; grid-template-columns:1fr 1fr; gap:16px; align-items:start; }
.grid-3{ display:grid; grid-template-columns:repeat(3,1fr); gap:16px; align-items:start; }
.kpi-grid,.kpi-row{ display:grid; grid-template-columns:repeat(4,1fr); gap:14px; margin-bottom:18px; align-items:start; }

.kpi-card{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--r-card);
  padding:15px 16px; box-shadow:var(--shadow);
}
.kpi-card .value{
  font-size:24px; font-weight:700; letter-spacing:-.02em; margin-top:5px; line-height:1.15;
}
.kpi-card .value.big{ font-size:30px; }
.kpi-card .delta{ font-size:11.5px; color:var(--text-muted); margin-top:4px; }
.kpi-card.is-hero{ border-color:var(--brand-yellow); box-shadow:0 0 0 3px var(--yellow-soft), var(--shadow); }
.kpi-card.is-alert{ border-color:var(--overdue); }
.kpi-card.is-alert .value{ color:var(--overdue); }

/* ============================ BUTTONS ============================ */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  font-family:var(--font); font-size:13px; font-weight:600;
  padding:9px 15px; border-radius:var(--r-input); border:1px solid var(--border-strong);
  background:var(--surface); color:var(--text); cursor:pointer; white-space:nowrap;
  transition:background .12s ease,border-color .12s ease,transform .06s ease;
}
.btn:hover{ background:#F3F4F6; }
.btn:active{ transform:translateY(1px); }
.btn-sm{ font-size:12px; padding:6px 11px; }
.btn-dark{ background:var(--chrome); color:#fff; border-color:var(--chrome); }
.btn-dark:hover{ background:#000; }
/* the one bright accent: primary money/commit actions only */
.btn-amber{ background:var(--brand-yellow); color:#111827; border-color:var(--brand-yellow); font-weight:700; }
.btn-amber:hover{ background:var(--yellow-hover); border-color:var(--yellow-hover); }
.btn-ghost{ background:transparent; border-color:var(--border); color:var(--text-muted); }
.btn-ghost:hover{ background:#F3F4F6; color:var(--text); }
.btn-danger{ background:var(--surface); color:var(--overdue); border-color:#F3C2C7; }
.btn-danger:hover{ background:var(--overdue-bg); }
.btn-wa{ background:#25D366; color:#fff; border-color:#25D366; }
.btn-wa:hover{ background:#1FB457; border-color:#1FB457; }
.link-btn{
  background:none; border:0; color:var(--text); font-family:var(--font); font-size:12.5px;
  font-weight:600; cursor:pointer; padding:0; text-decoration:underline;
  text-underline-offset:3px; text-decoration-thickness:1.5px; text-decoration-color:var(--brand-yellow);
}
.row-actions{ display:flex; gap:6px; flex-wrap:wrap; align-items:center; justify-content:flex-start; }
td .row-actions{ flex-wrap:nowrap; }

/* ============================ FORMS ============================ */
.form-row{ margin-bottom:13px; }
.form-row label,.form-row > .label{ display:block; margin-bottom:5px; }
.form-2col{ display:grid; grid-template-columns:1fr 1fr; gap:13px; }
input,select,textarea{
  font-family:var(--font); font-size:13.5px; width:100%; padding:9px 11px;
  border:1px solid var(--border-strong); border-radius:var(--r-input);
  background:var(--surface); color:var(--text);
}
input:focus,select:focus,textarea:focus{
  outline:none; border-color:var(--chrome); box-shadow:0 0 0 3px rgba(17,24,39,.07);
}
textarea{ min-height:80px; resize:vertical; }
.toolbar{ display:flex; gap:9px; align-items:center; flex-wrap:wrap; margin-bottom:14px; }
.search-input{ max-width:290px; }
.hint{ font-size:11.5px; color:var(--text-muted); line-height:1.5; }
.section-note{ margin-bottom:9px; }

/* ============================ TABLES ============================ */
.table-wrap,.card-scroll{ overflow-x:auto; -webkit-overflow-scrolling:touch; }
/* a scrollable table should LOOK scrollable, not truncated */
.table-wrap{ background:linear-gradient(90deg,transparent 92%,rgba(17,24,39,.05) 100%); }
.table-wrap::-webkit-scrollbar{ height:7px; }
.table-wrap::-webkit-scrollbar-thumb{ background:var(--border-strong); border-radius:4px; }
table{ width:100%; border-collapse:collapse; font-size:13px; }
th{
  text-align:left; padding:9px 11px; border-bottom:1px solid var(--border);
  font-size:10.5px; font-weight:700; letter-spacing:.07em; text-transform:uppercase;
  color:var(--text-muted); white-space:nowrap; background:var(--surface);
}
td{ padding:10px 11px; border-bottom:1px solid #F1F3F5; vertical-align:middle; }
tbody tr:last-child td{ border-bottom:0; }
tbody tr:hover{ background:#FCFCFD; }
.num-cell{ text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; min-width:104px; }
/* header must follow its column's alignment, or the number sits under nothing */
th.num-cell{ text-align:right; }
/* money must never be truncated: let the wrapper scroll instead of clipping the figure */
td.num-cell{ overflow:visible; text-overflow:clip; }
.mono{ font-variant-numeric:tabular-nums; }
th.th-sort{ cursor:pointer; user-select:none; }
th.th-sort:hover{ color:var(--text); }
td.ed-cell{ cursor:pointer; }
td.ed-cell:hover{ background:var(--yellow-soft); box-shadow:inset 0 0 0 1.5px var(--brand-yellow); border-radius:4px; }
.ed-input{ padding:4px 6px; font-size:13px; border:1.5px solid var(--brand-yellow); border-radius:var(--r-input); }
.name{ font-weight:600; }
.meta{ font-size:11.5px; color:var(--text-muted); }
.empty-state{
  text-align:center; padding:34px 18px; color:var(--text-muted); font-size:13px;
  border:1px dashed var(--border-strong); border-radius:var(--r-card); background:#FCFCFD;
}

/* ============================ PILLS ============================ */
.pill{
  display:inline-flex; align-items:center; gap:5px; padding:3px 10px;
  border-radius:var(--r-pill); font-size:11px; font-weight:700;
  letter-spacing:.03em; background:var(--info-bg); color:var(--text-muted); white-space:nowrap;
}
/* Status pills are short labels and should never wrap, but the margin warning
   on a job is a whole sentence: on a phone it ran off the side of the card. */
.pill.pill-wrap{ white-space:normal; text-align:left; line-height:1.45; }
@media (max-width:820px){ .pill-overdue{ white-space:normal; line-height:1.45; } }
.pill-won,.pill-accepted,.pill-completed,.pill-paid{ background:var(--won-bg); color:var(--won); }
.pill-sent,.pill-quoted,.pill-ongoing,.pill-contacted,.pill-due{ background:var(--due-bg); color:var(--due); }
.pill-lost,.pill-rejected,.pill-overdue{ background:var(--overdue-bg); color:var(--overdue); }
.pill-new,.pill-draft,.pill-pipeline{ background:var(--info-bg); color:#4B5563; }
.pill-urgent{ background:var(--brand-yellow); color:#111827; }
.tag-chip{
  display:inline-block; padding:3px 9px; border-radius:var(--r-pill);
  background:var(--info-bg); font-size:11.5px; margin:0 5px 5px 0;
}

/* ============================ OVERVIEW COMPARTMENTS ============================ */
.zones{ display:grid; grid-template-columns:1fr 1fr; gap:16px; align-items:start; }
.zone{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--r-card);
  box-shadow:var(--shadow); overflow:hidden;
}
.zone-head{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:13px 16px; border-bottom:1px solid var(--border); background:#FCFCFD;
}
.zone-head h3{ margin:0; font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; }
.zone-body{ padding:16px; }
.zone-body > :last-child{ margin-bottom:0; }

/* Today list */
.today-item{
  display:flex; align-items:flex-start; gap:11px; padding:10px 0;
  border-bottom:1px solid #F1F3F5;
}
.today-item:last-child{ border-bottom:0; }
.today-dot{ width:9px; height:9px; border-radius:50%; margin-top:6px; flex:0 0 9px; }
.today-dot.red{ background:var(--overdue); }
.today-dot.amber{ background:var(--due); }
.today-dot.green{ background:var(--won); }
.today-text{ flex:1; font-size:13.5px; }
.today-text small{ display:block; color:var(--text-muted); font-size:11.5px; margin-top:1px; }

/* funnel */
.funnel-row{ display:flex; align-items:center; gap:11px; margin-bottom:10px; }
.funnel-label{ width:64px; font-size:11.5px; color:var(--text); font-weight:600; }
.funnel-track{ flex:1; height:22px; background:var(--info-bg); border-radius:var(--r-input); overflow:hidden; }
.funnel-fill{ height:100%; background:var(--chrome); border-radius:var(--r-input); }
.funnel-row:last-child .funnel-fill{ background:var(--brand-yellow); }
.funnel-val{ width:66px; text-align:right; font-weight:700; font-size:13px; font-variant-numeric:tabular-nums; }

/* goal bar */
.target-row{ display:flex; align-items:center; justify-content:space-between; margin-bottom:7px; }
.target-label{ font-size:12px; color:var(--text-muted); }
.target-bar{ height:11px; background:var(--info-bg); border-radius:var(--r-pill); overflow:hidden; }
.target-bar > span{ display:block; height:100%; background:var(--brand-yellow); border-radius:var(--r-pill); }

/* margin bar (estimated vs actual) */
.mbar{ height:8px; background:var(--info-bg); border-radius:var(--r-pill); overflow:hidden; margin-top:5px; }
.mbar > span{ display:block; height:100%; background:var(--won); border-radius:var(--r-pill); }
.mbar.warn > span{ background:var(--due); }
.mbar.over > span{ background:var(--overdue); }

/* ============================ PIPELINE (KANBAN) ============================ */
.kanban{ display:grid; grid-template-columns:repeat(4,minmax(220px,1fr)); gap:14px; align-items:start; }
.kcol{ background:#F3F4F6; border:1px solid var(--border); border-radius:var(--r-card); min-height:130px; }
.kcol-head{
  display:flex; align-items:center; justify-content:space-between;
  padding:11px 13px; border-bottom:1px solid var(--border);
}
.kcol-head strong{ font-size:12px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; }
.kcount{ background:var(--surface); border:1px solid var(--border); border-radius:var(--r-pill); font-size:11px; font-weight:700; padding:1px 8px; }
/* Won holds every job ever landed (65 and counting), so an uncapped column
   stretched the page to seven screens and buried the three columns that
   actually need working. Each column scrolls inside itself instead. */
.kcol-body{
  padding:11px; display:flex; flex-direction:column; gap:9px;
  min-height:60px; max-height:64vh; overflow-y:auto; overscroll-behavior:contain;
}
@media (max-width:820px){ .kcol-body{ max-height:52vh; } }
.kcard{
  background:var(--surface); border:1px solid var(--border); border-radius:8px;
  padding:11px 12px; box-shadow:var(--shadow); cursor:grab;
}
.kcard:hover{ box-shadow:var(--shadow-lift); }
.kcard.dragging{ opacity:.45; }
.kcard .kname{ font-weight:600; font-size:13px; margin-bottom:3px; }
.kcard .kmeta{ font-size:11.5px; color:var(--text-muted); }
.kcard .kval{ font-weight:700; font-size:13.5px; margin-top:6px; font-variant-numeric:tabular-nums; }
.kcol.dragover{ outline:2px dashed var(--brand-yellow); outline-offset:-3px; }

/* bottom KPI strip from the concept */
.kpi-strip{
  display:flex; gap:26px; flex-wrap:wrap; align-items:center;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--r-card);
  padding:15px 20px; box-shadow:var(--shadow); margin:16px 0;
}
.kpi-strip .item{ flex:1; min-width:130px; }
.kpi-strip .item .value{ font-size:19px; font-weight:700; font-variant-numeric:tabular-nums; }

/* ============================ TIMELINE ============================ */
.timeline{ position:relative; padding-left:26px; }
.timeline::before{ content:''; position:absolute; left:8px; top:5px; bottom:5px; width:2px; background:var(--border); }
.tl-item{ position:relative; padding:0 0 17px; }
.tl-item::before{
  content:''; position:absolute; left:-22px; top:3px; width:13px; height:13px;
  border-radius:50%; background:var(--brand-yellow); border:2px solid var(--surface);
  box-shadow:0 0 0 1.5px var(--border);
}
.tl-item.future::before{ background:var(--border); }
.tl-title{ font-weight:600; font-size:13px; }
.tl-date{ font-size:11.5px; color:var(--text-muted); }

/* ============================ PHOTOS ============================ */
.photo-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(118px,1fr)); gap:10px; }
.photo-thumb{ position:relative; border-radius:8px; overflow:hidden; border:1px solid var(--border); background:#F3F4F6; aspect-ratio:1/1; }
.photo-thumb img{ width:100%; height:100%; object-fit:cover; display:block; }
.photo-thumb .pdel{
  position:absolute; top:5px; right:5px; background:rgba(17,24,39,.78); color:#fff;
  border:0; border-radius:50%; width:23px; height:23px; cursor:pointer; font-size:13px; line-height:1;
}
.photo-thumb .pdate{
  position:absolute; left:0; right:0; bottom:0; background:linear-gradient(transparent,rgba(0,0,0,.6));
  color:#fff; font-size:10.5px; padding:12px 6px 4px;
}
.upload-tile{
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:6px;
  aspect-ratio:1/1; border:2px dashed var(--border-strong); border-radius:8px;
  cursor:pointer; color:var(--text-muted); font-size:11.5px; text-align:center; background:#FCFCFD;
}
.upload-tile:hover{ border-color:var(--brand-yellow); background:var(--yellow-soft); color:var(--text); }

/* note cards */
.note-card{
  background:var(--surface-warm); border:1px solid #EFE7C6; border-radius:8px;
  padding:11px 13px; margin-bottom:9px; font-size:13px; position:relative;
}
.note-card .ndate{ font-size:11px; color:var(--text-muted); margin-top:5px; }
.note-card .ndel{ position:absolute; top:8px; right:9px; background:none; border:0; cursor:pointer; color:var(--text-muted); font-size:14px; }

/* ============================ MODAL ============================ */
.modal-backdrop{
  position:fixed; inset:0; background:rgba(17,24,39,.55); z-index:200;
  display:flex; align-items:flex-start; justify-content:center; padding:34px 16px; overflow-y:auto;
}
.modal{
  background:var(--surface); border-radius:12px; width:100%; max-width:640px;
  box-shadow:var(--shadow-lift); overflow:hidden;
}
.modal.modal-wide{ max-width:880px; }
.modal-head{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:16px 20px; border-bottom:1px solid var(--border); background:var(--chrome); color:#fff;
}
.modal-head h3{ margin:0; font-size:15px; font-weight:600; }
.modal-close{ background:none; border:0; color:rgba(255,255,255,.75); font-size:22px; cursor:pointer; line-height:1; }
.modal-close:hover{ color:#fff; }
.modal-body{ padding:20px; max-height:calc(100vh - 220px); overflow-y:auto; }
.modal-foot{ padding:14px 20px; border-top:1px solid var(--border); display:flex; justify-content:flex-end; gap:9px; background:#FCFCFD; }

/* ============================ QUOTE BUILDER ============================ */
.qb{ display:grid; grid-template-columns:1fr 300px; gap:18px; align-items:start; }
.qb-summary{
  background:var(--chrome); color:#fff; border-radius:var(--r-card); padding:17px; position:sticky; top:0;
}
.qb-summary .label{ color:rgba(255,255,255,.6); }
.qb-summary .row{ display:flex; justify-content:space-between; align-items:baseline; padding:8px 0; border-bottom:1px solid rgba(255,255,255,.11); }
.qb-summary .row:last-of-type{ border-bottom:0; }
.qb-summary .row .v{ font-weight:700; font-variant-numeric:tabular-nums; }
.qb-total{
  background:var(--brand-yellow); color:#111827; border-radius:8px; padding:12px 14px; margin-top:12px;
}
.qb-total .value{ font-size:25px; font-weight:700; letter-spacing:-.02em; font-variant-numeric:tabular-nums; }
.qb-line{ display:grid; grid-template-columns:118px 1fr 118px 34px; gap:8px; align-items:center; margin-bottom:8px; }
.margin-slider{ width:100%; accent-color:var(--brand-yellow); }

/* ============================ MOBILE ============================ */
/* Defaults must come BEFORE the media query: equal specificity means
   the LAST matching rule wins, so a trailing reset silently kills it. */
.tabbar{ display:none; }
.mobile-topbar{ display:none; }
.nav-scrim{ display:none; }
.mobile-only{ display:none !important; }

@media (max-width:1100px){
  .zones{ grid-template-columns:1fr; }
  .kpi-grid,.kpi-row{ grid-template-columns:repeat(2,1fr); }
  .qb{ grid-template-columns:1fr; }
  .qb-summary{ position:static; }
  .kanban{ grid-template-columns:repeat(2,minmax(200px,1fr)); }
}

@media (max-width:820px){
  .mobile-only{ display:block !important; }
  .desktop-only{ display:none !important; }

  .mobile-topbar{
    display:flex; align-items:center; gap:11px; position:sticky; top:0; z-index:90;
    background:var(--chrome); color:#fff; padding:11px 14px;
  }
  .mobile-topbar img{ height:26px; width:auto; object-fit:contain; }
  .hamburger{ background:none; border:0; color:#fff; font-size:21px; cursor:pointer; padding:2px 5px; }

  .app{ display:block; }
  .sidebar{
    position:fixed; left:0; top:0; bottom:0; z-index:120; height:100vh;
    transform:translateX(-100%); transition:transform .2s ease; width:260px;
  }
  /* the collapse toggle is a desktop concept; on a phone the sidebar is
     already an off-canvas drawer, so force full width regardless of a
     collapsed preference saved from a desktop session. */
  .sidebar.collapsed{ width:260px; }
  .sidebar-collapse-btn{ display:none; }
  body.nav-open .sidebar{ transform:translateX(0); }
  body.nav-open .nav-scrim{ display:block; position:fixed; inset:0; background:rgba(17,24,39,.5); z-index:110; }

  .content{ padding:16px 14px 90px; }
  .view-head h2{ font-size:20px; }
  .kpi-grid,.kpi-row,.grid-2,.grid-3,.form-2col{ grid-template-columns:1fr !important; }
  .kanban{ grid-template-columns:1fr; }
  .modal{ max-width:none; }
  .modal-body{ max-height:none; }
  .qb-line{ grid-template-columns:1fr 1fr; }
  .card{ padding:15px; }
  .btn{ padding:10px 14px; }
  .row-actions .btn{ flex:1 1 auto; min-width:84px; }
  table{ font-size:12.5px; }

  /* bottom tab bar: the phone's primary navigation */
  .tabbar{
    display:flex; position:fixed; left:0; right:0; bottom:0; z-index:100;
    background:var(--chrome); border-top:1px solid rgba(255,255,255,.1);
    padding:6px 4px calc(6px + env(safe-area-inset-bottom));
  }
  .tabbar button{
    flex:1; background:none; border:0; color:rgba(255,255,255,.6); cursor:pointer;
    font-family:var(--font); font-size:10.5px; font-weight:600; padding:7px 2px;
    display:flex; flex-direction:column; align-items:center; gap:3px;
  }
  .tabbar button .ico{ font-size:17px; line-height:1; }
  .tabbar button.active{ color:var(--brand-yellow); }
}

/* ============================ THIS MORNING (phone) ============================ */
.morning-card{
  display:flex; align-items:flex-start; gap:12px;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--r-card);
  padding:14px 15px; margin-bottom:10px; box-shadow:var(--shadow);
}
.morning-card .mstat{
  font-size:9.5px; font-weight:800; letter-spacing:.08em; padding:3px 8px;
  border-radius:var(--r-pill); white-space:nowrap;
}
.mstat.red{ background:var(--overdue-bg); color:var(--overdue); }
.mstat.amber{ background:var(--due-bg); color:var(--due); }
.mstat.green{ background:var(--won-bg); color:var(--won); }
.morning-card .mtext{ flex:1; font-size:14px; font-weight:500; }
.morning-card .mtext small{ display:block; font-weight:400; color:var(--text-muted); font-size:11.5px; margin-top:2px; }

/* big fat mobile action buttons on a job */
.job-actions{ display:grid; grid-template-columns:repeat(3,1fr); gap:9px; margin:14px 0; }
.job-actions .btn{ flex-direction:column; gap:5px; padding:15px 8px; font-size:11.5px; }
.job-actions .btn .ico{ font-size:19px; }

/* ============================ MISC ============================ */
.chart-wrap{ position:relative; height:230px; }
.upcoming-card{
  border:1px solid var(--border); border-radius:8px; padding:11px 13px; margin-bottom:9px; background:var(--surface);
}
.upcoming-card.clickable:hover{ border-color:var(--brand-yellow); background:#FFFEF5; cursor:pointer; }
.clickable{ cursor:pointer; }
.fu-name-link{ cursor:pointer; text-decoration:underline; text-decoration-style:dotted; text-underline-offset:2px; }
.fu-name-link:hover{ color:var(--due); }
.tip-item{ display:flex; gap:10px; align-items:flex-start; margin-bottom:11px; font-size:13px; }
.tip-icon{ flex:0 0 auto; }
.followup-item{
  display:flex; align-items:center; justify-content:space-between; gap:11px;
  padding:11px 0; border-bottom:1px solid #F1F3F5; flex-wrap:wrap;
}
.followup-item:last-child{ border-bottom:0; }
#toast{
  position:fixed; left:50%; bottom:26px; transform:translateX(-50%);
  background:var(--chrome); color:#fff; padding:11px 19px; border-radius:var(--r-pill);
  font-size:13px; z-index:400; box-shadow:var(--shadow-lift); opacity:0; pointer-events:none;
  transition:opacity .2s ease;
}
#toast.show{ opacity:1; }

/* The toasts the app ACTUALLY shows.
   showToast() has appended `div.toast` into #toastRoot since the redevelopment,
   and the only rule in this file was the older `#toast` element, which nothing
   creates. So every confirmation the app has raised, including the one added in
   August specifically so a saved cost could not be missed, was rendering as
   unstyled body text at the bottom of the page. Found while building the undo
   toast below, which cannot work without a styled, clickable surface. */
#toastRoot{
  position:fixed; left:50%; bottom:26px; transform:translateX(-50%);
  z-index:400; display:flex; flex-direction:column-reverse; align-items:center; gap:8px;
  pointer-events:none; max-width:min(560px, calc(100vw - 32px));
}
#toastRoot .toast{
  background:var(--chrome); color:#fff; padding:11px 19px; border-radius:var(--r-pill);
  font-size:13px; line-height:1.4; box-shadow:var(--shadow-lift); text-align:center;
  pointer-events:auto; animation:toast-in .18s ease-out;
}
@keyframes toast-in{ from{ opacity:0; transform:translateY(6px); } to{ opacity:1; transform:none; } }

/* Undo lives ON the toast: one tap is easy to do by accident, and the way back
   has to be under the thumb at the moment the mistake is noticed. */
#toastRoot .toast-undo{
  display:flex; align-items:center; gap:14px; text-align:left; padding:10px 10px 10px 19px;
}
#toastRoot .toast-undo .tu-msg{ flex:1 1 auto; }
#toastRoot .toast-undo .tu-undo{
  flex:0 0 auto; background:var(--brand-yellow); color:var(--chrome); border:0;
  border-radius:var(--r-pill); padding:6px 14px; font:inherit; font-weight:700; font-size:12.5px;
  cursor:pointer;
}
#toastRoot .toast-undo .tu-undo:hover{ background:var(--yellow-hover); }
@media (max-width:520px){
  #toastRoot{ bottom:84px; }   /* clear of the phone tab bar */
}
@media (prefers-reduced-motion:reduce){
  #toastRoot .toast{ animation:none; }
}

/* The "Coming up" entry point beside a view's primary action (item J). */
.head-actions{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.count-badge{
  display:inline-block; margin-left:7px; min-width:18px; padding:1px 6px; border-radius:var(--r-pill);
  background:var(--chrome); color:#fff; font-size:11px; font-weight:700; line-height:1.5;
  font-variant-numeric:tabular-nums;
}

/* ============================ LOGIN ============================ */
/* The gate is hidden by DEFAULT and shown only when .show is added.
   (Getting this the wrong way round leaves a fixed overlay covering the whole
   app after sign-in, which a full-page screenshot hides but a phone does not.) */
#loginGate{
  position:fixed; inset:0; z-index:500; background:var(--chrome);
  display:none; align-items:center; justify-content:center; padding:20px;
}
#loginGate.show{ display:flex; }
.login-card{
  background:var(--surface); border-radius:14px; padding:32px 30px; width:100%; max-width:370px;
  box-shadow:var(--shadow-lift); text-align:left;
}
.login-card .login-logo{ width:54px; height:54px; margin-bottom:14px; }
.login-card h2{ margin:0 0 3px; font-size:20px; font-weight:700; }
.login-sub{ color:var(--text-muted); font-size:13px; margin-bottom:20px; }
.login-card label{ display:block; font-size:11px; font-weight:600; letter-spacing:.07em; text-transform:uppercase; color:var(--text-muted); margin:12px 0 5px; }
.login-card .btn{ width:100%; margin-top:18px; padding:11px; }
.login-err{ display:none; background:var(--overdue-bg); color:var(--overdue); padding:9px 11px; border-radius:var(--r-input); font-size:12.5px; margin-bottom:12px; }
.login-err.show{ display:block; }

/* respect users who ask for less motion */
@media (prefers-reduced-motion:reduce){
  *{ transition:none !important; animation:none !important; }
}

/* ============================ QUICK ADD (capture) ============================ */
.qa-fab{
  position:fixed; right:22px; bottom:26px; z-index:150;
  width:56px; height:56px; border-radius:50%;
  background:var(--brand-yellow); color:#111827; border:0;
  font-size:30px; font-weight:400; line-height:1; cursor:pointer;
  box-shadow:var(--shadow-lift);
}
.qa-fab:hover{ background:var(--yellow-hover); }
/* The FAB is fixed at the bottom-right, so it lands ON TOP of whatever happens
   to be at that spot. That was harmless while the right-hand end of a row was
   an inert chevron. It stopped being harmless the moment a real action went
   there: measured on the live Money owed screen, the + was covering TWO "Paid
   in full" buttons, so tapping to settle those two jobs opened Quick Add
   instead. Flagged by a vision consult, then confirmed by measuring the
   rectangles rather than taken on trust.
   Padding the end of the list does NOT fix it (mid-scroll the + still lands on
   a row), so on the one screen where every row ends in an action, the + stands
   down. It is unchanged everywhere else. */
body[data-view="owed"] .qa-fab{ display:none; }
/* Clearance at the end of every list anyway, so the last row is never half
   under the button on the screens that keep it. */
.view{ padding-bottom:96px; }
/* The ask panel used to sit BEHIND this button (z-index 71 vs 150), so the
   FAB visibly overlapped the open chat drawer. Belt and braces: hide the FAB
   whenever the panel is open, on top of the panel now correctly outranking it. */
body.ask-open .qa-fab{ display:none; }

/* Voice capture. Recording is the one state that must be unmistakable at a
   glance on site, so it gets red plus a pulse rather than a subtle tint. */
.btn.is-recording{
  background:var(--overdue-bg); color:var(--overdue); border-color:var(--overdue);
  font-weight:700; animation:recPulse 1.4s ease-in-out infinite;
}
.btn.is-recording:hover{ background:var(--overdue-bg); }
.btn[disabled]{ opacity:.65; cursor:default; }
@keyframes recPulse{
  0%,100%{ box-shadow:0 0 0 0 rgba(220,53,69,.34); }
  50%    { box-shadow:0 0 0 6px rgba(220,53,69,0); }
}
@media (prefers-reduced-motion:reduce){ .btn.is-recording{ animation:none; } }
@media (max-width:820px){
  /* clear the bottom tab bar */
  .qa-fab{ bottom:calc(78px + env(safe-area-inset-bottom)); right:16px; width:54px; height:54px; }
}

/* stacked estimated-vs-actual rows for the phone */
.cost-row{ border:1px solid var(--border); border-radius:8px; padding:11px 12px; margin-bottom:9px; background:var(--surface); }
.cost-row-top{ display:flex; justify-content:space-between; align-items:baseline; gap:10px; margin-bottom:5px; font-size:13.5px; }
.cost-row-vals{ display:flex; justify-content:space-between; gap:10px; font-size:12px; color:var(--text-muted); margin-bottom:7px; }
/* the tab bar overlays content, so say so with a shadow rather than looking like a clip */
.tabbar{ box-shadow:0 -6px 18px rgba(17,24,39,.18); }

/* ==========================================================================
   OVERVIEW OVERHAUL + AGENT SURFACE (2026-07-27)
   Defaults are declared BEFORE their media queries throughout. Equal
   specificity means the last rule wins, and getting that backwards is how the
   phone tab bar went missing once already.
   ========================================================================== */

/* ------------------------------ segmented ------------------------------- */
.seg{
  display:inline-flex; gap:2px; padding:3px; background:#EFF1F4;
  border:1px solid var(--border); border-radius:var(--r-pill);
}
.seg button{
  border:0; background:transparent; cursor:pointer; font-family:var(--font);
  font-size:12.5px; font-weight:600; color:var(--text-muted);
  padding:6px 13px; border-radius:var(--r-pill); white-space:nowrap;
  transition:background .14s ease, color .14s ease;
}
.seg button:hover{ color:var(--text); }
.seg button.active{ background:var(--surface); color:var(--text); box-shadow:0 1px 2px rgba(17,24,39,.10); }
.seg.seg-sm button{ font-size:11.5px; padding:5px 11px; }
/* The board tabs are the primary control. A dark pill IS the active state;
   the earlier ::after underline stacked a second active-state treatment on
   top of the first pill and read as a stray line inside the button. */
.board-tabs button.active{ background:var(--chrome); color:var(--text-invert); }
.board-controls{
  display:flex; align-items:center; justify-content:space-between;
  gap:12px; flex-wrap:wrap; margin-bottom:18px;
}
.card-head{ display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; margin-bottom:12px; }
.card-head h3{ margin:0; }

/* -------------------------------- hero ---------------------------------- */
.hero-row{ display:grid; grid-template-columns:minmax(260px,340px) 1fr; gap:16px; align-items:stretch; }
.hero-card{
  background:var(--chrome); color:var(--text-invert); border-radius:var(--r-card);
  padding:20px 22px; display:flex; flex-direction:column; justify-content:center;
  box-shadow:var(--shadow);
}
.hero-label{ font-size:11px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; opacity:.7; }
.hero-figure{
  font-size:54px; line-height:1.02; font-weight:800; letter-spacing:-.02em;
  margin:6px 0 8px; color:var(--brand-yellow);
}
.hero-sub{ font-size:12.5px; line-height:1.5; opacity:.82; }
.hero-list{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--r-card);
  box-shadow:var(--shadow); padding:6px 16px; overflow:hidden;
}

/* ------------------------- today: 5-row left column ----------------------
   Replaces the old oversized dark "needs you" card, which carried a huge
   54px figure for what was often a one-line message. The four stat tiles
   that used to sit in their own full-width row below now live as four more
   rows in the SAME column, so the whole "what needs attention" picture reads
   top to bottom in one glance instead of one hero card plus a separate grid. */
.today-col{ display:flex; flex-direction:column; gap:8px; }
.today-row{
  flex:1; display:flex; align-items:center; justify-content:space-between; gap:10px;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--r-card);
  padding:11px 15px; box-shadow:var(--shadow);
}
.today-row.clickable{ cursor:pointer; transition:border-color .14s ease, box-shadow .14s ease; }
.today-row.clickable:hover{ border-color:var(--border-strong); box-shadow:var(--shadow-lift); }
.today-row-hero{ background:var(--chrome); color:var(--text-invert); border-color:var(--chrome); }
.today-row .tr-label{ font-size:11px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; opacity:.68; }
.today-row-hero .tr-label{ opacity:.7; }
.today-row .tr-main{ display:flex; align-items:baseline; gap:9px; min-width:0; }
.today-row .tr-value{ font-size:19px; font-weight:800; letter-spacing:-.01em; flex:0 0 auto; }
.today-row-hero .tr-value{ color:var(--brand-yellow); }
.today-row .tr-sub{ font-size:11px; color:var(--text-muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.today-row-hero .tr-sub{ color:rgba(255,255,255,.72); }
.today-row.tone-good .tr-value{ color:var(--won); }
.today-row.tone-bad .tr-value{ color:var(--overdue); }
.today-row.tone-warn .tr-value{ color:var(--due); }
@media (max-width:600px){
  .today-row{ flex-wrap:wrap; }
  .today-row .tr-main{ width:100%; justify-content:space-between; }
  .today-row .tr-sub{ white-space:normal; text-align:right; }
}
.today-go{ margin-left:auto; color:var(--text-muted); font-size:17px; line-height:1; opacity:0; transition:opacity .14s ease; }
.today-item.clickable{ cursor:pointer; }
.today-item.clickable:hover{ background:#FBFCFD; }
.today-item.clickable:hover .today-go{ opacity:1; }

/* ----------------------------- stat tiles -------------------------------- */
.tile-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:14px; margin-top:16px; }
.stat-tile{
  position:relative; overflow:hidden;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--r-card);
  padding:15px 16px 14px; box-shadow:var(--shadow);
  transition:border-color .14s ease, box-shadow .14s ease, transform .14s ease;
}
.stat-tile.clickable{ cursor:pointer; }
.stat-tile.clickable:hover{ border-color:var(--border-strong); box-shadow:var(--shadow-lift); transform:translateY(-1px); }
.tile-label{ font-size:10.5px; font-weight:700; letter-spacing:.07em; text-transform:uppercase; color:var(--text-muted); }
.tile-value{ font-size:27px; font-weight:700; letter-spacing:-.015em; line-height:1.18; margin:5px 0 3px; }
.tile-foot{ display:flex; align-items:baseline; gap:7px; flex-wrap:wrap; min-height:17px; }
.tile-delta{ font-size:11.5px; font-weight:700; }
.tile-delta.up{ color:var(--won); }
.tile-delta.down{ color:var(--overdue); }
.tile-prev{ font-size:11.5px; color:var(--text-muted); }
.tile-spark{ margin:6px -16px -14px; height:40px; pointer-events:none; }
.stat-tile.tone-good .tile-value{ color:var(--won); }
.stat-tile.tone-bad  .tile-value{ color:var(--overdue); }
.stat-tile.tone-warn .tile-value{ color:var(--due); }

/* --------------------------- job lines / goal ---------------------------- */
.job-line{ padding:11px 0; border-bottom:1px solid var(--border); }
.job-line:last-child{ border-bottom:0; }
.job-line.clickable{ cursor:pointer; }
.job-line.clickable:hover .job-name{ text-decoration:underline; }
.job-line-top{ display:flex; justify-content:space-between; align-items:baseline; gap:10px; margin-bottom:7px; }
.job-name{ font-weight:600; font-size:13.5px; }
.job-val{ font-variant-numeric:tabular-nums; font-weight:600; font-size:13px; }
.job-line-foot{ display:flex; justify-content:space-between; gap:10px; font-size:11.5px; color:var(--text-muted); margin-top:6px; }
.job-line-foot .pos{ color:var(--won); font-weight:600; }
.job-line-foot .neg{ color:var(--overdue); font-weight:600; }
.spend-bar{ height:6px; border-radius:3px; background:#EFF1F4; overflow:hidden; }
.spend-bar > span{ display:block; height:100%; border-radius:3px; transition:width .3s ease; }
.goal-foot{ display:flex; justify-content:space-between; gap:12px; flex-wrap:wrap; margin-top:6px; }
.goal-foot .label{ display:block; font-size:10.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--text-muted); }
.goal-foot strong{ font-size:15px; font-variant-numeric:tabular-nums; }

/* =============================== ASK BAR ================================= */
.ask-bar{
  display:flex; align-items:center; gap:8px;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--r-pill);
  padding:6px 6px 6px 14px; margin:0 0 18px; box-shadow:var(--shadow);
  transition:border-color .15s ease, box-shadow .15s ease;
}
.ask-bar:focus-within{ border-color:var(--chrome); box-shadow:var(--shadow-lift); }
.ask-spark{ display:flex; color:var(--chrome); flex:0 0 auto; }
.ask-input{
  flex:1 1 auto; min-width:0; border:0; outline:0; background:transparent;
  font-family:var(--font); font-size:13.5px; color:var(--text); padding:6px 2px;
}
.ask-input::placeholder{ color:#8B93A1; }
.ask-scope{
  flex:0 0 auto; font-size:10.5px; font-weight:700; letter-spacing:.05em; text-transform:uppercase;
  color:var(--text-muted); background:#EFF1F4; border-radius:var(--r-pill); padding:4px 10px;
}
.ask-mic, .ask-go{
  flex:0 0 auto; display:inline-flex; align-items:center; justify-content:center;
  width:32px; height:32px; border-radius:50%; border:1px solid var(--border);
  background:var(--surface); color:var(--text-muted); cursor:pointer; font-size:15px; line-height:1;
  transition:background .14s ease, color .14s ease, border-color .14s ease;
  /* These are fixed-size circles in a flex row. If anything ever puts words
     inside one again, they get clipped here rather than laid across the
     pill and the send button. The real guard is in app3.js setBtn(). */
  padding:0; overflow:hidden; white-space:nowrap;
}
.ask-mic:hover, .ask-go:hover{ color:var(--text); border-color:var(--border-strong); }
.ask-go{ background:var(--chrome); color:var(--text-invert); border-color:var(--chrome); font-weight:700; }
.ask-go:hover{ background:#000; color:var(--brand-yellow); }

/* Recording has to be obvious at a glance without growing the button, so the
   icon circle turns red and pulses in place, the way the labelled Quick Add
   button does. Working = the mic swaps for a spinner (see setBtn). */
.ask-bar .is-recording{
  background:var(--overdue); color:#fff; border-color:var(--overdue);
  animation:recPulse 1.4s ease-in-out infinite;
}
.ask-mic.is-working{ opacity:.7; cursor:default; }
.voice-spin{ transform-origin:50% 50%; animation:voiceSpin .8s linear infinite; }
@keyframes voiceSpin{ to{ transform:rotate(360deg); } }
@media (prefers-reduced-motion:reduce){
  .ask-bar .is-recording, .ask-compose .ask-icon.is-recording{ animation:none; }
  .voice-spin{ animation:none; }
}

/* ======================= STAGING ENVIRONMENT BANNER ======================= */
/*
 * Staging is not the live book, and since 11 August it is not the address Jay
 * should be opening either. So the message has to be impossible to miss and
 * impossible to mistake for part of the app.
 *
 * It is a full-width bar in NORMAL DOCUMENT FLOW, not an overlay. It takes its
 * own height, and every element that pins itself to the top of the viewport is
 * offset by that height below, so the bar covers nothing: the 10 August session
 * bar covered the sidebar logo by 2,146px squared precisely because it was
 * anchored over the layout instead of inside it.
 *
 * z-index 130 sits above the app's own chrome (mobile topbar 90, tab bar 100,
 * off-canvas sidebar 120) and below the temporary overlays (drawers 155-160,
 * modals 200), so a drawer covers the bar while it is open, which is what an
 * overlay is for, and nothing is permanently hidden behind it.
 *
 * Production never sets `body.env-staging`, so none of this applies there even
 * though the identical stylesheet ships to both environments.
 */
/* A FALLBACK only, for the instant before the script measures the rendered bar
   and writes the real height into this property on <body>. Do not tune it to
   match a particular screen: the bar wraps to three lines on a phone, so any
   constant here is right on one width and wrong on the next. */
body.env-staging{ --envbar-h:46px; }

#envBar{
  position:sticky; top:0; z-index:130;
  display:flex; align-items:center; justify-content:center;
  flex-wrap:wrap; gap:5px 12px; text-align:center;
  box-sizing:border-box; min-height:var(--envbar-h); padding:11px 16px;
  background:#C4291F; color:#fff; border-bottom:2px solid #8B1D15;
  font-family:var(--font); font-size:13.5px; font-weight:600; line-height:1.35;
}
#envBar .envbar-tag{
  flex:0 0 auto; white-space:nowrap;
  font-size:11px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  background:rgba(255,255,255,.2); padding:3px 9px; border-radius:4px;
}
#envBar a{
  color:#fff; font-weight:700; white-space:nowrap;
  text-decoration:underline; text-underline-offset:2px; padding:1px 3px; border-radius:3px;
}
#envBar a:hover,#envBar a:focus-visible{ background:rgba(255,255,255,.18); }

/* Everything that pins to the top of the viewport now pins BELOW the bar. */
body.env-staging .sidebar{ top:var(--envbar-h); height:calc(100vh - var(--envbar-h)); }
body.env-staging #loginGate{ top:var(--envbar-h); }

@media (max-width:820px){
  #envBar{ font-size:12.5px; padding:9px 12px; }
  body.env-staging .mobile-topbar{ top:var(--envbar-h); }
  body.env-staging .sidebar{ top:var(--envbar-h); height:calc(100vh - var(--envbar-h)); }
}

/* ============================== ASK PANEL ================================ */
.ask-scrim{
  position:fixed; inset:0; background:rgba(17,24,39,.34);
  opacity:0; pointer-events:none; transition:opacity .2s ease; z-index:155;
}
body.ask-open .ask-scrim{ opacity:1; pointer-events:auto; }
.ask-panel{
  position:fixed; top:0; right:0; bottom:0; width:min(440px,100vw);
  background:var(--surface); border-left:1px solid var(--border);
  box-shadow:-12px 0 40px rgba(17,24,39,.14);
  display:flex; flex-direction:column; z-index:156;
  transform:translateX(102%); transition:transform .24s cubic-bezier(.22,.7,.3,1);
}
body.ask-open .ask-panel{ transform:translateX(0); }
.ask-panel-head{
  display:flex; align-items:flex-start; justify-content:space-between; gap:12px;
  padding:15px 16px; background:var(--chrome); color:var(--text-invert); flex:0 0 auto;
}
.ask-panel-head strong{ font-size:14.5px; }
.ask-panel-sub{ font-size:11.5px; opacity:.72; margin-top:2px; }
.ask-panel-actions{ display:flex; gap:5px; }
.ask-icon{
  display:inline-flex; align-items:center; justify-content:center; width:28px; height:28px;
  border-radius:6px; border:1px solid rgba(255,255,255,.18); background:transparent;
  color:inherit; cursor:pointer; transition:background .14s ease;
}
.ask-icon:hover{ background:rgba(255,255,255,.12); }
.ask-thread{ flex:1 1 auto; overflow-y:auto; padding:16px; background:var(--app-bg); }
.ask-msg{ display:flex; gap:9px; margin-bottom:13px; align-items:flex-start; }
.ask-msg.user{ justify-content:flex-end; }
.ask-avatar{
  flex:0 0 24px; width:24px; height:24px; border-radius:50%; margin-top:2px;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--chrome); color:var(--brand-yellow); font-size:12px;
}
.ask-bubble{
  max-width:82%; padding:10px 13px; border-radius:12px; font-size:13.5px; line-height:1.55;
  background:var(--surface); border:1px solid var(--border); box-shadow:var(--shadow);
}
.ask-msg.user .ask-bubble{ background:var(--chrome); color:var(--text-invert); border-color:var(--chrome); }
.ask-li{ display:block; padding-left:13px; position:relative; }
.ask-li::before{ content:'\00B7'; position:absolute; left:3px; font-weight:700; }
.ask-tools{
  margin-top:8px; padding-top:7px; border-top:1px solid var(--border);
  font-size:10.5px; color:var(--text-muted); letter-spacing:.02em;
}
.ask-err{ color:var(--overdue); }
.ask-dots{ display:inline-flex; gap:4px; padding:3px 0; }
.ask-dots i{ width:6px; height:6px; border-radius:50%; background:#B6BDC7; animation:askPulse 1.1s infinite ease-in-out; }
.ask-dots i:nth-child(2){ animation-delay:.15s; }
.ask-dots i:nth-child(3){ animation-delay:.3s; }
@keyframes askPulse{ 0%,80%,100%{ opacity:.3; transform:translateY(0); } 40%{ opacity:1; transform:translateY(-3px); } }
@media (prefers-reduced-motion:reduce){ .ask-dots i{ animation:none; } .ask-panel{ transition:none; } }

.ask-empty{ text-align:center; padding:26px 8px; }
.ask-empty-title{ font-weight:600; font-size:14.5px; margin-bottom:6px; }
.ask-empty-sub{ font-size:12.5px; color:var(--text-muted); line-height:1.55; max-width:330px; margin:0 auto 16px; }
.ask-suggest{ display:flex; flex-direction:column; gap:8px; align-items:stretch; }
.ask-chip{
  font-family:var(--font); font-size:12.5px; text-align:left; cursor:pointer;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--r-pill);
  padding:9px 14px; color:var(--text); transition:border-color .14s ease, background .14s ease;
}
.ask-chip:hover{ border-color:var(--chrome); background:#FFFEF5; }

.ask-compose{ flex:0 0 auto; display:flex; align-items:flex-end; gap:8px; padding:11px 12px; border-top:1px solid var(--border); background:var(--surface); }
.ask-compose textarea{
  flex:1 1 auto; resize:none; font-family:var(--font); font-size:13.5px; line-height:1.5;
  border:1px solid var(--border); border-radius:12px; padding:9px 11px; max-height:120px; outline:0;
}
.ask-compose textarea:focus{ border-color:var(--chrome); }
.ask-compose .ask-icon{
  border-color:var(--border); color:var(--text-muted); width:34px; height:34px;
  padding:0; overflow:hidden; white-space:nowrap;
}
.ask-compose .ask-icon:hover{ background:#EFF1F4; }
.ask-compose .ask-icon.is-recording{
  background:var(--overdue); color:#fff; border-color:var(--overdue);
  animation:recPulse 1.4s ease-in-out infinite;
}

.ask-history{ flex:0 0 auto; max-height:44%; overflow-y:auto; border-bottom:1px solid var(--border); background:var(--surface); }
.ask-hist-row{ display:flex; align-items:center; gap:8px; padding:10px 14px; border-bottom:1px solid var(--border); cursor:pointer; }
.ask-hist-row:hover{ background:#FBFCFD; }
.ask-hist-main{ flex:1 1 auto; min-width:0; }
.ask-hist-title{ font-size:13px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ask-hist-meta{ font-size:11px; color:var(--text-muted); text-transform:capitalize; }
.ask-hist-del{ border-color:var(--border); color:var(--text-muted); }
.ask-hist-del:hover{ background:var(--overdue-bg); color:var(--overdue); }

/* ------------------------- insight cards ("What can I do better?") ------- */
.insight-title{ display:flex; align-items:center; gap:7px; }
.insight-spark{ display:flex; color:var(--chrome); flex:0 0 auto; }
.insight-tag{
  font-size:9.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:var(--text-muted); background:#EFF1F4; border-radius:var(--r-pill); padding:3px 9px; white-space:nowrap;
}
.insight-list{ display:flex; flex-direction:column; gap:8px; }
.insight-row{
  border:1px solid var(--border); border-radius:10px; padding:11px 13px; background:var(--surface-warm);
  transition:border-color .14s ease, box-shadow .14s ease;
}
.insight-row.clickable{ cursor:pointer; }
.insight-row.clickable:hover{ border-color:var(--border-strong); box-shadow:var(--shadow); }
.insight-row:focus-visible{ outline:2px solid var(--chrome); outline-offset:1px; }
.insight-head{ font-size:13px; font-weight:600; line-height:1.4; }
.insight-detail{ font-size:12px; color:var(--text-muted); line-height:1.5; margin-top:4px; }
.insight-source{
  font-size:10px; color:var(--text-muted); text-transform:uppercase; letter-spacing:.04em;
  margin-top:7px; padding-top:6px; border-top:1px dashed rgba(17,24,39,.10);
}
.insight-loading{ font-size:12.5px; color:var(--text-muted); padding:4px 0; }

/* The draft a proposal produces. It is labelled "not saved" because it is not
   saved: nothing is written until Jay presses Save in the existing form. */
.draft-card{ border:1px solid var(--border-strong); border-radius:10px; padding:12px 13px; background:var(--surface-warm); }
.draft-head{ display:flex; align-items:center; justify-content:space-between; gap:10px; font-weight:700; font-size:13px; margin-bottom:9px; }
.draft-flag{
  font-size:9.5px; font-weight:800; letter-spacing:.07em; text-transform:uppercase;
  background:var(--chrome); color:var(--brand-yellow); border-radius:var(--r-pill); padding:3px 8px;
}
.draft-row{ display:flex; justify-content:space-between; gap:12px; font-size:12.5px; padding:4px 0; border-bottom:1px dashed rgba(17,24,39,.10); }
.draft-row:last-of-type{ border-bottom:0; }
.draft-row span{ color:var(--text-muted); }
.draft-actions{ display:flex; gap:8px; justify-content:flex-end; margin-top:11px; }

/* ========================= SHARED ATTACHMENTS =========================== */
/* Files follow the work through enquiry -> quote -> job, so a tile has to say
   which stage it came in at when it was not added here. */
.file-tile{ display:block; }
.file-doc{
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:5px;
  text-decoration:none; color:var(--text); background:#FCFCFD; padding:10px 8px; text-align:center;
}
.file-doc:hover{ border-color:var(--border-strong); background:var(--info-bg); }
.file-ico{ color:var(--text-muted); line-height:0; }
.file-name{
  font-size:11px; font-weight:600; line-height:1.25; word-break:break-word;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
}
.file-meta{ font-size:10px; color:var(--text-muted); }
.stage-tag{
  position:absolute; left:5px; top:5px; background:rgba(17,24,39,.78); color:#fff;
  font-size:9.5px; font-weight:600; letter-spacing:.03em; text-transform:uppercase;
  padding:2px 6px; border-radius:var(--r-pill);
}
.upload-progress{ margin-top:10px; font-size:12px; color:var(--text-muted); }
.clip-badge{
  display:inline-flex; align-items:center; gap:2px; margin-left:6px; padding:1px 6px 1px 4px;
  background:var(--info-bg); color:var(--text-muted); border-radius:var(--r-pill);
  font-size:10.5px; font-weight:600; vertical-align:middle;
}
.clip-badge svg{ opacity:.75; }

/* ============================== GROWTH ================================== */
.growth-hero{
  background:var(--chrome); color:var(--text-invert); border-radius:var(--r-card);
  padding:20px 22px; margin-bottom:16px; box-shadow:var(--shadow);
}
.gh-top{ display:flex; align-items:center; justify-content:space-between; gap:18px; }
.gh-label{ font-size:11px; text-transform:uppercase; letter-spacing:.06em; color:#9CA3AF; font-weight:600; }
.gh-value{ font-size:38px; font-weight:700; line-height:1.15; display:flex; align-items:baseline; gap:10px; }
.gh-edit{
  background:transparent; border:1px solid rgba(255,255,255,.28); color:#E5E7EB;
  border-radius:var(--r-pill); font-size:11px; padding:3px 10px; cursor:pointer; font-family:var(--font);
}
.gh-edit:hover{ border-color:var(--brand-yellow); color:var(--brand-yellow); }
.gh-gauge{ width:170px; flex:0 0 170px; }
/* The bar is the year; the tick is today. Being left of the tick is being behind. */
.gh-bar{
  position:relative; height:9px; border-radius:var(--r-pill); background:rgba(255,255,255,.14);
  margin:16px 0 10px; overflow:visible;
}
.gh-bar > span{ display:block; height:100%; border-radius:var(--r-pill); background:var(--brand-yellow); }
.gh-pace{
  position:absolute; top:-4px; width:2px; height:17px; background:#fff; opacity:.85; border-radius:1px;
}
.gh-sub{ font-size:12.5px; color:#D1D5DB; }
.gh-flag{ font-weight:600; }
.gh-flag.behind{ color:#FCA5A5; }
.gh-flag.ahead{ color:#86EFAC; }
.growth-hero.no-goal{ text-align:center; }
.growth-hero.no-goal .gh-value{ justify-content:center; font-size:26px; margin-bottom:6px; }
.growth-hero.no-goal .gh-sub{ margin-bottom:14px; }

.growth-cols{ display:grid; grid-template-columns:1fr 1fr; gap:16px; align-items:start; }

.growth-need{ margin-bottom:14px; }
.gn-headline{ font-size:32px; font-weight:700; line-height:1.1; }
.gn-headline span{ display:block; font-size:12.5px; font-weight:500; color:var(--text-muted); margin-top:2px; }
.gn-note{ font-size:12.5px; color:var(--text-muted); margin-top:6px; }

.growth-funnel{ display:flex; flex-direction:column; gap:12px; }
.gf-row{ border-left:3px solid var(--border-strong); padding-left:12px; }
.gf-row.is-done{ border-left-color:var(--won); }
.gf-row.is-short{ border-left-color:var(--due); }
.gf-need{ display:flex; align-items:baseline; gap:7px; }
.gf-need strong{ font-size:21px; font-weight:700; }
.gf-need span{ font-size:12.5px; color:var(--text-muted); }
.gf-bar{ height:6px; border-radius:var(--r-pill); background:var(--border); margin:6px 0 5px; overflow:hidden; }
.gf-bar > span{ display:block; height:100%; background:#2C6BBE; border-radius:var(--r-pill); }
.gf-row.is-done .gf-bar > span{ background:var(--won); }
.gf-got{ font-size:12px; color:var(--text-muted); }
.gf-tick{ color:var(--won); font-style:normal; font-weight:600; margin-left:6px; }
.gf-gap{ color:var(--due); font-style:normal; font-weight:600; margin-left:6px; }
.growth-basis{
  margin-top:14px; padding-top:12px; border-top:1px solid var(--border);
  font-size:12.5px; color:var(--text-muted);
}
.growth-missing{ margin-top:4px; }

.growth-mix{ display:flex; height:12px; border-radius:var(--r-pill); overflow:hidden; background:var(--border); }
.gm-seg{ display:block; height:100%; }
.growth-mix-key{ display:flex; flex-wrap:wrap; gap:14px; margin-top:10px; font-size:12.5px; color:var(--text-muted); }
.growth-mix-key i{ display:inline-block; width:9px; height:9px; border-radius:3px; margin-right:6px; }

.growth-warn{ border-color:#F0D9A8; background:var(--due-bg); }
.growth-outlier{
  display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
  font-size:12.5px; padding:7px 0; border-bottom:1px dashed rgba(17,24,39,.12);
}
.growth-outlier:last-of-type{ border-bottom:0; }

.growth-levers{ display:flex; flex-direction:column; gap:2px; }
.gl-row{
  display:grid; grid-template-columns:1fr auto auto; gap:12px; align-items:baseline;
  padding:8px 0; border-bottom:1px dashed rgba(17,24,39,.10); font-size:12.5px;
}
.gl-row:last-child{ border-bottom:0; }
.gl-row.is-base{ color:var(--text-muted); }
.gl-value{ font-weight:600; white-space:nowrap; }
.gl-delta{ font-size:11.5px; color:var(--won); font-weight:600; white-space:nowrap; }
.gl-row.is-base .gl-delta{ color:var(--text-muted); font-weight:500; }

/* ------------------------------- responsive ------------------------------ */
@media (max-width:1100px){
  .tile-grid{ grid-template-columns:repeat(2,1fr); }
  .hero-row{ grid-template-columns:1fr; }
  .growth-cols{ grid-template-columns:1fr; }
}
@media (max-width:820px){
  .board-controls{ gap:9px; }
  /* The controls must never wrap into a two-line mess on a phone: they scroll. */
  .board-controls .seg{ max-width:100%; overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:none; }
  .board-controls .seg::-webkit-scrollbar{ display:none; }
  .board-period{ order:2; }
  .hero-figure{ font-size:44px; }
  .tile-grid{ grid-template-columns:repeat(2,1fr); gap:10px; }
  .tile-value{ font-size:22px; }
  .ask-bar{ padding-left:12px; gap:6px; }
  /* The scope chip is the first thing to go: the input matters more than the label. */
  .ask-scope{ display:none; }
  .ask-panel{ width:100vw; border-left:0; }
  .ask-bubble{ max-width:88%; }
  .goal-foot{ gap:8px; }
  .goal-foot > div{ flex:1 1 30%; }
  /* Growth on a phone: the gauge and the big number cannot sit side by side
     without the number shrinking to nothing, so the gauge goes under it. */
  .growth-hero{ padding:16px 16px 18px; }
  .gh-top{ flex-direction:column; align-items:flex-start; gap:6px; }
  .gh-value{ font-size:30px; }
  .gh-gauge{ width:100%; flex:0 0 auto; margin-top:4px; }
  .gn-headline{ font-size:26px; }
  /* Three columns of levers do not fit; label over the two figures. */
  .gl-row{ grid-template-columns:1fr auto; }
  .gl-label{ grid-column:1 / -1; font-weight:600; color:var(--text); }
  .gl-row.is-base .gl-label{ color:var(--text-muted); }
}
@media (max-width:420px){
  .tile-grid{ grid-template-columns:1fr; }
}

/* ==========================================================================
   HEADLINE NUMBERS + THE SHEET (2026-07-28, Jay's 27 July feedback)

   "I just want that to be numbers, turnover, leads, ongoing jobs. And I click
    on that ... that will open up the slide."

   Two components: four pressable numbers at the top of Today, and one
   right-hand slide-over that every drill-through opens into. The sheet sits
   at z-index 160, above the ask panel (156), because a list opened from the
   chat has to land on top of it.
   ========================================================================== */
.big-nums{
  display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin-bottom:16px;
}
.big-num{
  display:flex; flex-direction:column; gap:5px; text-align:left;
  padding:16px 16px 15px; background:var(--surface);
  border:1px solid var(--border); border-radius:var(--r-card);
  box-shadow:var(--shadow-card); cursor:pointer; font:inherit; color:inherit;
  transition:border-color .14s ease, box-shadow .14s ease, transform .14s ease;
}
.big-num:hover{ border-color:var(--border-strong); box-shadow:var(--shadow-lift); transform:translateY(-1px); }
.big-num:focus-visible{ outline:2px solid var(--chrome); outline-offset:2px; }
.big-num .bn-label{
  font-size:11px; font-weight:700; letter-spacing:.07em; text-transform:uppercase;
  color:var(--text-muted);
}
.big-num .bn-value{ font-size:30px; font-weight:800; letter-spacing:-.02em; line-height:1.05; }
.big-num .bn-sub{ font-size:11.5px; color:var(--text-muted); }
.big-num.tone-good .bn-value{ color:var(--won); }
.big-num.tone-bad  .bn-value{ color:var(--overdue); }

.needs-card .today-item:first-of-type{ border-top:1px solid var(--border); }
/* The chevron is hover-only elsewhere. On this list it must always show and
   sit centred: it is the affordance that says "there is a named list behind
   this row", and on a phone there is no hover, so a hover-only arrow means
   the one thing Jay asked for is invisible on the device he uses. */
.needs-card .today-go{
  color:var(--text-muted); font-size:17px; line-height:1;
  opacity:.55; align-self:center; margin-left:auto; flex:0 0 auto;
}
.needs-card .today-item.clickable:hover .today-go{ opacity:1; }
.needs-card .today-item{ align-items:center; }

@media (max-width:900px){ .big-nums{ grid-template-columns:repeat(2,1fr); gap:10px; } }
@media (max-width:430px){
  .big-num{ padding:13px 13px 12px; }
  .big-num .bn-value{ font-size:24px; }
}

/* ------------------------------- the sheet ------------------------------ */
.sheet-scrim{
  position:fixed; inset:0; background:rgba(17,24,39,.38);
  opacity:0; pointer-events:none; transition:opacity .2s ease; z-index:159;
}
body.sheet-open .sheet-scrim{ opacity:1; pointer-events:auto; }
.sheet{
  position:fixed; top:0; right:0; bottom:0; width:min(470px,100vw);
  background:var(--surface); border-left:1px solid var(--border);
  box-shadow:-12px 0 40px rgba(17,24,39,.16);
  display:flex; flex-direction:column; z-index:160;
  transform:translateX(102%); transition:transform .24s cubic-bezier(.22,.7,.3,1);
}
body.sheet-open .sheet{ transform:translateX(0); }
.sheet-head{
  display:flex; align-items:flex-start; justify-content:space-between; gap:12px;
  padding:16px; background:var(--chrome); color:var(--text-invert); flex:0 0 auto;
}
.sheet-head h3{ margin:0; font-size:15.5px; color:inherit; }
.sheet-sub{ font-size:11.5px; opacity:.74; margin-top:3px; line-height:1.5; }
.sheet-close{
  flex:0 0 28px; width:28px; height:28px; border-radius:6px;
  border:1px solid rgba(255,255,255,.18); background:transparent; color:inherit;
  cursor:pointer; font-size:13px; line-height:1;
}
.sheet-close:hover{ background:rgba(255,255,255,.12); }
.sheet-body{ flex:1 1 auto; overflow-y:auto; padding:14px 16px; background:var(--app-bg); }
.sheet-foot{
  flex:0 0 auto; padding:11px 16px; border-top:1px solid var(--border);
  background:var(--surface); display:flex; justify-content:flex-end;
}
.sheet-note{
  margin-top:12px; padding:10px 12px; border-radius:var(--r-input);
  background:var(--info-bg); font-size:11.5px; color:var(--text-muted); line-height:1.55;
}

/* ------------------------- named record list ---------------------------- */
.rec-list{ display:flex; flex-direction:column; gap:8px; }
.rec-row{
  display:flex; align-items:center; justify-content:space-between; gap:12px; width:100%;
  padding:12px 13px; background:var(--surface); border:1px solid var(--border);
  border-radius:var(--r-card); cursor:pointer; font:inherit; color:inherit; text-align:left;
  transition:border-color .14s ease, box-shadow .14s ease;
}
.rec-row:hover{ border-color:var(--border-strong); box-shadow:var(--shadow-lift); }
.rec-main{ display:flex; flex-direction:column; gap:2px; min-width:0; }
.rec-name{ font-size:13.5px; font-weight:600; }
.rec-meta{ font-size:11.5px; color:var(--text-muted); line-height:1.45; }
.rec-right{ display:flex; align-items:center; gap:8px; flex:0 0 auto; }
.rec-value{ font-family:'JetBrains Mono',monospace; font-size:12.5px; font-weight:600; white-space:nowrap; }
.rec-value.tone-bad{ color:var(--overdue); }
.rec-value.tone-warn{ color:var(--due); }
.rec-go{ color:var(--text-muted); font-size:17px; line-height:1; }

/* --------------------- turnover, month by month ------------------------- */
.month-list{ display:flex; flex-direction:column; gap:9px; }
.month-row{
  padding:11px 13px; background:var(--surface); border:1px solid var(--border);
  border-radius:var(--r-card);
}
.month-top{ display:flex; align-items:baseline; justify-content:space-between; gap:10px; }
.month-name{ font-size:12.5px; font-weight:600; }
.month-rev{ font-family:'JetBrains Mono',monospace; font-size:13px; font-weight:700; }
.month-bar{ height:5px; border-radius:3px; background:var(--info-bg); margin:7px 0 6px; overflow:hidden; }
.month-bar span{ display:block; height:100%; background:var(--chrome); border-radius:3px; }
.month-foot{ display:flex; justify-content:space-between; gap:10px; font-size:11.5px; color:var(--text-muted); }
.month-foot .pos{ color:var(--won); }
.month-foot .neg{ color:var(--overdue); }
.month-total{
  margin-top:14px; padding:13px; border-radius:var(--r-card);
  background:var(--chrome); color:var(--text-invert);
  display:flex; justify-content:space-between; gap:12px; flex-wrap:wrap;
}
.month-total .label{ display:block; font-size:10.5px; text-transform:uppercase; letter-spacing:.06em; opacity:.7; }
.month-total strong{ font-family:'JetBrains Mono',monospace; font-size:14px; }
.month-total .pos{ color:var(--brand-yellow); }
.month-total .neg{ color:#FF8A93; }

/* The quick-add button is fixed at bottom-right. At bottom:26px on a phone it
   sat ON the tab bar and covered the chevron of whichever action row happened
   to be under it, which both vision reviewers read as "that row is not
   pressable". Lift it clear of the bar. */
@media (max-width:820px){
  .qa-fab{ right:16px; bottom:calc(74px + env(safe-area-inset-bottom)); width:50px; height:50px; font-size:26px; }
}

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

/* ==========================================================================
   THE JOB CALENDAR (2026-08-05)
   A month grid with jobs drawn as bars from start to finish. Read only.
   Bars are laid out per WEEK inside a 7-column grid, which is what lets a
   two-week job draw as one continuous run rather than ten separate chips.
   ========================================================================== */
.cal-head{ display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap; margin-bottom:10px; }
.cal-nav{ display:flex; align-items:center; gap:8px; }
.cal-nav h3{ margin:0; min-width:190px; text-align:center; font-size:17px; }
.cal-legend{ display:flex; align-items:center; gap:14px; font-size:12px; color:var(--text-muted); }
.cal-key{ display:inline-flex; align-items:center; gap:6px; }
.cal-key i{ width:14px; height:9px; border-radius:3px; display:inline-block; }
.cal-key .k-live{ background:#2C6BBE; }
.cal-key .k-booked{ background:var(--due); }
.cal-key .k-done{ background:var(--won); }

.cal-sum{ font-size:13px; color:var(--text-muted); margin-bottom:10px; }
.cal-sum strong{ color:var(--text); }

.cal-grid{ background:var(--surface); border:1px solid var(--border); border-radius:var(--r-card); box-shadow:var(--shadow); overflow:hidden; }
.cal-dow{ display:grid; grid-template-columns:repeat(7,1fr); background:var(--info-bg); border-bottom:1px solid var(--border); }
.cal-dow span{ padding:7px 8px; font-size:11px; letter-spacing:.06em; text-transform:uppercase; color:var(--text-muted); font-weight:600; }

.cal-week{ position:relative; border-bottom:1px solid var(--border); }
.cal-week:last-child{ border-bottom:0; }
.cal-days{ display:grid; grid-template-columns:repeat(7,1fr); }
.cal-day{ min-height:26px; padding:5px 8px 0; border-right:1px solid var(--border); }
.cal-day:last-child{ border-right:0; }
.cal-day.out{ background:#FCFCFD; }
.cal-day.out .cal-dnum{ color:#B6BCC6; }
.cal-day.today .cal-dnum{ background:var(--brand-yellow); color:#111827; border-radius:var(--r-pill); padding:1px 7px; font-weight:700; }
.cal-dnum{ font-size:12px; color:var(--text-muted); font-weight:600; }

.cal-lanes{ padding:2px 0 8px; display:flex; flex-direction:column; gap:3px; min-height:34px; }
.cal-lane{ display:grid; grid-template-columns:repeat(7,1fr); gap:0; }
.cal-bar{
  min-width:0; margin:0 3px; padding:3px 7px; border:0; border-radius:5px; cursor:pointer;
  font:inherit; font-size:11.5px; font-weight:600; line-height:1.35; text-align:left;
  color:#fff; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;
}
.cal-bar:hover{ filter:brightness(1.08); }
.cal-bar:focus-visible{ outline:2px solid var(--chrome); outline-offset:1px; }
.cal-bar-txt{ display:block; overflow:hidden; text-overflow:ellipsis; }
.cal-bar.t-live{ background:#2C6BBE; }
.cal-bar.t-booked{ background:var(--due); }
.cal-bar.t-done{ background:var(--won); }
/* A run continuing past the edge of the week squares off on that side, so a
   job that spans two weeks reads as one job rather than two. */
.cal-bar.open-l{ border-top-left-radius:0; border-bottom-left-radius:0; margin-left:0; }
.cal-bar.open-r{ border-top-right-radius:0; border-bottom-right-radius:0; margin-right:0; }
/* Start date but no finish date: a marker, never an open-ended bar. Eighteen
   live jobs are in this state and drawing them as long bars would make "we do
   not know" look identical to "six weeks on site". */
.cal-bar.one-day{ background:transparent; color:var(--text); border-left:3px solid #2C6BBE; border-radius:0 5px 5px 0; background:#EEF3FA; }
.cal-bar.one-day.t-booked{ border-left-color:var(--due); background:var(--due-bg); }
.cal-bar.one-day.t-done{ border-left-color:var(--won); background:var(--won-bg); }
.cal-more{ font-size:11px; color:var(--text-muted); padding:1px 10px; }

.cal-missing{ margin-top:12px; }
.cal-note{ margin-top:10px; font-size:12.5px; color:var(--text-muted); line-height:1.6; max-width:70ch; }

@media (max-width:760px){
  .cal-head{ gap:8px; }
  .cal-nav h3{ min-width:0; flex:1; font-size:15px; }
  .cal-legend{ width:100%; justify-content:flex-start; }
  .cal-dow span{ padding:6px 4px; font-size:10px; }
  .cal-day{ padding:4px 4px 0; }
  .cal-bar{ font-size:10px; padding:2px 4px; margin:0 1px; }
}
