/* the platform — stylesheet. Rebuilt 18 Sep 2026.
   PART 1  the v8 design system, VERBATIM, from the approved preview at
           work.noumansadiq.com/gcp-dashboard-preview/. Not one selector
           is rewritten - the markup matches it instead.
   PART 2  the existing app CSS, :root removed so it inherits v8's tokens.
   PART 3  compatibility. See the note there. */

/* ============ PART 1 - v8 design system (verbatim) ============ */

/* ONE palette. 3 Sep: there were two :root blocks — this one (the old warm
   cream skin) and a second one further down that overrides it. --blue, --green
   and --yellow were each declared TWICE at different hex values, so "the blue"
   depended on which block won the cascade. The live values all live in the
   second block now; only --violet ever survived from here, and it has moved
   there too. Do not reintroduce a second :root. */
:root{
  --cream:#FBF6EA; --cream-2:#F4ECD9; --ink:#1B1710; --ink-soft:#4B4438;
}
*{box-sizing:border-box; margin:0; padding:0;}
html,body{overflow-x:hidden; max-width:100%;}
body{font-family:'Manrope',sans-serif; background:var(--cream-2); color:var(--ink); line-height:1.55; padding:30px 16px 70px;}
h1,h2,h3{font-family:'Bricolage Grotesque',sans-serif; font-weight:800; letter-spacing:-0.02em;}
.wrap{max-width:980px; margin:0 auto;}
.note-banner{background:rgba(255,90,56,.08); border:2px dashed var(--coral); border-radius:16px; padding:14px 18px; font-size:12.5px; color:var(--ink-soft); margin-bottom:22px;}
.note-banner b{color:var(--coral);}
.roletoggle{display:flex; gap:8px; margin-bottom:16px; flex-wrap:wrap;}
.roletoggle button{font-family:'Manrope',sans-serif; font-weight:800; font-size:13px; padding:10px 18px; border:2.5px solid var(--ink); border-radius:99px; background:var(--cream); cursor:pointer;}
.roletoggle button.active{background:var(--ink); color:var(--cream);}
.shell{background:var(--cream); border:3px solid var(--ink); border-radius:24px; padding:24px; box-shadow:6px 6px 0 var(--ink);}
.top-bar{display:flex; justify-content:space-between; align-items:center; margin-bottom:18px; flex-wrap:wrap; gap:10px;}
.logo{font-size:16px; font-weight:800;}
.who{font-size:12px; font-weight:700; color:var(--ink-soft); background:var(--cream-2); border:2px solid var(--ink); border-radius:99px; padding:5px 12px;}
.navbar{display:flex; gap:6px; flex-wrap:wrap; margin-bottom:24px; padding-bottom:18px; border-bottom:2px solid rgba(27,23,16,.1);}
.navbar button{font-family:'Manrope',sans-serif; font-size:11.5px; font-weight:800; padding:8px 14px; border:2px solid var(--ink); border-radius:99px; background:var(--cream-2); cursor:pointer; color:var(--ink);}
.navbar button.on{background:var(--coral); color:var(--ink); border-color:var(--coral);}
.navbar button.locked{opacity:.35; cursor:not-allowed;}
/* Grouped nav (20 Aug redesign, matches the real system).
   Rules that keep it calm for someone in here 3-4h/day:
   - only ONE menu open at a time (enforced in buildNav's toggle handler)
   - nothing opens on page load — highlight shows where you are, click shows more
   - click anywhere else closes it
   - everything eases in/out; nothing snaps */
