/* Black & Gold theme — token-based, two palettes (DARK default, LIGHT via
   :root[data-theme="light"], toggled + persisted by the switch in the
   header — see app.js's initTheme()/wireThemeToggle()). Everything below
   reads off --bg/--panel/--ink/etc.; --paper/--card/--faint/--goldb/--goldd/
   --navy/--navy2 are kept as aliases so the rest of this file (and a few
   inline styles in app.js) don't need touching just because the palette
   changed color. Semantic status colors (--good/--warn/--crit/--info) are
   tuned per theme but kept separate from the gold accent on purpose — the
   🟢🟡🔴 health colors must stay readable regardless of the brand color. */
:root{
  --bg:#0c0c0e;--panel:#161619;--panel2:#1c1c21;--header:#0a0a0b;
  --line:#2c2c32;--line2:#3a3a42;
  --ink:#f4efe1;--muted:#a49d8c;--dim:#6f695c;
  --gold:#c49b3e;--gold2:#d9b85f;--gold-deep:#8f6d1c;
  --paper:var(--bg);--card:var(--panel);--faint:var(--dim);
  --goldb:var(--gold);--goldd:var(--gold-deep);
  --navy:var(--gold);--navy2:var(--gold2);
  --good:#63C08E;--good-bg:#14301F;--warn:#E0AC55;--warn-bg:#33260F;
  --crit:#E8756B;--crit-bg:#391714;--info:#79A6D8;--info-bg:#122437;
  --shadow:0 1px 2px rgba(0,0,0,.5),0 10px 26px rgba(0,0,0,.4);
  /* Schedule Timeline lane accents (Wave 5) — warm neighbors of the one
     gold brand color (amber/rust/olive/wine/bronze), deliberately NO blue,
     so each crew lane reads as distinct without introducing a second
     "primary" color into a black & gold app. Cycled by lane position —
     see app.js's SCHED_TL_PALETTE. */
  --tl-1:#c49b3e;--tl-2:#c97a4a;--tl-3:#8a9a5b;--tl-4:#b5707d;--tl-5:#a68a64;--tl-6:#d9b85f;
  /* White-label accent for the unauthenticated /sign e-sign page — set at
     runtime by app.js's applySignBrand() off the signing tenant's own
     org (see GET /api/sign/{token}); falls back to OG's own gold so the
     page still looks intentional before that JS runs. Same idea as
     portal.js/portal.css's own --accent for the client portal. */
  --accent:var(--gold);
}
:root[data-theme="light"]{
  --bg:#f4efe2;--panel:#fffdf6;--panel2:#f7f1e2;--header:#111112;
  --line:#e6ddc8;--line2:#ddd0ac;
  --ink:#161512;--muted:#5c5645;--dim:#8a8270;
  --gold:#8f6c15;--gold2:#a67c17;--gold-deep:#6f5410;
  --paper:var(--bg);--card:var(--panel);--faint:var(--dim);
  --goldb:var(--gold);--goldd:var(--gold-deep);
  --navy:var(--gold);--navy2:var(--gold2);
  --good:#2E7D52;--good-bg:#E4F0E8;--warn:#B0741A;--warn-bg:#F7ECD7;
  --crit:#B3261E;--crit-bg:#F7DEDB;--info:#3A6EA5;--info-bg:#E5EEF7;
  --shadow:0 1px 2px rgba(20,28,45,.05),0 8px 22px rgba(20,28,45,.07);
  --accent:var(--gold);
  --tl-1:#8f6c15;--tl-2:#a15a2e;--tl-3:#5f6e3a;--tl-4:#8a4a56;--tl-5:#7a6440;--tl-6:#a67c17;
}
*{box-sizing:border-box}
body{margin:0;background:var(--paper);color:var(--ink);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  line-height:1.5;-webkit-font-smoothing:antialiased;font-variant-numeric:tabular-nums}
.mono{font-family:ui-monospace,"SF Mono",Menlo,Consolas,monospace}
.hidden{display:none!important}
.wrap{max-width:900px;margin:0 auto;padding:0 16px}

/* app shell: a condensed top bar — parent tabs, with a sub-tab row revealed
   below the active parent ("tabs-under-tabs") — same on desktop and phone,
   scrolling horizontally on narrow screens instead of a hamburger drawer.
   See index.html's #app/.apphead/#navwrap and app.js's ownerMenu/
   leaderMenu/salesMenu/crewMenu + renderNav()/openParent()/go(). */
#app{min-height:100vh}
.apphead{background:var(--header);color:#f3ecda;position:sticky;top:0;z-index:20;
  border-bottom:1px solid var(--line)}
.apphead-row{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:10px 14px 4px;flex-wrap:wrap}
.apphead .brand{color:var(--goldb);padding:0}
.apphead .brand .cn{color:#b9b09a}
.apphead-right{display:flex;align-items:center;gap:12px;flex-wrap:wrap}

/* Dark/light theme toggle — a small slider under the "OG Construction"
   title (see index.html's .theme-switch blocks + app.js's initTheme()/
   wireThemeToggle()). Track/thumb read off tokens so it looks right on the
   login screen's --bg surface, which flips with the theme; the app-header
   variant below overrides to a white-based overlay since that surface is
   always the near-black --header in both themes — same idea as the
   header's own hardcoded cream text (#f3ecda) elsewhere. */
.theme-switch{display:inline-flex;align-items:center;gap:6px;margin:0 8px 10px;cursor:pointer;user-select:none}
.theme-switch.center{margin:6px auto 4px;justify-content:center}
.theme-switch input{position:absolute;opacity:0;width:1px;height:1px}
.theme-switch .ts-track{position:relative;width:34px;height:18px;border-radius:999px;
  background:var(--line2);border:1px solid var(--line);flex:none;transition:background .15s ease}
.theme-switch .ts-thumb{position:absolute;top:1px;left:1px;width:14px;height:14px;border-radius:50%;
  background:var(--goldb);transition:transform .15s ease}
.theme-switch input:checked+.ts-track{background:var(--goldd)}
.theme-switch input:checked+.ts-track .ts-thumb{transform:translateX(16px);background:var(--header)}
.theme-switch input:focus-visible+.ts-track{outline:2px solid var(--goldb);outline-offset:2px}
.apphead .theme-switch .ts-track{background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.22)}
.apphead .theme-switch input:checked+.ts-track{background:rgba(255,255,255,.26)}
.apphead .whoami{font-size:12px;color:#cfc7ae;display:flex;align-items:center;gap:8px;white-space:nowrap}
.apphead .whoami b{color:#f3ecda}
.apphead .whoami .role{font-family:ui-monospace,monospace;font-size:9px;color:var(--goldb);text-transform:uppercase;letter-spacing:.05em}
.apphead .whoami .link{color:var(--goldb)}

/* Parent-tab row (top) + sub-tab row (revealed below the active parent) —
   see app.js's renderNav(). Both rows scroll horizontally rather than
   wrapping, so the condensed ~9-tab bar stays one line even on a phone. */
.navrow{display:flex;gap:4px;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:thin}
.navrow.parents{padding:2px 10px 8px}
.navrow.subs{padding:0 10px 8px;gap:6px}
.navtab{flex:none;border:none;background:transparent;color:#e6ddc7;font:inherit;font-size:13.5px;font-weight:700;
  padding:8px 12px;border-radius:8px;cursor:pointer;white-space:nowrap}
.navtab:hover{background:rgba(255,255,255,.08)}
.navtab.on{background:var(--goldb);color:#20160a}
.subnavtab{flex:none;border:1px solid rgba(255,255,255,.2);background:transparent;color:#e6ddc7;font:inherit;
  font-size:12.5px;font-weight:600;padding:6px 12px;border-radius:16px;cursor:pointer;white-space:nowrap}
.subnavtab:hover{border-color:var(--gold2)}
.subnavtab.on{background:var(--goldb);border-color:var(--goldb);color:#20160a}

main{padding:18px 0 60px}
h2.view{font-size:19px;margin:0 0 14px;color:var(--gold)}
.card{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:16px;box-shadow:var(--shadow);margin-bottom:14px}
.card h3{margin:0 0 10px;font-size:15px}
label{display:block;font-size:12px;color:var(--muted);margin:10px 0 4px;font-weight:600}
input,select,textarea{width:100%;font:inherit;font-size:15px;padding:10px 12px;border:1px solid var(--line2);
  border-radius:9px;background:var(--card);color:var(--ink)}
textarea{min-height:64px;resize:vertical}
input:focus,select:focus,textarea:focus{outline:2px solid var(--goldb);outline-offset:1px}
.btn{display:inline-flex;justify-content:center;align-items:center;gap:8px;width:100%;font:inherit;font-weight:700;
  font-size:15px;padding:13px;border:none;border-radius:10px;background:var(--goldb);color:#20160a;cursor:pointer;margin-top:12px}
.btn:active{transform:translateY(1px)}
.btn.navy{background:var(--header);color:var(--gold2)}
.btn.ghost{background:transparent;color:var(--gold);border:1px solid var(--line2)}
.btn.crit{background:var(--crit);color:#fff}
.btn.sm{width:auto;padding:7px 12px;font-size:13px;margin:0}
.link{color:var(--gold);cursor:pointer;text-decoration:underline;font-size:13px}
.msg{padding:10px 12px;border-radius:8px;font-size:13px;margin:10px 0}
.msg.err{background:var(--crit-bg);color:var(--crit)}.msg.ok{background:var(--good-bg);color:var(--good)}
.msg.warn{background:var(--warn-bg);color:var(--warn)}

/* tiles */
.tiles{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:14px}
.tile{background:var(--card);border:1px solid var(--line);border-radius:11px;padding:13px;box-shadow:var(--shadow)}
.tile .k{font-family:ui-monospace,monospace;font-size:9.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--muted)}
.tile .v{font-size:22px;font-weight:800;color:var(--gold);margin-top:3px}
.tile.good .v{color:var(--good)}
.alarm{background:var(--crit-bg);color:var(--crit);border-radius:9px;padding:10px 13px;font-size:13px;font-weight:600;margin-bottom:8px;display:flex;gap:8px}

/* job + list rows */
.jrow{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:11px 0;border-top:1px solid var(--line)}
.jrow:first-child{border-top:none}
.jrow .nm{font-weight:700;font-size:14px}.jrow .nm .wo{font-family:ui-monospace,monospace;color:var(--gold);font-size:12px}
.jrow .sub{font-size:11.5px;color:var(--faint)}
.jrow .rt{text-align:right}
.jrow .rt .m{font-weight:800;color:var(--good)}.jrow .rt .h{font-size:11px;color:var(--muted)}
/* Work Order health traffic light (green/yellow/red) — same left-border
   convention as .attn .item's crit/warn/info, applied to a job-list row. */
.jrow.wo-health{border-left:3px solid var(--muted);padding-left:8px}
.jrow.wo-health.health-green{border-left-color:var(--good)}
.jrow.wo-health.health-yellow{border-left-color:var(--warn)}
.jrow.wo-health.health-red{border-left-color:var(--crit)}
.bar{height:7px;background:var(--line);border-radius:4px;overflow:hidden;margin-top:5px;width:120px}
.bar>i{display:block;height:100%;background:var(--good)}
.bar>i.near{background:var(--warn)}.bar>i.over{background:var(--crit)}
.chip{font-family:ui-monospace,monospace;font-size:9px;font-weight:700;padding:3px 8px;border-radius:999px;text-transform:uppercase}
.chip.owner{background:var(--header);color:var(--gold2)}.chip.exec,.chip.office{background:var(--good-bg);color:var(--good)}
.chip.superintendent{background:var(--info-bg);color:var(--info)}.chip.lead,.chip.fulfillment{background:var(--warn-bg);color:var(--warn)}
.chip.status-lead,.chip.status-scheduled{background:var(--info-bg);color:var(--info)}
.chip.status-active{background:var(--good-bg);color:var(--good)}
.chip.status-done{background:var(--line);color:var(--muted)}
.pill{font-family:ui-monospace,monospace;font-size:9px;font-weight:700;text-transform:uppercase;
  letter-spacing:.05em;padding:3px 8px;border-radius:999px;white-space:nowrap}
.pill.ok,.pill.in{background:var(--good-bg);color:var(--good)}
.pill.warn{background:var(--warn-bg);color:var(--warn)}
.pill.crit{background:var(--crit-bg);color:var(--crit)}
.pill.off{background:var(--line);color:var(--muted)}
.pill.info{background:var(--info-bg);color:var(--info)}

/* Requests closed-loop: clickable queue row + the request detail page */
.reqrow.clickable{cursor:pointer}
.reqrow.clickable:hover{background:var(--paper)}
.reqbanner{background:var(--warn-bg);color:var(--warn);border-radius:9px;padding:9px 12px;
  font-size:13px;margin:10px 0}
.reqbanner b{color:inherit}

.crewline{display:grid;grid-template-columns:1.4fr 1fr .8fr auto;gap:6px;align-items:center;margin-bottom:6px}
.crewline input{padding:8px 9px;font-size:13px}
.crewline .x{color:var(--crit);cursor:pointer;font-weight:700;padding:0 6px}
.reqrow{display:flex;justify-content:space-between;gap:10px;padding:10px 0;border-top:1px solid var(--line);font-size:13px}
.muted{color:var(--muted);font-size:12.5px}
.center{text-align:center}
.login-wrap{max-width:380px;margin:8vh auto 0}
.login-wrap .brand{text-align:center;margin-bottom:6px}
.login-wrap .brand .og{font-size:52px}.login-wrap .brand .cn{font-size:16px}
/* White-label brand mark for the /sign e-sign page (see applySignBrand in
   app.js) — same shape as the client portal's own .brandmark in
   portal.css: an optional logo image above a company-name line, colored
   with the tenant's own --accent rather than a hardcoded wordmark. */
.login-wrap .brandmark{display:flex;flex-direction:column;align-items:center;gap:8px;margin-bottom:6px}
.login-wrap .brandmark img{max-height:56px;max-width:220px;object-fit:contain}
.login-wrap .brandmark .name{font-size:22px;font-weight:800;color:var(--accent)}
/* The Sign & submit button itself picks up the tenant's accent too — same
   as the client portal's own buttons (portal.css's .btn) — so the color a
   client sees isn't just the brand name text. Scoped to #signview only:
   every other button in the app keeps the house gold, since --accent stays
   at its default (OG's navy) everywhere else — applySignBrand() only ever
   overrides it on this one unauthenticated page. */
#signview .card .btn{background:var(--accent)}
.seg{display:flex;gap:6px;margin:14px 0}
.seg button{flex:1;font:inherit;font-size:13px;padding:8px;border:1px solid var(--line2);background:var(--card);border-radius:8px;cursor:pointer;color:var(--muted)}
.seg button.on{background:var(--gold);color:#20160a;border-color:var(--gold);font-weight:700}

/* Team screen: per-user permission toggles */
.perms{display:grid;grid-template-columns:1fr;gap:2px;margin:4px 0 12px}
@media(min-width:520px){.perms{grid-template-columns:1fr 1fr}}
.permrow{display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:8px;font-size:13px;cursor:pointer}
.permrow:hover{background:var(--card)}
.permrow input{width:16px;height:16px;margin:0;flex:none}
.permrow.off{opacity:.5;cursor:not-allowed}
.chip.crew{background:var(--line);color:var(--muted)}

/* schedule: month calendar */
.scal-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}
.scal-head b{font-size:14px;color:var(--gold)}
.scal-dow{display:grid;grid-template-columns:repeat(7,1fr);gap:3px;font-size:10px;color:var(--faint);
  text-align:center;margin-bottom:3px}
.scal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:3px}
.scal-cell{min-height:60px;border:1px solid var(--line);border-radius:7px;padding:4px;cursor:pointer;
  font-size:10px;background:var(--paper);overflow:hidden}
.scal-cell.empty{border-color:transparent;background:transparent;cursor:default}
.scal-cell.sel{border-color:var(--goldb);border-width:2px;padding:3px}
.scal-cell:hover:not(.empty){border-color:var(--gold2)}
.scal-num{font-weight:700;color:var(--muted);margin-bottom:2px}
.schip{background:var(--info-bg);color:var(--info);border-radius:5px;padding:2px 4px;margin-bottom:2px;
  line-height:1.3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.schip:hover{background:var(--gold);color:#20160a}

/* photo gallery */
.pgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:6px;margin-bottom:10px}
.pthumb{display:block;aspect-ratio:1;border-radius:8px;overflow:hidden;border:1px solid var(--line)}
.pthumb img{width:100%;height:100%;object-fit:cover;display:block}

/* dashboard job-cost breakdown */
.stat-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px 10px;margin-top:10px;padding-top:10px;
  border-top:1px solid var(--line);font-size:12.5px}
.stat-grid div{display:flex;justify-content:space-between;gap:6px}
.stat-grid b{color:var(--ink)}

/* cockpit dashboard: KPI tiles, P&L-by-job bars, attention list */
.cockpit-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;margin-bottom:14px}
.cols2{display:grid;grid-template-columns:1.5fr 1fr;gap:14px}
@media(max-width:820px){.cols2{grid-template-columns:1fr}}
.plrow{cursor:pointer;padding:8px 0}
.plrow .top{display:flex;justify-content:space-between;font-size:13px;margin-bottom:4px;gap:8px}
.plrow .top .mg{font-weight:800;white-space:nowrap}
.plbar{height:11px;background:var(--line);border-radius:6px;overflow:hidden;display:flex;border:1px solid var(--line2)}
.plbar i{display:block;height:100%}
.plbar .cost{background:linear-gradient(90deg,#9c6f28,#c99a3f)}
.plbar .prof{background:linear-gradient(90deg,#2e7d32,#57b45c)}

/* money-meter: contract vs. spent-so-far -> margin remaining, colored by
   health (green/amber/red/gray). Shared by job-detail, the client hub's
   compact per-job row, and the dashboard's margin-watch tile. */
.money-meter{margin:6px 0}
.money-meter .mm-bar{height:14px;background:var(--line);border-radius:7px;overflow:hidden;
  border:1px solid var(--line2)}
.money-meter.compact .mm-bar{height:8px}
.money-meter .mm-bar i{display:block;height:100%;border-radius:7px 0 0 7px;transition:width .3s}
.money-meter .mm-row{display:flex;justify-content:space-between;gap:8px;font-size:12px;margin-top:4px;flex-wrap:wrap}
.money-meter.compact .mm-row{font-size:11px}
.money-meter .mm-remain{font-weight:800;white-space:nowrap}
.margin-watch-row{display:flex;justify-content:space-between;align-items:center;gap:8px;
  padding:7px 0;border-bottom:1px solid var(--line);cursor:pointer}
.margin-watch-row:last-child{border-bottom:none}
.margin-watch-row .mwr-name{font-size:13px;font-weight:600}
.margin-watch-row .mwr-meter{flex:1;max-width:160px}
.attn{display:flex;flex-direction:column;gap:8px}
.attn .item{display:flex;flex-direction:column;gap:2px;font-size:13px;padding:9px 11px;border-radius:9px;
  background:var(--paper);border-left:3px solid var(--muted);cursor:default}
.attn .item.clickable{cursor:pointer}
.attn .item.crit{border-left-color:var(--crit)}.attn .item.warn{border-left-color:var(--warn)}
.attn .item.info{border-left-color:var(--info)}
.attn .item .t{font-weight:700}
.attn .item .m{color:var(--muted);font-size:12px}
.live-dot{color:var(--good);font-weight:700}

/* unified job detail page */
.dhead{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;flex-wrap:wrap;
  border-bottom:2px solid var(--goldb);padding-bottom:12px;margin-bottom:14px}
.dhead .wob{font-family:ui-monospace,monospace;font-weight:800;font-size:22px;color:var(--goldb)}
.dhead .clb{font-size:16px;font-weight:700;margin-top:2px}
/* Work Order health traffic light on the job hub header — same left-border
   convention as .jrow.wo-health on the list. */
.dhead.wo-health{border-left:3px solid var(--muted);padding-left:10px}
.dhead.wo-health.health-green{border-left-color:var(--good)}
.dhead.wo-health.health-yellow{border-left-color:var(--warn)}
.dhead.wo-health.health-red{border-left-color:var(--crit)}
.dgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:10px;margin-bottom:14px}
.fact{background:var(--paper);border:1px solid var(--line);border-radius:9px;padding:9px 11px}
.fact .k{font-family:ui-monospace,monospace;font-size:9.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
.fact .v{font-weight:800;font-size:15px;margin-top:2px}
.sec{border:1px solid var(--line);border-radius:11px;margin-bottom:9px;overflow:hidden}
.sec>button.sechead{width:100%;text-align:left;background:var(--paper);border:none;font:inherit;font-weight:700;
  font-size:14px;color:var(--ink);padding:11px 13px;cursor:pointer;display:flex;justify-content:space-between;align-items:center}
.sec>button.sechead .c{font-size:11px;color:var(--muted);font-weight:600}
.sec .body{padding:6px 13px 13px;display:none}
.sec.open .body{display:block}
.sec .body table{width:100%;border-collapse:collapse;font-size:13px}
.sec .body td{padding:6px 4px;border-bottom:1px solid var(--line);vertical-align:top}
.sec .body td.r{text-align:right}
.thumbs{display:flex;gap:8px;flex-wrap:wrap}
.thumb-lnk{width:78px;height:60px;border-radius:8px;overflow:hidden;border:1px solid var(--line);display:block}
.thumb-lnk img{width:100%;height:100%;object-fit:cover;display:block}
/* per-job photo gallery/timeline (CompanyCam parity): date-ordered cards,
   each with a thumbnail + who took it + when + optional caption. */
.phototl{display:flex;flex-direction:column;gap:8px}
.phototl-item{display:flex;gap:10px;align-items:flex-start;padding:8px;border:1px solid var(--line);border-radius:10px}
.phototl-thumb{width:88px;height:88px;flex-shrink:0;border-radius:8px;overflow:hidden;border:1px solid var(--line);display:block}
.phototl-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.phototl-meta{flex:1;min-width:0}
.phototl-cap{font-weight:600;font-size:13.5px;overflow-wrap:anywhere}
.phototl-sub{font-size:11.5px;color:var(--muted);margin-top:2px}
.note{font-size:12px;color:var(--muted);background:var(--paper);border:1px dashed var(--line2);border-radius:9px;
  padding:9px 11px;margin-top:8px}

/* "coming soon" placeholder for a reserved-but-unbuilt nav slot */
.coming-soon{padding:26px 16px;text-align:center}
.coming-soon .ic{font-size:30px;opacity:.7}
.coming-soon h3{margin:8px 0 4px}
.coming-soon p{color:var(--muted);max-width:440px;margin:0 auto}

/* phone-first crew "My Day" clock card */
.clockcard{text-align:center;padding:22px 14px}
.clockcard .lab{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em;font-weight:700}
.clockcard .wo{font-family:ui-monospace,monospace;font-weight:800;font-size:22px;color:var(--goldb);margin-top:4px}
.clockcard .ad{color:var(--muted);font-size:13px}
.clockbtn{margin-top:18px;width:100%;max-width:280px;background:var(--good);color:#fff;border:none;
  border-radius:16px;padding:20px;font:inherit;font-weight:800;font-size:19px;letter-spacing:.02em;cursor:pointer;
  box-shadow:0 6px 16px rgba(46,125,50,.3)}
.clockbtn.out{background:var(--crit);box-shadow:0 6px 16px rgba(192,57,49,.28)}

/* doc editor (Estimates/Proposals "type it like Word") — Quill vendored in
   static/vendor/quill; these just fit its toolbar/container into the app's
   existing card look instead of Quill's own page-width defaults. */
#dc_toolbar.ql-toolbar.ql-snow{border-radius:8px 8px 0 0;background:var(--paper,#f7f7f5)}
#dc_body.ql-container.ql-snow{border-radius:0 0 8px 8px;font-size:14px}
#dc_toolbar button[type="button"]{width:auto;padding:3px 6px;font-size:12px}

/* toast + inline confirm — replaces every browser alert()/confirm() (see
   app.js's toast()/confirmDialog()). No library. */
#toastHost{position:fixed;left:0;right:0;bottom:18px;display:flex;flex-direction:column;
  align-items:center;gap:8px;z-index:200;pointer-events:none;padding:0 16px}
.toast{max-width:420px;width:100%;background:var(--header);color:#f3ecda;border-radius:10px;
  padding:12px 16px;font-size:14px;font-weight:600;box-shadow:var(--shadow);
  opacity:0;transform:translateY(8px);transition:opacity .18s ease,transform .18s ease;
  pointer-events:auto}
.toast.show{opacity:1;transform:translateY(0)}
.toast.err{background:var(--crit)}
.toast.warn{background:var(--warn);color:#20160a}

.confirm-overlay{position:fixed;inset:0;background:rgba(20,28,45,.45);z-index:210;
  display:flex;align-items:center;justify-content:center;padding:16px}
.confirm-box{background:var(--card);border-radius:12px;box-shadow:var(--shadow);
  padding:20px;max-width:380px;width:100%}
.confirm-box p{margin:0 0 16px;font-size:14px;line-height:1.5;color:var(--ink)}
.confirm-actions{display:flex;gap:8px}
.confirm-actions .btn{margin-top:0}

/* empty-state kit — every bare "Nothing yet." list gets an icon, a one-line
   explanation of what shows up here, and a primary CTA (see app.js's
   emptyState()). Same visual weight as .coming-soon, distinct name since
   the meaning differs (a real, working screen with no data yet vs. a
   reserved-but-unbuilt nav slot). */
.empty-state{padding:30px 16px;text-align:center}
.empty-state .ic{font-size:32px;opacity:.8}
.empty-state h3{margin:10px 0 4px;font-size:15px}
.empty-state p{color:var(--muted);max-width:420px;margin:0 auto 14px;font-size:13px}
.empty-state .btn{width:auto;padding:11px 20px;display:inline-flex}
.empty-state .secondary{display:block;margin-top:10px}

/* Pipeline board: Open/Converted/Completed/Lost columns — same .card/.jrow
   look as every other list, just laid out side by side. Collapses to 2
   columns then 1 on a narrower screen, same idiom as .cockpit-tiles/.cols2. */
.pipecols{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;align-items:start}
@media(max-width:900px){.pipecols{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.pipecols{grid-template-columns:1fr}}
.pipecol-head{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:4px}
.pipecol-head h3{margin:0;font-size:12.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}

/* Schedule TIMELINE (Wave 5, compacted Wave 13 S1) — ONE lane per crew,
   always stacked vertically (never side-by-side — see the reference mock
   this rebuild matched), each lane a .card with a colored left bar + name
   + count, and its own jobs running left-to-right in a horizontally-
   scrolling row. `.tl-window` is the "Next 2 weeks / 4 weeks / All
   upcoming" control + the covered-range label, above the lanes.
   S1 (Oleg: "shrink so ~5 jobs fit before scrolling, scannable at a
   glance"): card width/padding/type sizes were cut roughly in half from
   the original build (232px -> 132px cards) — on the app's own 900px
   content width that's ~5.5 cards visible per lane with no scrolling at
   all; on a 390px phone ~2 fit before the row's own internal scroll takes
   over (never the page's), still legible at these sizes. */
.tl-window{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:10px 14px}
.tl-window label{margin:0;font-weight:700;font-size:12.5px;color:var(--muted)}
.tl-window select{width:auto;margin:0}
.tl-board{display:flex;flex-direction:column;gap:10px}
.tl-lane{padding:8px 10px 4px}
.tl-lane-head{display:flex;align-items:center;gap:8px}
.tl-lane-head h3{margin:0;font-size:13px}
.tl-bar{width:5px;height:18px;border-radius:3px;background:var(--tl-accent);flex:none}
.tl-cnt{margin-left:auto;font-weight:600;font-size:11px;white-space:nowrap}
/* The horizontal-scroll row itself — this is what keeps a lane's cards
   off the page's own horizontal scroll at phone width (~400px): the row
   scrolls internally, the page never does. */
.tl-cards{display:flex;gap:8px;overflow-x:auto;padding:8px 2px 6px;
  -webkit-overflow-scrolling:touch;scrollbar-width:thin}
.tl-card{flex:0 0 132px;border:1px solid var(--line);border-radius:8px;padding:7px 8px;
  border-left:3px solid var(--tl-accent);cursor:pointer}
.tl-card:hover{border-color:var(--gold2);border-left-color:var(--tl-accent)}
.tl-card .tl-seq{font-size:9px;font-weight:800;letter-spacing:.04em;color:var(--muted);margin-bottom:1px}
.tl-card .nm{font-weight:700;font-size:12px;line-height:1.25}
.tl-card .nm .wo{font-family:ui-monospace,monospace;color:var(--gold);font-size:10.5px;margin-right:3px}
.tl-card .tl-client{font-size:11.5px;font-weight:600}
.tl-card .sub{font-size:10.5px;color:var(--faint);margin-top:1px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tl-card .tl-datepill{margin-top:5px;display:inline-block;font-size:10px;padding:2px 6px}
/* A job whose carryover chain has slipped 2+ times in a row
   (ops_cascade.py's flagged_jobs) — same crit-border convention as
   .jrow.wo-health/.dhead.wo-health, applied to the timeline card. */
.tl-card.flagged{border-color:var(--crit);border-left-color:var(--crit)}
/* W17 board parity: crew chips (with a × to remove), the "+ crew" add
   select, the borrowed-people row, and the note-count badge — all inside
   the existing .tl-card, no new wrapper element needed for the click-to-
   open-job area above them. */
.tl-chips{display:flex;flex-wrap:wrap;gap:4px;align-items:center;margin-top:8px}
.tl-chips .chip.crew{display:inline-flex;align-items:center;gap:4px;cursor:default}
.tl-chips .chip-x{cursor:pointer;font-weight:800;opacity:.65}
.tl-chips .chip-x:hover{opacity:1}
.tl-addcrew{width:auto;margin:0;font-size:11px;padding:2px 6px;height:auto}
.tl-card .tl-people{margin-top:2px}
.tl-card .tl-notes{margin-left:4px;padding:1px 6px}
.tl-complete{display:block;margin-top:8px;width:100%}
/* Drag-and-drop between lanes (crew reassign / Finished). */
.tl-card[draggable="true"]{cursor:grab}
.tl-lane.tl-dragover{outline:2px dashed var(--gold2);outline-offset:-4px}
/* Zoom control: a smaller/denser card for scanning a big board at a
   glance, toggled on the board's own container so every lane shrinks
   together. */
.tl-board.tl-compact .tl-card{flex-basis:150px;padding:7px 8px}
.tl-board.tl-compact .tl-card .sub,
.tl-board.tl-compact .tl-card .tl-scope,
.tl-board.tl-compact .tl-card .tl-people{display:none}
.tl-board.tl-compact .tl-card .nm{font-size:12px}
.tl-zoom{margin-left:8px}
/* Schedule Board Calendar view's own day chip needs its own "slipping"
   variant of .schip (which the day/time scheduler's calendar already
   uses) — same red as every other slipping signal in the app. */
.schip.crit{background:var(--crit-bg);color:var(--crit)}
.schip.crit:hover{background:var(--crit);color:#fff}

/* S4: the "Unassigned / to schedule" backlog — a plain read-only LIST atop
   the Timeline's crew lanes (see unassignedBacklogHtml), styled off the
   SAME .jrow every other job list in the app already uses, so it reads as
   an ordinary list, not a lane pretending to be a crew's. */
.tl-backlog .tl-bar{background:var(--dim)}
.tl-backlog-list .jrow{padding:8px 0}

/* Schedule Board Calendar view (Wave 13 rebuild, S3) — a month grid of
   WEEKS, each week its own mini CSS-grid: a day-number row, then one row
   per "bar lane" underneath carrying each job's continuous
   start->finish span for that week (see _calendarWeekHtml/_assignBarLanes)
   — never a chip repeated on every day a job covers. */
.scal-week{display:grid;grid-template-columns:repeat(7,1fr);gap:2px 3px;margin-bottom:3px}
.scal-daynum{grid-row:1;font-size:10px;font-weight:700;color:var(--muted);padding:1px 3px}
.scal-bar{border-radius:4px;background:var(--tl-1);color:#181109;font-size:9.5px;font-weight:700;
  padding:0 5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;
  display:flex;align-items:center}
.scal-bar.crit{background:var(--crit);color:#fff}

/* STAFFING BOARD (Wave 13, S5) — crew rows down the side, months across the
   top, a color-coded bar per job spanning its real start->finish dates
   (see renderStaffingBoard). One shared horizontally-scrolling strip
   (`.staff-scroll`) so every row's bars, and the month header, all page in
   lockstep with a single scroll gesture — the crew-name column stays
   pinned via `position:sticky` instead of a second, synced scrollbar. */
:root{
  --staff-big:var(--gold2);--staff-weather:var(--crit);--staff-exterior:var(--tl-3);
  --staff-interior:var(--info);--staff-decision:var(--tl-4);--staff-none:var(--dim);
}
.staff-legend{display:flex;flex-wrap:wrap;gap:10px 16px;padding:10px 14px}
.staff-legend-item{display:flex;align-items:center;gap:6px;font-size:11.5px;color:var(--muted)}
.staff-swatch{width:11px;height:11px;border-radius:3px;flex:none}
.staff-board{padding:0;overflow:hidden}
.staff-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:thin;padding:8px 0}
.staff-row{display:flex;align-items:center;min-height:26px}
.staff-header-row{min-height:20px;margin-bottom:4px}
.staff-rowname{flex:0 0 96px;position:sticky;left:0;z-index:2;background:var(--panel);
  font-size:11px;font-weight:700;padding:2px 8px 2px 14px;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.staff-track{position:relative;height:20px;flex:0 0 auto}
.staff-month{position:absolute;top:0;font-size:10px;font-weight:700;color:var(--muted);
  border-left:1px solid var(--line);padding-left:4px;height:100%}
.staff-bar{position:absolute;top:2px;height:16px;border-radius:4px;background:var(--staff-none);
  color:#181109;font-size:9.5px;font-weight:700;padding:0 5px;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;cursor:pointer;display:flex;align-items:center}
.staff-bar.crit{background:var(--crit);color:#fff}
@media(max-width:390px){
  .staff-rowname{flex-basis:76px;font-size:10px;padding-left:8px}
}

/* dashboard getting-started checklist */
.getting-started ul{list-style:none;margin:0;padding:0}
.getting-started li{display:flex;align-items:center;gap:10px;padding:8px 0;
  border-top:1px solid var(--line);font-size:13.5px}
.getting-started li:first-child{border-top:none}
.getting-started .gs-check{width:20px;height:20px;border-radius:50%;flex:none;
  display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:800;
  background:var(--line);color:var(--muted)}
.getting-started li.done .gs-check{background:var(--good);color:#fff}
.getting-started li.done span.lab{color:var(--muted);text-decoration:line-through}

/* R11/R12/R13 — the FIELD WIZARD (Phase 3): one section per screen, thumb-
   reachable big tap targets, no dense desktop-style multi-column forms.
   Reuses .card/.btn/.note/.msg/.wiz-wrap etc. everywhere it can; this block
   is only the wizard-specific pieces (progress dots, tap-choice buttons,
   the yes/no toggle pair, per-room measurement cards) — see app.js's
   renderWizard()/wizQuestionHtml()/wizMeasureHtml(). */
.wiz-wrap{max-width:520px;margin:0 auto}
.wiz-progress{display:flex;gap:5px;margin:10px 0 4px}
.wiz-dot{flex:1;height:5px;border-radius:3px;background:var(--line2)}
.wiz-dot.on{background:var(--goldb)}
.wiz-dot.cur{background:var(--gold2)}
.wiz-steplabel{font-size:12px;color:var(--muted);margin-bottom:10px;font-weight:700;
  text-transform:uppercase;letter-spacing:.03em}
.wiz-card{padding:18px 16px}
.wiz-q{font-size:14px;font-weight:700;margin:14px 0 8px}
.wiz-card>.wiz-q:first-child{margin-top:0}
/* Tap, don't type (R12): a grid of big buttons for a bool toggle or an
   either/or / multi-option choice — never a <select> or free-text field
   for a question the intake bank already knows has a closed answer set. */
.wiz-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin:6px 0}
.wiz-toggle{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin:6px 0}
.wiz-choice{font:inherit;font-size:14px;font-weight:700;padding:14px 10px;min-height:48px;
  border:1.5px solid var(--line2);border-radius:10px;background:var(--card);color:var(--ink);
  cursor:pointer;text-align:center;line-height:1.25}
.wiz-choice:active{transform:translateY(1px)}
.wiz-choice.sel{border-color:var(--goldb);background:var(--goldb);color:#20160a}
.wiz-catblock{padding:10px 0;border-top:1px solid var(--line)}
.wiz-catblock:first-child{border-top:none;padding-top:0}
.wiz-cathead{font-size:15px;font-weight:800;color:var(--gold);margin-bottom:6px;
  display:flex;justify-content:space-between;align-items:center;gap:8px}
.wiz-room{padding:10px 0;border-top:1px solid var(--line)}
.wiz-room:first-child{border-top:none}
.wiz-room-head{display:flex;justify-content:space-between;align-items:baseline;gap:8px;font-size:13.5px}
.wiz-room-photo{margin-top:8px;padding:10px;border:1px dashed var(--line2);border-radius:10px;
  background:var(--panel2);text-align:center}
.wiz-nav{display:flex;justify-content:space-between;gap:10px;margin-top:16px;
  position:sticky;bottom:0;padding:10px 0;background:var(--paper)}
.wiz-nav .btn{width:auto;flex:1;margin-top:0}
.link-btn{background:none;border:none;color:var(--gold);text-decoration:underline;
  font:inherit;font-size:12px;cursor:pointer;padding:0}
@media(max-width:390px){
  .wiz-grid,.wiz-toggle{grid-template-columns:1fr 1fr}
  .wiz-choice{font-size:13px;padding:12px 8px}
}
.getting-started a.link{margin-left:auto;flex:none}