.navbar{align-items:flex-start; position:relative;}
.navbar button, .navgroup summary{transition:background .18s ease, color .18s ease, border-color .18s ease, transform .12s ease, box-shadow .18s ease;}
.navbar > button:hover, .navgroup summary:hover{transform:translateY(-1px); box-shadow:0 3px 0 rgba(27,23,16,.14);}
.navgroup{position:relative;}
.navgroup summary{list-style:none; cursor:pointer; font-family:'Manrope',sans-serif; font-size:11.5px; font-weight:800; padding:8px 15px; border:2px solid var(--ink); border-radius:99px; background:var(--cream-2); user-select:none; letter-spacing:.02em; display:inline-flex; align-items:center; gap:5px;}
.navgroup summary::-webkit-details-marker{display:none;}
.navgroup summary::after{content:"▾"; font-size:8px; opacity:.55; transition:transform .18s ease;}
.navgroup[open] > summary::after{transform:rotate(180deg);}
.navgroup.ongroup > summary{background:var(--coral); color:var(--ink); border-color:var(--coral);}
.navgroup[open] > summary{background:var(--ink); color:var(--cream-2); border-color:var(--ink);}
.navmenu{position:absolute; top:calc(100% + 8px); left:0; background:#fff; border:2px solid var(--ink); border-radius:16px; padding:7px; display:flex; flex-direction:column; gap:2px; min-width:172px; z-index:40; box-shadow:0 10px 28px rgba(27,23,16,.16), 0 2px 0 rgba(27,23,16,.08); animation:menuIn .16s ease both; transform-origin:top left;}
@keyframes menuIn{from{opacity:0; transform:translateY(-5px) scale(.98);} to{opacity:1; transform:translateY(0) scale(1);}}
.navmenu button{text-align:left; border-radius:10px !important; border-color:transparent !important; background:transparent !important; color:var(--ink) !important; width:100%; transition:background .14s ease, padding-left .14s ease;}
.navmenu button:hover{background:var(--cream-2) !important; padding-left:18px;}
.navmenu button.on{background:var(--coral) !important; color:#fff !important;}
.navmenu button{display:flex; align-items:center; justify-content:space-between; gap:10px;}
.navcount{display:inline-flex; align-items:center; justify-content:center; min-width:19px; height:19px; padding:0 6px; background:var(--coral); color:var(--ink); border-radius:99px; font-size:10.5px; font-weight:800; line-height:1;}
.navgroup summary .navcount{margin-left:2px;}
.navgroup[open] > summary .navcount{background:#fff; color:var(--ink);}
.navmenu button.on .navcount{background:#fff; color:var(--ink);}
@media(max-width:640px){
  .navmenu{position:static; box-shadow:none; margin-top:6px; min-width:0; animation:menuInMobile .18s ease both;}
  @keyframes menuInMobile{from{opacity:0; transform:translateY(-4px);} to{opacity:1; transform:translateY(0);}}
}
.back{display:inline-block; font-size:12px; font-weight:800; margin-bottom:14px; cursor:pointer; color:var(--coral);}
.greet{font-size:12.5px; font-weight:700; color:var(--coral); text-transform:uppercase; letter-spacing:.05em; margin-bottom:4px;}
h1.dt{font-size:23px; margin-bottom:18px;}
.money{display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:18px;}
.money.four{grid-template-columns:repeat(4,1fr);}
.card{border:2.5px solid var(--ink); border-radius:16px; padding:14px 16px; background:var(--cream-2); position:relative;}
.card .l{font-size:11px; font-weight:700; color:var(--ink-soft); text-transform:uppercase; letter-spacing:.04em; margin-bottom:6px;}
.card .v{font-size:19px; font-weight:800;}
.card.click{cursor:pointer; transition:transform .12s ease, box-shadow .12s ease, border-color .12s ease;}
.card.click:hover{transform:translateY(-1px); box-shadow:4px 4px 0 rgba(27,23,16,.08);}
.card.blurred .v{filter:blur(6px); user-select:none;}
.notif{border:2.5px solid var(--yellow); background:#fffaf0; border-radius:14px; padding:12px 14px; margin-bottom:8px; cursor:pointer; transition:transform .12s ease, box-shadow .12s ease;}
.notif:hover{transform:translateY(-1px); box-shadow:3px 3px 0 rgba(27,23,16,.08);}
/* A card that holds its own decision buttons is NOT itself clickable — it
   must not offer a pointer cursor, and it must not lift on hover, or a
   mis-tap becomes an approval. */
.notif.static{cursor:default;}
.notif.static:hover{transform:none; box-shadow:none;}
.card .hint{font-size:10px; font-weight:700; color:var(--ink-soft); margin-top:4px;}
.card.profit .v{color:var(--green-ink);}
.sec-title{font-size:13px; font-weight:800; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-soft); margin:28px 0 12px; padding-top:18px; border-top:2px solid rgba(27,23,16,.08);}
.sec-title:first-of-type{padding-top:0; border-top:none; margin-top:20px;}
.summary-grid{display:grid; grid-template-columns:repeat(4, minmax(0,1fr)); gap:12px; margin:6px 0 18px;}
.summary-grid .card{padding:12px 14px;}
.summary-grid .card .v{font-size:16px;}
.attn-block{border:2.5px solid var(--coral); border-radius:20px; padding:18px; background:rgba(255,90,56,.05); margin-bottom:26px;}
.attn-head{display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:12px;}
.attn-title{font-size:13px; font-weight:800; text-transform:uppercase; letter-spacing:.05em; color:var(--coral);}
.sortbox{display:flex; align-items:center; gap:8px; font-size:11px; font-weight:800; color:var(--ink-soft);}
.sortbox select{padding:7px 10px; border:2px solid var(--ink); border-radius:10px; background:var(--cream); font-family:'Manrope',sans-serif; font-weight:800; font-size:11px;}
.attn-empty{font-size:12.5px; font-weight:700; color:var(--green-ink);}
.notif{border:2.5px solid var(--yellow); background:#fffaf0; border-radius:14px; padding:12px 14px; margin-bottom:8px;}
.notif.orange{border-color:var(--coral); background:rgba(255,90,56,.06);}
.notif.green{border-color:var(--green); background:rgba(18,166,107,.06);}
.notif.blue{border-color:var(--blue); background:rgba(47,91,255,.06);}
.notif.yellow{border-color:var(--yellow); background:#fffaf0;}
.notif .l{font-size:11px; font-weight:800; color:var(--ink-soft); text-transform:uppercase; margin-bottom:3px;}
.notif .v{font-size:13.5px; font-weight:700;}
.pill-btn{display:inline-block; font-size:11px; font-weight:800; padding:7px 13px; border:2px solid var(--ink); border-radius:99px; background:var(--cream); margin-top:6px; margin-right:6px; cursor:pointer;}
.pill-btn.solid{background:var(--coral); color:var(--ink); border-color:var(--coral);}
.pill-btn.green{background:var(--green); color:var(--ink); border-color:var(--green);}
.pill-btn.blue{background:var(--blue); color:#fff; border-color:var(--blue);}
.pill-btn.ghost{background:transparent;}
.segtabs{display:flex; gap:6px; flex-wrap:wrap; margin-bottom:16px;}
.segtabs button{font-family:'Manrope',sans-serif; font-size:11.5px; font-weight:800; padding:8px 14px; border:2px solid var(--ink); border-radius:10px; background:var(--cream-2); cursor:pointer;}
.segtabs button.on{background:var(--ink); color:var(--cream);}
.tablewrap{width:100%; overflow-x:auto; border-radius:14px; margin-bottom:10px;}
/* -webkit-overflow-scrolling:touch REMOVED 21 Aug 2026 — prime suspect for the
   iOS-only "infinite footer" blank space (documented Safari bug where legacy
   momentum-scroll containers inflate the page height; deprecated since iOS 13,
   momentum scrolling is default now — removing costs nothing). */
table{width:100%; min-width:460px; border-collapse:collapse; border:2.5px solid var(--ink); border-radius:14px; font-size:12.5px; margin-bottom:0;}
th{background:var(--ink); color:var(--cream); text-align:left; padding:9px 12px; font-size:10.5px; text-transform:uppercase; letter-spacing:.04em;}
td{padding:9px 12px; border-top:1.5px solid rgba(27,23,16,.12); font-weight:600;}
tr.link{cursor:pointer;}
tr.link:hover td{background:rgba(255,90,56,.05);}
.status{display:inline-block; font-size:10px; font-weight:800; padding:3px 9px; border-radius:99px; background:var(--cream-2); border:1.5px solid var(--ink); white-space:nowrap;}
.status.needsattn{background:var(--coral); color:var(--ink); border-color:var(--coral);}
.status.waiting{background:var(--yellow); color:var(--ink); border-color:var(--yellow);}
.status.approved,.status.won,.status.paid,.status.matched{background:var(--green); color:var(--ink); border-color:var(--green);}
.status.declined,.status.lost{background:var(--ink-soft); color:#fff; border-color:var(--ink-soft);}
.status.progress{background:var(--blue); color:#fff; border-color:var(--blue);}
.kv{border:2.5px solid var(--ink); border-radius:16px; padding:14px 18px; background:var(--cream-2); margin-bottom:16px;}
.kv .row{display:flex; justify-content:space-between; padding:7px 0; border-bottom:1.5px solid rgba(27,23,16,.1); font-size:13px; gap:12px;}
.kv .row:last-child{border-bottom:none;}
.kv .row > span:first-child{color:var(--ink-soft); font-weight:700; flex-shrink:0;}
.kv .row > span:last-child{font-weight:800; text-align:right;}
.field{margin-bottom:12px;}
.field label{display:block; font-size:11.5px; font-weight:800; color:var(--ink-soft); margin-bottom:4px;}
.field input,.field select,.field textarea{width:100%; padding:9px 11px; border:2px solid var(--ink); border-radius:10px; font-size:13px; font-family:'Manrope',sans-serif; background:var(--cream);}
.field textarea{resize:vertical; min-height:60px;}
.formcard{border:2.5px solid var(--ink); border-radius:16px; padding:16px; background:var(--cream-2); max-width:440px;}
.subrow{display:flex; gap:8px; align-items:center; margin-bottom:8px; font-size:12.5px;}
.subrow .nm{flex:1; font-weight:700;}
.subrow input{width:70px; padding:6px 8px; border:2px solid var(--ink); border-radius:8px; font-size:12px;}
.empty{font-size:12.5px; color:var(--ink-soft); font-weight:700; padding:10px 0;}
.legend{display:flex; gap:16px; flex-wrap:wrap; margin-top:24px; font-size:11.5px; color:var(--ink-soft); font-weight:700;}
.legend span{display:inline-flex; align-items:center; gap:6px;}
.dot{width:10px; height:10px; border-radius:50%; border:1.5px solid var(--ink);}
footer{text-align:center; padding:26px 0 10px; font-size:12px; color:var(--ink-soft);}
.searchbar{display:flex; flex-wrap:wrap; gap:8px; margin-bottom:16px;}
.searchbar select{padding:9px 10px; border:2px solid var(--ink); border-radius:10px; font-size:12.5px; font-family:'Manrope',sans-serif; background:var(--cream-2); font-weight:700; flex-shrink:0;}
.searchbar input{flex:1 1 160px; min-width:0; padding:9px 12px; border:2px solid var(--ink); border-radius:10px; font-size:13px; font-family:'Manrope',sans-serif;}
.searchbar .pill-btn{margin-top:0; flex-shrink:0;}
.attach{display:flex; align-items:center; gap:10px; border:2px solid var(--ink); border-radius:14px; padding:9px 12px; margin-bottom:6px; font-size:12px; font-weight:700;}
.attach .tag{font-size:9.5px; font-weight:800; text-transform:uppercase; background:var(--violet); color:#fff; padding:2px 8px; border-radius:99px;}
.attach .ico{width:26px; height:26px; border-radius:8px; border:2px solid var(--ink); display:flex; align-items:center; justify-content:center; font-size:12px; flex-shrink:0; background:var(--cream-2);}
.lockednote{font-size:11.5px; color:var(--ink-soft); font-weight:700; font-style:italic;}
.notesbox{border:2px solid var(--ink); border-radius:14px; overflow:hidden; margin-bottom:10px;}
.note{padding:11px 14px; border-top:1.5px solid rgba(27,23,16,.12); font-size:12.5px;}
.note:first-child{border-top:none;}
.note .meta{font-weight:800; color:var(--ink-soft); font-size:10.5px; text-transform:uppercase; margin-bottom:3px; display:flex; justify-content:space-between; gap:8px;}
.note .to{background:var(--violet); color:#fff; padding:2px 8px; border-radius:99px; font-size:9.5px;}
.noteform{display:flex; gap:8px; flex-wrap:wrap; margin-top:8px;}
.noteform textarea{flex:1; min-width:200px; padding:9px 11px; border:2px solid var(--ink); border-radius:10px; font-size:12.5px; font-family:'Manrope',sans-serif; min-height:44px;}
.noteform select{padding:9px; border:2px solid var(--ink); border-radius:10px; font-size:12px; font-family:'Manrope',sans-serif; background:var(--cream);}
/* ---- COMPLETION FUNNEL & WORKFLOW ---- */
.funnel-container{margin:20px 0; background:var(--cream-2); border:2px solid var(--ink); border-radius:14px; padding:16px; overflow-x:auto;}
.funnel-row{display:flex; gap:8px; margin-bottom:12px; align-items:center;}
.funnel-step{flex:1; min-width:140px; background:var(--cream); border:2.5px solid var(--ink); border-radius:10px; padding:12px; text-align:center; transition:all .12s ease;}
.funnel-step.active{background:var(--coral); color:var(--ink); border-color:var(--coral);}
.funnel-step.completed{background:var(--green); color:var(--ink); border-color:var(--green);}
.funnel-step.pending{background:var(--yellow); border-color:var(--yellow);}
.funnel-step.skipped{opacity:.5; border-style:dashed;}
.funnel-step .step-label{font-size:10px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; margin-bottom:4px; opacity:.8;}
.funnel-step .step-title{font-size:12px; font-weight:800; margin-bottom:2px;}
.funnel-step .step-detail{font-size:10px; font-weight:700; opacity:.85; line-height:1.3;}
.funnel-arrow{width:24px; height:2px; background:var(--ink); margin-top:30px;}
.funnel-footer{font-size:10.5px; color:var(--ink-soft); margin-top:12px; padding-top:8px; border-top:1px solid rgba(27,23,16,.1);}

/* ---- MOBILE ---- */
@media (max-width:640px){
  body{padding:16px 10px 20px;}
  footer{padding:16px 0 4px;}
  .shell{padding:16px; border-radius:18px;}
  .money{grid-template-columns:repeat(2,1fr); gap:8px;}
  .money.four{grid-template-columns:repeat(2,1fr);}
  .summary-grid{grid-template-columns:repeat(2,minmax(0,1fr));}
  .card{padding:11px 12px;}
  .card .v{font-size:16px;}
  .searchbar select{flex:1 1 100%;}
  .formcard{max-width:100%;}
  h1.dt{font-size:19px;}
}
@media (max-width:380px){
  .money, .money.four, .summary-grid{grid-template-columns:1fr;}
}


/* ============================================================
   SKIN v7 — the first client's chosen direction (21 Aug reference image):
   black app bar, white cards on light gray, royal blue actions,
   coral kept for the brand + "needs you" alerts, icon-tile nav.
   Built as an override layer: structure and behaviour untouched.
   ============================================================ */
:root{
  --cream:#FFFFFF;            /* card surfaces */
  --cream-2:#F1F3F6;          /* page background / soft fills */
  --ink:#0B0B0D;
  --ink-soft:#5A6069;
  --blue:#2563EB;
  --coral:#FF5A38;
  --green:#16A34A;
  --green-ink:#137A38;      /* green as TEXT: #16A34A is 3.3:1 on white */
  /* --orange was used 11 times and DEFINED NOWHERE. An undefined var makes the
     whole declaration invalid, so "Past due", the waiting states and several
     borders silently fell back to inherited colour. It is the warning hue. */
  --orange:#F59E0B;
  --orange-ink:#8A5A06;     /* amber as TEXT: #F59E0B is 2.15:1 on white */
  --yellow:#F59E0B;
  --violet:#7A4DFF;           /* re-declared here — see note below */
  --line:#E4E7EC;
  --shadow:0 1px 2px rgba(16,24,40,.05), 0 4px 16px rgba(16,24,40,.06);
}
body{background:var(--cream-2); padding:22px 14px 70px;}
.shell{background:transparent; border:none; border-radius:0; padding:0; box-shadow:none;}

/* ---- black app bar ---- */
.top-bar{background:var(--ink); border-radius:20px; padding:16px 18px; margin-bottom:16px; box-shadow:var(--shadow);}
.top-bar .logo{color:#fff; font-family:'Bricolage Grotesque',sans-serif; font-size:20px; line-height:1.1;}
.top-bar .logo b{color:var(--coral);}
.top-bar .logo small{display:block; font-size:9.5px; letter-spacing:.14em; font-weight:700; color:rgba(255,255,255,.75); font-family:'Manrope',sans-serif;}
#navToggle{width:42px; height:42px; border-radius:50%; border:2px solid rgba(255,255,255,.35); background:transparent; color:#fff; cursor:pointer; font-size:16px; display:flex; align-items:center; justify-content:center; transition:transform .2s ease, background .2s ease;}
#navToggle:hover{background:rgba(255,255,255,.12); transform:scale(1.05);}
/* The gear sits beside the menu button, top right, and is styled to match
   it exactly so neither looks bolted on. 42px square clears the 44px touch
   guidance once its 2px border is counted. */
.topbtns{display:flex; align-items:center; gap:9px;}
.gearbtn{width:42px; height:42px; border-radius:50%; border:2px solid rgba(255,255,255,.35);
  background:transparent; color:#fff; cursor:pointer; display:flex; align-items:center;
  justify-content:center; transition:transform .2s ease, background .2s ease;}
.gearbtn:hover{background:rgba(255,255,255,.12); transform:rotate(35deg);}
.gearbtn svg{display:block; pointer-events:none;}
.gearbtn[hidden]{display:none;}
.who{background:#fff; border:1.5px solid var(--line); color:var(--ink); box-shadow:var(--shadow); margin-bottom:4px;}

/* ---- generic surfaces ---- */
.card,.formcard,.notif,.attn-block,.notesbox,.kv{background:var(--cream); border:1.5px solid var(--line); box-shadow:var(--shadow); border-radius:18px;}
.tablewrap{border:1.5px solid var(--line); border-radius:16px; box-shadow:var(--shadow); background:#fff;}
table{border:none;}
th{background:var(--ink); color:#fff;}
.note-banner{background:#fff; border:2px dashed var(--coral); box-shadow:var(--shadow);}
.lockednote{border-radius:14px;}

/* ---- buttons: primary actions go BLUE; coral = attention/brand ---- */
.pill-btn{border:1.5px solid var(--line); background:#fff; box-shadow:var(--shadow); border-radius:14px; transition:transform .15s ease, box-shadow .2s ease, background .2s ease;}
.pill-btn:hover{transform:translateY(-1px); box-shadow:0 6px 18px rgba(16,24,40,.10);}
.pill-btn:active{transform:scale(.97);}
.pill-btn.solid{background:var(--blue) !important; border-color:var(--blue) !important; color:#fff !important;}
.pill-btn.blue{background:var(--blue) !important; border-color:var(--blue) !important; color:#fff !important;}
.pill-btn.green{background:var(--green) !important; border-color:var(--green) !important; color:var(--ink) !important;}
.searchbar button{background:var(--blue); border-color:var(--blue);}
.roletoggle button{background:#fff; border:1.5px solid var(--line); box-shadow:var(--shadow); transition:transform .15s ease;}
.roletoggle button:active{transform:scale(.97);}
.roletoggle button.active{background:var(--ink); border-color:var(--ink); color:#fff;}
input,select,textarea{border-color:var(--line) !important; background:#fff; border-radius:14px !important; transition:border-color .2s ease, box-shadow .2s ease;}
input:focus,select:focus,textarea:focus{outline:none; border-color:var(--blue) !important; box-shadow:0 0 0 3px rgba(37,99,235,.15);}

/* ---- filter chips with counts (reference style) ---- */
.segtabs{gap:8px;}
.segtabs button{border:1.5px solid var(--line); background:#fff; border-radius:14px; padding:9px 14px; box-shadow:var(--shadow); transition:transform .15s ease, border-color .2s ease, background .2s ease; display:inline-flex; align-items:center; gap:7px;}
.segtabs button:active{transform:scale(.96);}
.segtabs button.on{border:2px solid var(--blue); color:var(--blue); background:#fff;}
.segtabs button .chipn{display:inline-flex; align-items:center; justify-content:center; min-width:20px; height:20px; padding:0 6px; border-radius:99px; background:var(--cream-2); font-size:11px; font-weight:800;}
.segtabs button.on .chipn{background:var(--blue); color:#fff;}

/* ---- summary stat cards: hero card is blue ---- */
.summary-grid .card{transition:transform .18s ease, box-shadow .2s ease;}
.summary-grid .card:hover{transform:translateY(-2px);}
/* The emphasised card is CORAL, not blue. The app prints its own colour legend
   at the foot of every screen — "Coral = needs attention now" — and then the
   first thing a person saw each morning was an attention count in blue, which
   is the action/link colour everywhere else (Search, Start pricing, Submit).
   The screen contradicted the legend. Coral = attention, blue = the thing you
   click. 3 Sep. */
.summary-grid .card:first-child{background:rgba(255,90,56,.08); border:2px solid var(--coral);}
/* No coral TEXT here: #FF5A38 measures 2.56:1 on this surface and cannot pass AA
   on any light background. The tint plus the 2px coral border does the work, and
   the text stays ink. (The decorative "Good morning" greeting elsewhere is coral
   on cream and has the same problem — flagged for Boss, not changed here.) */
/* White on coral measures 3.10:1 — it fails AA for the label and the hint, and
   only scrapes large-text AA for the number. This is the SAME treatment the app
   already uses for "Needs your attention" (.attn-block): coral tint, coral
   border, ink text. Reusing it rather than inventing a third attention style. */

/* ---- TILE NAV (icon grid launcher, the reference's signature) ---- */
/* The navbar is a plain block; .navrow is what lays the tiles out in a grid.
   3 Sep: the navbar used to BE the tile grid, and buildNav wraps every set of
   tiles in a .navrow — so each row became one 96px cell of the outer grid and
   the tiles stacked into a single column. Grouped roles AND flat roles were
   both wrong. One place owns the columns now: .navrow. */
/* One touch-target rule for the whole app. There were six scattered
   @media(hover:none) blocks each patching one component, and everything nobody
   remembered to patch stayed at 31–42px: pill buttons on four screens, the
   search input, the scope select. A phone is the primary device here. */
@media (hover:none){
  button, .pill-btn, input, select, textarea, .segtabs button, .sortbox select,
  .w9btn, .sectab, .crumb, .assignsel{ min-height:44px; }
  button, .pill-btn, .sectab{ display:inline-flex; align-items:center; justify-content:center; }
  textarea{ min-height:66px; }
}
.navbar{display:block; border-bottom:none; padding-bottom:6px; margin-bottom:20px;}
.navbar.navhidden{display:none;}
/* One-screen estimate: section tabs, anchors, and the bar that stays put. */
.sectabs{display:flex; gap:6px; flex-wrap:wrap; margin:12px 0 4px;}
.sectab{font-size:12px; font-weight:800; padding:7px 12px; border-radius:99px; border:1.5px solid var(--line); background:#fff; cursor:pointer;}
.sectab:hover{border-color:var(--ink);}
.sec-anchor{scroll-margin-top:8px;}
.scope-in{width:100%; border:none; border-bottom:2px solid var(--ink); background:transparent; font:inherit; font-weight:800; text-align:right; outline:none;}
.actionbar{position:fixed; left:0; right:0; bottom:0; z-index:40; display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:10px 16px; background:var(--ink); color:var(--cream); box-shadow:0 -4px 16px rgba(0,0,0,.18);}
.ab-total .k{display:block; font-size:10px; font-weight:800; text-transform:uppercase; letter-spacing:.06em; opacity:.7;}
.ab-total .v{font-size:18px; font-weight:800;}
.ab-btns{display:flex; gap:8px; flex-wrap:wrap; justify-content:flex-end;}
.ab-btns .pill-btn{background:#fff; color:var(--ink); border-color:#fff;}
.ab-btns .pill-btn.solid{background:var(--coral); color:var(--ink); border-color:var(--coral);}
.ab-btns .pill-btn.green{background:var(--green); color:var(--ink); border-color:var(--green);}
.ab-btns .pill-btn.blue{background:var(--blue); color:#fff; border-color:var(--blue);}
.actionbar-spacer{height:74px;}
@media (hover:none){ .actionbar{padding:12px 14px;} .ab-btns .pill-btn{min-height:44px; display:inline-flex; align-items:center;} .sectab{min-height:40px; display:inline-flex; align-items:center;} }
/* Grouped nav */
/* It is a <button> now, so reset the browser chrome and opt out of the tile
   hover-lift that .navbar > button otherwise applies to it. */
/* Must be .navbar button.navgroup, not .navgroup: `.navbar button` (line 34)
   carries a pill border and beats a bare class on specificity, so the plain
   text headers rendered as bordered pills — a look they never had. */
.navbar button.navgroup{display:flex; align-items:center; gap:8px; width:100%; text-align:left;
  background:none; border:none; border-radius:0; box-shadow:none;
  font-family:'Manrope',sans-serif; font-size:11px; font-weight:800;
  text-transform:uppercase; letter-spacing:.07em; color:var(--ink-soft);
  padding:10px 4px 6px; cursor:pointer; user-select:none;}
.navbar > button.navgroup:hover{transform:none; box-shadow:none; color:var(--ink);}
.navgroup:focus-visible{outline:2px solid var(--blue); outline-offset:2px; border-radius:8px;}
.navgroup .chev{transition:transform .18s ease;}
.navgroup .chev{margin-left:auto; font-size:12px;}
.navgroup.open{color:var(--ink);}
.navrow{display:grid; grid-template-columns:repeat(auto-fill,minmax(108px,1fr)); gap:10px; margin-bottom:6px;}
.navrow .tile{margin:0;}
@media(max-width:640px){ .navrow{grid-template-columns:repeat(3,1fr); gap:8px;} .navgroup{min-height:44px; padding:8px 4px;} }
/* reference strip + price picker inside costing */
.refstrip{display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin:0 0 12px;}
.refstrip .k{font-size:10.5px; font-weight:800; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-soft);}
.refchip{font-size:12px; font-weight:700; background:#fff; border:1.5px solid var(--line); border-radius:99px; padding:5px 10px;}
.picker{background:#fff; border:2px solid var(--ink); border-radius:14px; padding:10px 12px; margin:-8px 0 16px; max-width:560px;}
.picker .k{font-size:10.5px; font-weight:800; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-soft); margin-bottom:6px;}
.pickrow{display:flex; justify-content:space-between; align-items:center; padding:8px 6px; border-top:1px solid var(--line); cursor:pointer; font-size:13px; font-weight:700;}
.pickrow:first-of-type{border-top:none;}
.pickrow:hover{background:var(--cream-2);}
.pickrow small{font-weight:600; color:var(--ink-soft);}
@media (hover:none){ .pickrow{min-height:44px;} .navgroup{min-height:40px;} }
/* Explanations are OFF by default. The seven that prevent a money misread are
   marked .keep and always show. The rest appear when the ? is on — there for
   whoever wants them, invisible to whoever just wants to work. 34 boxes of
   prose is what made a simple tool feel complicated. */
.lockednote:not(.keep){display:none;}
body.showhelp .lockednote:not(.keep){display:block;}
.helpbtn{margin-left:auto; width:30px; height:30px; border-radius:50%; border:2px solid var(--ink); background:#fff;
  color:var(--ink); font-weight:800; font-size:14px; cursor:pointer; display:inline-flex; align-items:center; justify-content:center; flex:0 0 auto;}
.helpbtn.on{background:var(--ink); color:#fff;}
@media (hover:none){ .helpbtn{width:44px; height:44px;} }
.crumbs{display:flex; align-items:center; flex-wrap:wrap; gap:4px; font-size:12.5px; font-weight:800;
  margin:2px 0 14px; color:var(--ink-soft);}
.crumb{cursor:pointer; padding:6px 8px; border-radius:8px; transition:background .12s ease;}
.crumb:hover{background:rgba(27,23,16,.06); color:var(--ink);}
.crumb.cur{cursor:default; color:var(--ink);}
.crumb.cur:hover{background:transparent;}
.crumb-sep{color:var(--ink-soft); opacity:.6; padding:0 2px;}
@media (hover:none){ .crumb{padding:10px 10px; min-height:40px; display:inline-flex; align-items:center;} }
.navbar button.tile{position:relative; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px; background:#fff; border:1.5px solid var(--line); border-radius:18px; padding:14px 6px 12px; min-height:92px; cursor:pointer; box-shadow:var(--shadow); font-family:'Manrope',sans-serif; font-size:11px; font-weight:800; color:var(--ink); transition:transform .16s ease, box-shadow .2s ease, background .2s ease, border-color .2s ease; animation:tileIn .35s ease backwards;}
.navbar button.tile svg{width:22px; height:22px; stroke:var(--ink); fill:none; stroke-width:1.9; stroke-linecap:round; stroke-linejoin:round; transition:stroke .2s ease;}
.navbar button.tile:hover{transform:translateY(-3px); box-shadow:0 8px 22px rgba(16,24,40,.12);}
.navbar button.tile:active{transform:scale(.94);}
/* THE CORAL RULE, 3 Sep. #FF5A38 is a FILL and a BORDER. It is never text, and
   text on it is never white. Measured: white on coral 3.10:1, coral on white
   3.10:1, ink on coral 6.34:1. The tile label is 11px, so it needs 4.5:1 — the
   white version failed, and darkening the tile instead would have put a second
   coral millimetres from the wordmark and the count badges, which is the exact
   colour drift this pass removed. One coral; the text changes, not the hue. */
.navbar button.tile.on{background:var(--coral); border-color:var(--coral); color:var(--ink);}
.navbar button.tile.on svg{stroke:var(--ink);}
.navbar button.tile.locked{opacity:.32; cursor:not-allowed;}
.navbar button.tile .navcount{position:absolute; top:-6px; right:-6px; box-shadow:0 2px 6px rgba(16,24,40,.25); animation:badgePop .35s cubic-bezier(.34,1.56,.64,1) .22s backwards;}
.navbar button.tile.on .navcount{background:#fff; color:var(--ink);}
@keyframes tileIn{from{opacity:0; transform:translateY(10px) scale(.95);} to{opacity:1; transform:translateY(0) scale(1);}}
@keyframes badgePop{from{opacity:0; transform:scale(.3);} to{opacity:1; transform:scale(1);}}
.navbar .tile:nth-child(1){animation-delay:.02s} .navbar .tile:nth-child(2){animation-delay:.05s}
.navbar .tile:nth-child(3){animation-delay:.08s} .navbar .tile:nth-child(4){animation-delay:.11s}
.navbar .tile:nth-child(5){animation-delay:.14s} .navbar .tile:nth-child(6){animation-delay:.17s}
.navbar .tile:nth-child(7){animation-delay:.20s} .navbar .tile:nth-child(8){animation-delay:.23s}
.navbar .tile:nth-child(9){animation-delay:.26s} .navbar .tile:nth-child(10){animation-delay:.29s}
.navbar .tile:nth-child(11){animation-delay:.32s} .navbar .tile:nth-child(12){animation-delay:.35s}
.navbar .tile:nth-child(13){animation-delay:.38s} .navbar .tile:nth-child(14){animation-delay:.41s}
/* (the phone column count lives on .navrow now — see the rule near .navgroup) */

/* ---- page transition ---- */
#pageBody.pagein{animation:pageIn .28s ease;}
/* Enough height that ANY screen can be scrolled up to sit under the tiles.
   Without this, a short screen (Reports, Banking) physically cannot reach the
   top of the window — there is nothing below it to scroll against — so tapping
   its tile left you still looking at the navigation. This is the other half of
   scrollToContent(); the JS asks for the scroll, this is what makes the scroll
   possible. */
#pageBody{min-height:calc(100vh - 120px);}
@keyframes pageIn{from{opacity:0; transform:translateY(10px);} to{opacity:1; transform:translateY(0);}}

/* ---- statuses keep their meaning, restyled softer ---- */
.status{border:none; background:var(--cream-2);}

/* ---- iOS "infinite footer" hardening (21 Aug) ----
   overflow:hidden makes body a scrollable box on iOS, which can reserve
   phantom scroll area below the content. overflow:clip clips WITHOUT
   creating a scrollable box — supported iOS 16+; older Safari keeps the
   hidden fallback from the base styles. Height explicitly left to content. */
@supports (overflow: clip){
  html, body{overflow-x: clip;}
}
html, body{height: auto; min-height: 0;}

/* Respect users who turn animations off at the OS level. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation:none !important; transition:none !important;}
}


/* ===== v8 additions: role-based platform + estimator module ===== */
.rolebar{display:flex; align-items:center; gap:10px; margin-bottom:14px; flex-wrap:wrap;}
.role-lab{font-size:11px; font-weight:800; letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink-soft); flex:0 0 auto;}
.role-select{flex:1 1 220px; min-width:0; min-height:46px; font-family:'Manrope',sans-serif;
  font-weight:800; font-size:14px; color:var(--ink); background:#fff;
  border:1.5px solid var(--line); border-radius:14px; box-shadow:var(--shadow);
  padding:11px 40px 11px 14px; cursor:pointer; appearance:none; -webkit-appearance:none;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'><path d='M1 1l6 6 6-6' fill='none' stroke='%231B1710' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat:no-repeat; background-position:right 14px center;}
.role-select:focus-visible{outline:2px solid var(--ink); outline-offset:2px;}
.stepbar{display:flex; gap:0; align-items:stretch; margin:14px 0 18px; flex-wrap:wrap; border:1.5px solid var(--line); border-radius:16px; overflow:hidden; background:#fff; box-shadow:var(--shadow);}
.stepbar .stp{flex:1 1 120px; padding:11px 12px; font-size:11px; font-weight:800; color:var(--ink-soft); border-right:1.5px solid var(--line); display:flex; align-items:center; gap:7px;}
.stepbar .stp:last-child{border-right:none;}
.stepbar .stp .n{width:20px; height:20px; border-radius:50%; background:var(--cream-2); display:inline-flex; align-items:center; justify-content:center; font-size:10px;}
.stepbar .stp.done{color:var(--green);} .stepbar .stp.done .n{background:var(--green); color:var(--ink);}
.stepbar .stp.now{color:#fff; background:var(--blue);} .stepbar .stp.now .n{background:rgba(255,255,255,.28); color:#fff;}
.lineitem{background:#fff; border:1.5px solid var(--line); border-radius:16px; padding:13px 14px; margin-bottom:10px; box-shadow:var(--shadow); animation:tileIn .3s ease backwards;}
.lineitem .li-top{display:flex; justify-content:space-between; gap:10px; align-items:flex-start; margin-bottom:9px;}
.lineitem .li-desc{font-weight:800; font-size:13.5px; line-height:1.35;}
.lineitem .li-tot{font-weight:800; font-size:14px; white-space:nowrap;}
.li-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(88px,1fr)); gap:8px;}
.li-cell{background:var(--cream-2); border-radius:10px; padding:7px 9px;}
.li-cell .k{font-size:9.5px; font-weight:800; text-transform:uppercase; color:var(--ink-soft); letter-spacing:.03em;}
.li-cell .v{font-size:12.5px; font-weight:800; margin-top:1px;}
/* An INPUT cell is white with a dark border — it looks like something you type
   into. A RESULT cell keeps the grey tile — it looks like something the system
   worked out. The difference has to be visible without reading. */
.li-cell.in{background:#fff; border:2px solid var(--ink);}
.li-cell.out{opacity:.92;}
.in-wrap{display:flex; align-items:center; gap:3px; margin-top:2px;}
.in-wrap input{width:100%; min-width:0; border:none; outline:none; background:transparent;
  font:inherit; font-size:13.5px; font-weight:800; padding:2px 0;}
.in-wrap .unit{font-size:11px; font-weight:800; color:var(--ink-soft); flex:0 0 auto;}
.li-desc-in{flex:1; min-width:0; border:none; border-bottom:2px solid var(--ink); background:transparent;
  font:inherit; font-weight:800; font-size:13.5px; padding:2px 0; outline:none;}
.li-del{flex:0 0 auto; width:28px; height:28px; border-radius:50%; border:2px solid var(--line);
  display:flex; align-items:center; justify-content:center; cursor:pointer; font-size:16px;
  color:var(--ink-soft); margin-left:6px;}
.li-del:hover{border-color:var(--coral); color:var(--coral);}
.pricing-grid{grid-template-columns:repeat(auto-fit,minmax(110px,1fr));}
.preset-row{display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin-top:12px;}
.preset-lbl{font-size:11px; font-weight:800; color:var(--ink-soft); text-transform:uppercase; letter-spacing:.04em;}
.preset-btn{font-size:11.5px; padding:6px 11px;}
.preset-btn.on{background:var(--ink); color:var(--cream); border-color:var(--ink);}
.qp-details summary::-webkit-details-marker{display:none;}
.qp-details summary::before{content:'▸ '; font-size:11px;}
.qp-details[open] summary::before{content:'▾ ';}
@media (hover:none){ .in-wrap input{min-height:40px; font-size:15px;} .li-del{width:44px; height:44px;} }
.totrow{display:flex; justify-content:space-between; padding:9px 2px; font-size:13px; border-bottom:1px solid var(--line);}
.totrow:last-child{border-bottom:none;}
.totrow.grand{font-size:16px; font-weight:900; border-top:2px solid var(--ink); border-bottom:none; padding-top:12px; margin-top:4px;}
.totrow .lbl{color:var(--ink-soft); font-weight:700;}
.totrow .amt{font-weight:800;}
.pricecard{display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:10px; margin:12px 0;}
.pricecard .pc{background:#fff; border:1.5px solid var(--line); border-radius:16px; padding:13px; box-shadow:var(--shadow);}
.pricecard .pc.rec{background:var(--blue); border-color:var(--blue); color:#fff;}
.pricecard .pc.strong{background:var(--ink); border-color:var(--ink); color:#fff;}
.pricecard .pc .k{font-size:10px; font-weight:800; text-transform:uppercase; opacity:.75;}
.pricecard .pc .v{font-size:19px; font-weight:900; margin-top:3px;}
.doc{background:#fff; border:1.5px solid var(--line); border-radius:18px; padding:20px 18px; box-shadow:var(--shadow); font-size:13px; line-height:1.65;}
.doc h2{font-size:16px; margin:16px 0 7px;}
.doc h2:first-child{margin-top:0;}
.doc .docmeta{color:var(--ink-soft); font-size:12.5px;}
.doc ul{margin:6px 0 6px 18px;} .doc li{margin-bottom:4px;}
.doc .bigprice{font-size:19px; font-weight:900; background:var(--cream-2); border-radius:14px; padding:11px 14px; margin:14px 0;}
.rolenote{background:#EEF4FF; border:1.5px solid #C7DAFF; color:#1E3A8A; border-radius:14px; padding:11px 13px; font-size:12.5px; font-weight:600; margin-bottom:14px;}
/* Job file code — the thing someone reads off this screen and types into a
   Telegram caption. Sized to be legible on a phone held in one hand on a site. */
.codebox{display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
  background:#fff; border:2px solid var(--ink); border-radius:14px; padding:14px 16px; margin-bottom:10px; box-shadow:var(--shadow);}
.codelab{font-size:10.5px; font-weight:800; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-soft);}
.codeval{font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:26px; font-weight:800; letter-spacing:.05em; margin:3px 0 6px;}
.codehelp{font-size:11.5px; color:var(--ink-soft); font-weight:700; max-width:46ch;}
/* On a touch device the shared .pill-btn is 33px tall, which is under the 44px
   a thumb needs. Raised HERE rather than on .pill-btn itself — that style is
   used across every screen the first client has already approved. */
@media (hover:none){
  .codeval{font-size:22px;}
  .codebox .pill-btn{width:100%; text-align:center; min-height:44px; line-height:28px;}
}
/* The door to the intake, on the Jobs page. */
.newjob-cta{display:flex; align-items:center; gap:13px; cursor:pointer; background:#fff;
  border:2.5px solid var(--coral); border-radius:14px; padding:14px 16px; margin-bottom:16px;
  box-shadow:var(--shadow); transition:transform .12s ease;}
.newjob-cta:active{transform:scale(.99);}
.newjob-cta strong{display:block; font-size:14px; font-weight:800;}
.newjob-cta small{display:block; font-size:11.5px; color:var(--ink-soft); margin-top:2px;}
.newjob-plus{flex:0 0 auto; width:38px; height:38px; border-radius:50%; background:var(--coral);
  color:#fff; font-size:22px; font-weight:800; display:flex; align-items:center; justify-content:center;}
/* The four steps from a phone call to a job. */
.chainbox{display:flex; align-items:stretch; gap:8px; flex-wrap:wrap; margin-bottom:16px;}
.chainstep{flex:1 1 130px; display:flex; gap:9px; align-items:flex-start; background:#fff;
  border:1.5px solid var(--line); border-radius:14px; padding:11px 12px; box-shadow:var(--shadow);}
.chainstep.done{border-color:var(--green); border-width:2px;}
.chainstep b{flex:0 0 auto; width:22px; height:22px; border-radius:50%; background:var(--ink);
  color:#fff; font-size:11.5px; display:flex; align-items:center; justify-content:center;}
.chainstep span{font-size:12.5px; font-weight:800; line-height:1.35;}
.chainstep small{font-weight:600; color:var(--ink-soft); font-size:11px;}
.chainarrow{align-self:center; color:var(--ink-soft); font-weight:800;}
@media (max-width:620px){ .chainarrow{display:none;} .chainstep{flex:1 1 100%;} }
.assignsel{padding:6px 8px; border:2px solid var(--ink); border-radius:8px; font:inherit; font-weight:700; font-size:12.5px; background:#fff; cursor:pointer;}
.rate-eg{font-size:13px; font-weight:800; color:var(--green-ink); margin:-4px 0 10px; background:#f2f9f4; border:1.5px solid #cfe8d6; border-radius:10px; padding:8px 11px;}
.catrow{display:flex; justify-content:space-between; gap:10px; padding:11px 13px; background:#fff; border:1.5px solid var(--line); border-radius:14px; margin-bottom:8px; box-shadow:var(--shadow); cursor:pointer; transition:transform .15s ease;}
.catrow:active{transform:scale(.99);}
/* A row that is a reference line or a setting readout, not a record you can
   open. It keeps the card look so the page still reads as one family, and drops
   every affordance that promises a tap: no pointer, no press, no hover lift.
   3 Sep — 20-odd rows looked identical to openable ones and did nothing. */
.catrow.static{cursor:default; background:var(--cream-2); box-shadow:none; border-style:dashed;}
.catrow.static:active{transform:none;}
.catrow.static:hover{border-color:var(--line);}
.catrow .nm{font-weight:800; font-size:13px;}
.catrow .sub{font-size:11.5px; color:var(--ink-soft); margin-top:2px;}
.catrow .pr{text-align:right; white-space:nowrap;}
.catrow .pr .y{font-weight:900; font-size:13.5px;} .catrow .pr .s{font-size:11px; color:var(--ink-soft);}
/* ADDED 1 Sep: the permission grid needs the full column width. .formcard is
   capped at 440px, which is right for the small "add someone" form and wrong
   for sixteen tick boxes — it was rendering as two columns in a narrow strip.
   A separate class, so the existing form keeps the width the first client approved. */
.permcard{max-width:100% !important;}
.permgrid{display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:8px;}
.permtile{display:flex; gap:9px; align-items:center; min-height:50px; padding:9px 11px;
  border-radius:14px; background:var(--cream-2); border:1.5px solid var(--line);}
.permtile.on{background:var(--blue); border-color:var(--blue); color:#fff;}
.permtile.lock{opacity:.55;}
.permtile:not(.lock){cursor:pointer;}

/* ── What's next: the plan screen. 10 Sep 2026. ──────────────────────────
   Built for a low-attention reader on a phone: one line of text per item, a
   price on the right, a tick box on the left, and a total that moves. No
   paragraphs. Nothing that has to be read twice. */
.plan-have{border:2.5px solid var(--ink); border-radius:16px; overflow:hidden; margin:0 0 14px;}
.ph-row{display:flex; align-items:center; gap:12px; padding:13px 15px; background:var(--cream);
  border-bottom:2px solid rgba(27,23,16,.10);}
.ph-row:last-child{border-bottom:0;}
.ph-tick{flex:0 0 auto; width:24px; height:24px; border-radius:50%; background:var(--green,#137A38);
  color:#fff; display:flex; align-items:center; justify-content:center; font-weight:900; font-size:13px;}
.ph-row b{font-size:14px;}
.ph-sub{font-size:12px; color:var(--ink-soft); line-height:1.4; margin-top:2px;}
.ph-amt{margin-left:auto; flex:0 0 auto; font-weight:900; font-size:13px; color:var(--ink-soft); white-space:nowrap;}
.ph-amt.due{color:var(--coral); background:rgba(255,90,56,.12); border:2px solid var(--coral);
  border-radius:99px; padding:5px 11px;}

.plan-bulk{display:flex; gap:8px; margin:0 0 14px;}
.plan-bulk button{font-family:'Manrope',sans-serif; font-weight:800; font-size:12px; padding:12px 18px;
  border:2.5px solid var(--ink); border-radius:99px; background:var(--cream); cursor:pointer; min-height:44px;}

.plan-stage{border:2.5px solid var(--ink); border-radius:18px; overflow:hidden; margin:0 0 14px; background:var(--cream);}
.plan-stage.off{opacity:.55;}
.ps-head{display:flex; align-items:flex-start; gap:12px; padding:14px 16px; background:var(--cream-2);
  border-bottom:2.5px solid var(--ink);}
.ps-n{font-size:10.5px; font-weight:900; letter-spacing:.14em; text-transform:uppercase; color:var(--ink-soft);}
.ps-t{font-family:'Bricolage Grotesque',sans-serif; font-weight:800; font-size:16px; line-height:1.15; margin-top:2px;}
.ps-d{font-size:12px; color:var(--ink-soft); margin-top:3px; line-height:1.4;}
.ps-amt{margin-left:auto; font-family:'Bricolage Grotesque',sans-serif; font-weight:800; font-size:18px; white-space:nowrap;}

.plan-item{display:flex; align-items:flex-start; gap:12px; padding:13px 15px; cursor:pointer;
  border-bottom:2px solid rgba(27,23,16,.08); min-height:56px; transition:background .12s;}
.plan-item:last-child{border-bottom:0;}
.plan-item:active{transform:scale(.995);}
.plan-item .pi-box{flex:0 0 auto; width:26px; height:26px; border:2.5px solid var(--ink); border-radius:8px;
  display:flex; align-items:center; justify-content:center; font-weight:900; font-size:14px; background:#fff; margin-top:1px;}
.plan-item.on .pi-box{background:var(--ink); color:var(--cream);}
.plan-item.on{background:rgba(19,122,56,.05);}
.pi-mid{flex:1 1 auto; min-width:0;}
.pi-n{font-weight:800; font-size:14px; line-height:1.25;}
.pi-d{font-size:12px; color:var(--ink-soft); line-height:1.42; margin-top:3px;}
.pi-who{font-size:10.5px; color:var(--ink-soft); opacity:.75; margin-top:4px; font-weight:700;}
.pi-amt{flex:0 0 auto; font-family:'Bricolage Grotesque',sans-serif; font-weight:800; font-size:15px;
  white-space:nowrap; margin-top:1px;}
.plan-item:not(.on) .pi-amt, .plan-item:not(.on) .pi-n{opacity:.45;}

.plan-foot{position:sticky; bottom:10px; z-index:5; border:3px solid var(--ink); border-radius:18px;
  background:var(--yellow,#FFD84D); padding:14px 16px; margin:16px 0 12px;
  box-shadow:0 6px 0 rgba(27,23,16,.18);}
.pf-line{display:flex; align-items:baseline; justify-content:space-between; gap:14px; font-weight:800; font-size:15px;}
.pf-line b{font-family:'Bricolage Grotesque',sans-serif; font-size:20px; white-space:nowrap;}
.pf-line.sm{font-size:12.5px; font-weight:700; color:var(--ink-soft); margin-top:6px;}
.pf-line.sm b{font-size:14px; color:var(--ink);}

.plan-cta{display:grid; gap:9px; margin:0 0 12px;}
.plan-cta a{display:block; text-align:center; text-decoration:none; font-weight:900; font-size:14px;
  padding:15px 16px; border:2.5px solid var(--ink); border-radius:99px; min-height:52px;}
.pc-go{background:var(--ink); color:var(--cream);}
.pc-ask{background:var(--cream); color:var(--ink);}
.plan-fine{font-size:11.5px; color:var(--ink-soft); line-height:1.5; padding:0 2px 6px;}

@media(max-width:520px){
  .ps-amt{font-size:16px;}
  .pi-d{font-size:11.5px;}
  .pf-line b{font-size:18px;}
}


/* 10 Sep — three controls sat at 40–42px, just under the 44px minimum. They
   pre-date the role dropdown; fixed while the file was open. */
.searchbar select, .searchbar input, .pill-btn{min-height:44px;}
.navmenu, .gearbtn{min-height:44px; min-width:44px;}


/* ============ PART 2 - existing app components ============ */

  
  *{box-sizing:border-box;}
  body{font-family:system-ui,-apple-system,sans-serif; background:var(--cream); color:var(--ink); margin:0;}
  a{color:inherit;}
  .topbar{display:flex; align-items:center; justify-content:space-between; padding:14px 18px; border-bottom:var(--border); background:var(--white); position:sticky; top:0; z-index:5; flex-wrap:wrap; gap:10px;}
  .topbar .brand{font-weight:900; font-size:18px;}
  .topbar .searchform{display:flex; gap:6px; order:3; width:100%;}
  .topbar .searchform select{padding:7px; border:2px solid var(--ink); border-radius:8px; font-size:11.5px; font-weight:700;}
  .topbar .searchform input{flex:1; min-width:100px; padding:7px 10px; border:2px solid var(--ink); border-radius:8px; font-size:12.5px;}
  .topbar nav{display:flex; gap:6px; flex-wrap:wrap; align-items:center;}
  .topbar nav a{font-size:12px; font-weight:800; text-transform:uppercase; padding:8px 12px; border-radius:99px; border:2px solid transparent; text-decoration:none;}
  .topbar nav a.active{border-color:var(--ink); background:var(--cream);}
  /* Grouped nav (20 Aug redesign, polish pass 21 Aug): Home + 3 groups.
     Rules that keep it calm for 8h/day use: only one menu open at a time and
     click-outside closes it (tiny script at the end of this file — menus still
     work without it, just less tidy); nothing opens on page load; everything
     eases, nothing snaps. */
  .topbar nav a, .navgroup summary{transition:background .18s ease, color .18s ease, border-color .18s ease, transform .12s ease, box-shadow .18s ease;}
  .topbar nav > a:hover, .navgroup summary:hover{transform:translateY(-1px); box-shadow:0 3px 0 rgba(27,23,16,.12);}
  .navgroup{position:relative;}
  .navgroup summary{list-style:none; cursor:pointer; font-size:12px; font-weight:800; text-transform:uppercase; padding:8px 13px; border-radius:99px; border:2px solid transparent; user-select:none; letter-spacing:.02em; display:inline-flex; align-items:center; gap:5px;}
  .navgroup summary::-webkit-details-marker{display:none;}
  .navgroup summary::after{content:"▾"; font-size:8px; opacity:.55; transition:transform .18s ease;}
  .navgroup[open] > summary::after{transform:rotate(180deg);}
  .navgroup.on > summary{border-color:var(--ink); background:var(--cream);}
  .navgroup[open] > summary{border-color:var(--ink); background:var(--ink); color:var(--cream);}
  .navgroup .menu{position:absolute; top:calc(100% + 8px); left:0; background:var(--white); border:var(--border); border-radius:16px; padding:7px; display:flex; flex-direction:column; gap:2px; min-width:176px; z-index:30; box-shadow:0 10px 28px rgba(27,23,16,.16), 0 2px 0 rgba(27,23,16,.08); animation:menuIn .16s ease both; transform-origin:top left;}
  @keyframes menuIn{from{opacity:0; transform:translateY(-5px) scale(.98);} to{opacity:1; transform:translateY(0) scale(1);}}
  .navgroup .menu a{border-radius:10px; padding:9px 12px; white-space:nowrap; transition:background .14s ease, padding-left .14s ease; display:flex; align-items:center; justify-content:space-between; gap:10px;}
  .navgroup .menu a:hover{background:var(--cream); padding-left:16px;}
  .navgroup .menu a.active{background:var(--cream); border-color:var(--ink);}
  .navbadge{display:inline-block; min-width:17px; text-align:center; background:var(--orange); color:#fff; border-radius:99px; font-size:10px; padding:1px 5px; margin-left:4px;}
  /* The gear (1 Sep 2026). margin-left:auto pushes it to the far right of the
     nav row on a wide screen — Boss asked for top right — while still being a
     normal flex item, so on a phone it wraps into the row instead of
     overflowing off the edge. The word is hidden on desktop where the icon is
     unambiguous, and shown on mobile where a lone gear is a guessing game. */
  .topbar nav a.geartab{margin-left:auto; display:inline-flex; align-items:center; gap:7px; border-color:var(--ink);}
  .topbar nav a.geartab svg{display:block;}
  .topbar nav a.geartab:hover{background:var(--ink); color:var(--cream);}
  .topbar nav a.geartab.active{background:var(--ink); color:var(--cream); border-color:var(--ink);}
  .gearword{display:none;}
  /* ---- TOUCH TARGETS, EVERYWHERE (1 Sep 2026) --------------------------
     Boss: "it should be mobile first and mobile friendly." This is the shared
     rule rather than a per-page fix, so a screen built next month inherits it.

     The query is deliberately `hover: none` OR a narrow width, not width
     alone: a 768px tablet is a touch device and was getting desktop-sized
     30px targets under a width-only rule. `hover: none` catches any device
     driven by a finger whatever its size.

     44px is the floor. It was chosen because these people are on job sites,
     often with gloves on, and a 30px row between two other 30px rows is a
     coin toss between "Jobs" and "Clients". */
  @media (hover: none), (max-width: 900px){
    .topbar nav a, .navgroup summary{min-height:44px; display:inline-flex; align-items:center;}
    .navgroup .menu a{min-height:46px;}
    .pill-btn{min-height:44px; display:inline-flex; align-items:center; justify-content:center;}
    .back{min-height:44px; display:inline-flex; align-items:center; font-size:13.5px;}
    .topbar .searchform select{min-height:44px; font-size:14px;}
    .topbar .searchform input{min-height:44px; font-size:16px;}  /* 16px stops iOS zooming on focus */
    tr.link-row td{padding-top:12px; padding-bottom:12px;}
    details.detail-toggle > summary{min-height:44px; display:inline-flex; align-items:center;}
    input[type=text], input[type=email], input[type=number], input[type=date],
    input[type=time], input[type=password], select, textarea{min-height:46px; font-size:16px;}
  }

  @media(max-width:760px){
    .topbar nav a.geartab{margin-left:0;}
    .gearword{display:inline;}
    /* Mobile-first pass, 1 Sep: every nav item is a 44px touch target on a
       phone. They were 30px, which on a job site with gloves on is a coin
       toss between "Jobs" and "Clients". */
    .topbar nav a, .navgroup summary{min-height:44px; display:inline-flex; align-items:center; padding:11px 14px;}
    .navgroup .menu a{min-height:46px;}

    /* The last three real offenders, found by measuring the EFFECTIVE target
       (an element, or its label if that is what the finger actually hits)
       rather than the element alone — the naive count was full of false
       positives from 24px checkboxes sitting inside 56px labels.
       16px on the input also stops iOS zooming the whole page on focus. */
    .topbar .searchform select{min-height:44px; font-size:14px;}
    .topbar .searchform input{min-height:44px; font-size:16px;}
    .back{min-height:44px; display:inline-flex; align-items:center; font-size:13.5px;}
  }
  .pill-btn{transition:background .18s ease, color .18s ease, transform .12s ease, box-shadow .18s ease;}
  .pill-btn:hover{transform:translateY(-1px); box-shadow:0 3px 0 rgba(27,23,16,.12);}
  a:focus-visible, button:focus-visible, summary:focus-visible{outline:3px solid var(--yellow); outline-offset:2px; border-radius:10px;}
  @media(max-width:640px){
    .navgroup .menu{position:static; box-shadow:none; border-width:1.5px; margin-top:6px; min-width:0; animation:menuInM .18s ease both;}
    @keyframes menuInM{from{opacity:0; transform:translateY(-4px);} to{opacity:1; transform:translateY(0);}}
  }
  main{padding:18px; max-width:1100px; margin:0 auto;}
  .greet{font-size:13px; color:var(--ink-soft); font-weight:700;}
  h1{font-size:24px; margin:4px 0 18px;}
  .money{display:flex; gap:12px; margin-bottom:22px; flex-wrap:wrap;}
  .card{background:var(--white); border:var(--border); border-radius:14px; padding:14px 18px; flex:1; min-width:150px;}
  .card .l{font-size:11px; font-weight:800; text-transform:uppercase; color:var(--ink-soft);}
  .card .v{font-size:20px; font-weight:800;}
  table{width:100%; border-collapse:collapse; background:var(--white); border:var(--border); border-radius:14px; overflow:hidden;}
  th,td{padding:10px 12px; text-align:left; font-size:13px; border-bottom:1px solid #eee;}
  th{background:var(--ink); color:var(--cream); font-size:11px; text-transform:uppercase;}
  tr:last-child td{border-bottom:none;}
  tr.link-row{cursor:pointer;}
  tr.link-row:hover{background:#faf4e5;}
  .status{display:inline-block; padding:3px 10px; border-radius:99px; font-size:10.5px; font-weight:800; border:1.5px solid var(--ink); white-space:nowrap;}
  .st-bid_needed,.st-quoted{background:#fff; color:var(--ink);}
  .st-approved{background:#fff; color:var(--ink);}
  .st-assigned,.st-in_progress{background:var(--yellow); color:var(--ink);}
  .st-completed,.st-invoiced,.st-paid{background:var(--green); color:#fff; border-color:var(--green);}
  .st-review_requested{background:var(--orange); color:#fff; border-color:var(--orange);}
  .badge-overdue{background:var(--orange); color:#fff; border-color:var(--orange);}
  .pill-btn{display:inline-block; padding:8px 14px; border:2px solid var(--ink); border-radius:10px; background:var(--white); font-weight:800; font-size:12px; text-decoration:none;}
  .section-title{font-size:15px; font-weight:900; margin:26px 0 10px; text-transform:uppercase; letter-spacing:.03em;}
  .empty{padding:24px; text-align:center; color:var(--ink-soft); font-size:13px;}
  .back{font-size:12px; font-weight:700; text-decoration:none; margin-bottom:12px; display:inline-block;}
  .kv{display:grid; grid-template-columns:140px 1fr; gap:6px 12px; font-size:13px; background:var(--white); border:var(--border); border-radius:14px; padding:16px;}
  .kv dt{font-weight:800; color:var(--ink-soft);}
  .kv dd{margin:0;}
  .notes-box{white-space:pre-wrap; background:#fffdf6; border:1.5px dashed var(--ink); border-radius:10px; padding:10px 12px; font-size:12.5px; margin-top:10px;}
  /* ---- THE LEDGER LOOK (1 Sep 2026) ----------------------------------
     Boss saw the money-flow walkthrough and said: "this is how I actually
     want their Google Sheets to look and to preview like... and if it has a
     lot of columns then it should be scrollable left and right... and this
     should only be available as an option to see everything, only when
     needed."

     So: the summary is always on screen, and the full column-by-column
     ledger sits behind a "Show every column" toggle. On a phone the ledger
     scrolls sideways INSIDE its own box rather than stretching the page —
     which is why .ledger deliberately opts OUT of the mobile card layout
     below. A ledger turned into stacked cards stops being a ledger. */
  .ledger-wrap{background:var(--white); border:var(--border); border-radius:14px; overflow:hidden; margin-top:10px;}
  .scrollx{overflow-x:auto; -webkit-overflow-scrolling:touch;}
  .scrollx table.ledger{min-width:640px; border:none; border-radius:0; margin:0;}
  table.ledger th{background:var(--ink); color:var(--cream); white-space:nowrap; font-size:10.5px; letter-spacing:.04em;}
  table.ledger td{font-size:12.5px; white-space:nowrap;}
  table.ledger td.num, table.ledger th.num{text-align:right; font-variant-numeric:tabular-nums;}
  table.ledger tr.dim td{color:var(--ink-soft); font-style:italic; background:#faf8f2;}
  table.ledger tr.total td{font-weight:900; border-top:2px solid var(--ink); background:#fffdf6;}
  .money-in{color:var(--green); font-weight:800;}
  .money-out{color:var(--orange); font-weight:800;}
  .scroll-hint{font-size:11px; color:var(--ink-soft); padding:6px 12px; border-top:1px solid #eee; background:#faf8f2;}
  details.detail-toggle > summary{cursor:pointer; font-size:12px; font-weight:800; text-transform:uppercase;
    letter-spacing:.03em; padding:9px 13px; border:2px solid var(--ink); border-radius:10px;
    background:var(--white); display:inline-block; list-style:none; user-select:none;}
  details.detail-toggle > summary::-webkit-details-marker{display:none;}
  details.detail-toggle > summary::after{content:" ▾"; opacity:.55;}
  details.detail-toggle[open] > summary::after{content:" ▴";}
  details.detail-toggle[open] > summary{background:var(--ink); color:var(--cream);}

  @media(max-width:640px){
    table, thead, tbody, th, td, tr{display:block;}
    thead{display:none;}
    /* 8 Oct 2026: most tables write their heading row as a bare <tr><th>,
       not inside <thead>, so the rule above never hid it and every heading
       stacked into a tower of black bars above the cards. Each card already
       carries its own labels (td::before), so the heading row goes. */
    table:not(.ledger) tr:has(> th){display:none;}
    tr{border-bottom:var(--border); padding:8px 0;}
    tr:last-child{border-bottom:none;}
    td{border:none; padding:4px 12px; display:flex; justify-content:space-between; gap:10px;}
    td::before{content:attr(data-label); font-weight:800; color:var(--ink-soft); font-size:10.5px; text-transform:uppercase;}

    /* The ledger keeps its real table shape and scrolls sideways instead.
       Everything above turns tables into stacked cards for phones, which is
       right for a list of jobs and wrong for a row of figures you are
       reading across. Stated as an explicit exception so nobody "fixes" it
       back later. */
    table.ledger, table.ledger thead, table.ledger tbody, table.ledger tr{display:revert;}
    table.ledger thead{display:table-header-group;}
    table.ledger tr{display:table-row; border-bottom:none; padding:0;}
    table.ledger th, table.ledger td{display:table-cell; padding:9px 12px; border-bottom:1px solid #eee;}
    table.ledger td::before{content:none;}
  }


/* ============ PART 3 - compatibility ============ */

/* ===================================================================
   COMPATIBILITY LAYER — rebuilt 18 Sep 2026

   🔴 WHY THIS IS NOW SHORT. The earlier version rewrote 19 of v8's own
   selectors from `button` to `:is(button,a)` and bolted on an anchor
   shim. That was needed only because the nav had been rendered with
   <a class="tile"> when v8 writes its rules against <button class="tile">.
   Deviating from the mockup's markup meant patching its CSS to match,
   and each patch pulled the look further from the picture the first client
   approved. The nav now emits v8's markup EXACTLY, so v8's stylesheet
   applies untouched and all of that is deleted.

   What is left is only what the old app needs to keep working.
   =================================================================== */
:root{
  --white:#fff;
  --border:1.5px solid var(--line);
  --muted:var(--ink-soft);
  --page:var(--cream-2);
}
body{ background:var(--page); padding:18px 14px 40px; }
main{ padding:0; max-width:none; margin:0; }
/* Two warm creams hard-coded from the retired palette. */
.notes-box{ background:var(--cream-2)!important; border:1.5px dashed var(--line)!important; border-radius:12px; }
.scroll-hint{ background:var(--cream-2)!important; }
table.ledger tr.dim td{ background:var(--cream-2)!important; }
table.ledger tr.total td{ background:var(--cream-2)!important; border-top:2px solid var(--ink)!important; }
.section-title{ color:var(--ink-soft); font-size:12px; letter-spacing:.08em; }
h1{ font-size:26px; letter-spacing:-.01em; }
/* The retired horizontal nav chrome. Hidden, not deleted, so nothing
   that still references it throws. */
.topbar > nav, .topbar .brand, .topbar .searchform{ display:none; }
.navbadge{ background:var(--coral); color:#fff; }
/* Account actions are not destinations, so they get no tile. */
.navfoot{ display:flex; align-items:center; gap:10px; padding:14px 2px 0;
  font-size:12px; font-weight:700; color:var(--ink-soft); }
.navfoot a{ color:var(--ink-soft); text-decoration:none; min-height:44px;
  display:inline-flex; align-items:center; }
.navfoot a:hover{ color:var(--ink); text-decoration:underline; }

/* ---- mobile tables: keep this app's card-per-row pattern --------------
   Verified at a real 375px viewport. v8 styles tables for a sideways
   scroll wrapper (table{min-width:460px}), which pushed the jobs list off
   the side of the phone and un-hid <thead>. .ledger is exempt on purpose:
   the money ledgers are deliberately wide inside .scrollx. */
@media (max-width: 640px){
  main table:not(.ledger){ min-width:0 !important; width:100% !important; }
  main table:not(.ledger) thead{ display:none !important; }
}

/* ---- money-card footnotes ------------------------------------------------
   Added 18 Sep 2026. A money card that shows $0.00 and nothing else is the
   most alarming thing this app can put in front of an owner: it reads as
   "your money is gone" when it usually means "nothing has been confirmed yet"
   or "this calendar month has not started billing." These two classes give a
   card room to say which, in a sentence, directly under the figure.
   .cardnote  neutral context.
   .cardwait  something is waiting on HER — amber, and it is a link. */
.card .cardnote{ font-size:11.5px; font-weight:600; line-height:1.5;
  color:var(--ink-soft); margin-top:7px; }
.card .cardwait{ display:inline-flex; align-items:center; gap:5px;
  font-size:11.5px; font-weight:800; line-height:1.5; margin-top:7px;
  /* --orange-ink, NOT --orange: this file already records that #F59E0B is
     2.15:1 on white and fails as text. The rule is only useful if it is
     followed by the next thing written. */
  color:var(--orange-ink); text-decoration:none;
  border-bottom:1.5px solid var(--orange); padding-bottom:1px; }
.card .cardwait:hover{ filter:brightness(.88); }
@media (max-width: 640px){
  .card .cardnote, .card .cardwait{ font-size:11px; }
}
