/* "Site Ops" palette - deep green header with a hi-vis amber accent,
   picked from three mocked-up directions. Bold condensed Archivo for
   headings/figures, Barlow for body text - built to be read at a glance
   from across a site office, not a generic dashboard default.
   ink      #24282D   charcoal, body text
   accent   #1F4A3D   deep green, primary interactive colour + masthead
   paper    #F2EFE9   warm concrete off-white
   rule     #E3DFD3
   hazard   #E88A1C   amber, at risk
   signal   #C0392B   overdue or breached
   go       #2E7D53   compliant / on track / paid
   chalk    #5B6470   secondary text, steel-grey
*/
:root{
  --ink:#24282D; --accent:#1F4A3D; --paper:#F2EFE9; --card:#FFFFFF; --rule:#E3DFD3;
  --hazard:#E88A1C; --signal:#C0392B; --go:#2E7D53; --chalk:#5B6470;
  --header-ink:#F1EEE8; --header-ink-muted:rgba(241,238,232,.72);
  --sans: "Barlow", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --display: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: "SFMono-Regular", ui-monospace, "Roboto Mono", Consolas, monospace;
  --gap:20px;
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0; background:var(--paper); color:var(--ink);
  font-family:var(--sans); font-size:15px; line-height:1.5;
  font-variant-numeric:tabular-nums;
}
.env-banner{
  position:sticky; top:0; z-index:200; text-align:center;
  padding:7px 12px; font-size:12.5px; font-weight:700; letter-spacing:.04em;
  text-transform:uppercase; background:var(--hazard); color:#3D2200;
}
h2{font-family:var(--display); font-weight:700; font-size:19px; letter-spacing:-.01em; margin:0 0 10px}
h3{font-family:var(--display); font-size:14px; font-weight:700; text-transform:uppercase; letter-spacing:.09em; color:var(--chalk);
   margin:40px 0 14px; padding-bottom:6px; border-bottom:1px solid var(--rule)}
.lede{max-width:min(100%, 80ch); color:var(--chalk); margin:0 0 28px}
em{font-style:normal; box-shadow:inset 0 -.45em 0 rgba(232,138,28,.30)}

/* masthead ---------------------------------------------------------------- */
.masthead{
  display:flex; flex-wrap:wrap; gap:var(--gap); align-items:flex-end;
  justify-content:space-between;
  padding:26px 32px 22px; background:var(--accent); color:var(--header-ink);
}
.masthead-brand{display:flex; align-items:center; gap:14px}
.masthead-logo{
  background:var(--paper); padding:6px 12px; border-radius:3px;
  display:flex; align-items:center;
}
.masthead-logo img{display:block; height:36px; width:auto}
.masthead-mark{display:flex; flex-direction:column; gap:2px}
.masthead-rule{width:44px; height:5px; background:var(--hazard); margin-bottom:8px}
.masthead-title{font-family:var(--display); font-size:20px; font-weight:700; letter-spacing:-.015em; color:var(--header-ink)}
.masthead-sub{font-size:12px; color:var(--header-ink-muted); letter-spacing:.02em}
.project-picker{display:flex; flex-direction:column; gap:5px; font-size:11px;
  text-transform:uppercase; letter-spacing:.11em; color:var(--header-ink-muted)}
.project-picker select{
  min-width:270px; padding:9px 11px; font:inherit; font-size:14px; letter-spacing:0;
  text-transform:none; color:var(--ink); background:var(--paper);
  border:0; border-radius:2px;
}
.masthead-right{display:flex; align-items:flex-end; gap:20px; flex-wrap:wrap}

/* Pending counts box: the Incoming/Dockets/Deleted badges used to sit on the
   flat nav, so grouping the tabs into dropdowns hid them behind a click.
   This keeps the same three numbers visible at all times, and each one is a
   shortcut into the view it counts. */
.pending-box{display:flex; flex-direction:column; gap:5px}
.pending-box[hidden]{display:none}
.pending-box-label{
  font-size:11px; text-transform:uppercase; letter-spacing:.11em;
  color:var(--header-ink-muted);
}
.pending-box-items{display:flex; gap:2px; background:rgba(0,0,0,.16); border-radius:2px; padding:2px}
.pending-item{
  appearance:none; border:0; cursor:pointer; font:inherit;
  display:flex; flex-direction:column; align-items:center; gap:1px;
  padding:5px 13px; min-width:62px; border-radius:2px;
  background:transparent; color:var(--header-ink);
}
.pending-item[hidden]{display:none}
.pending-item:hover{background:rgba(255,255,255,.12)}
.pending-item:focus-visible{outline:2px solid var(--hazard); outline-offset:-2px}
.pending-count{
  font-family:var(--display); font-size:17px; font-weight:700; line-height:1.1;
  font-variant-numeric:tabular-nums;
}
/* Zero is not news - only colour the number when there's something to act on. */
.pending-item[data-state="active"] .pending-count{color:var(--hazard)}
.pending-item[data-state="zero"] .pending-count{color:var(--header-ink-muted)}
.pending-name{
  font-size:10.5px; text-transform:uppercase; letter-spacing:.06em;
  color:var(--header-ink-muted);
}
.user-badge{display:flex; align-items:center; gap:10px; font-size:12.5px; color:var(--header-ink-muted)}
.btn--small{padding:6px 11px; font-size:12px}
.masthead-right .btn--small{border-color:var(--header-ink-muted); color:var(--header-ink)}
.masthead-right .btn--small:hover{background:var(--hazard); border-color:var(--hazard); color:#2A1B00}

/* login screen -------------------------------------------------------------- */
.login-screen{
  min-height:100vh; display:flex; align-items:center; justify-content:center;
  background:var(--ink); padding:24px;
}
.login-screen[hidden]{display:none}
.login-card{
  background:var(--card); border-radius:4px; padding:40px 36px 32px;
  width:100%; max-width:380px; text-align:center;
}
.login-logo{display:inline-flex; margin:0 auto 18px; padding:8px 14px}
.login-logo img{height:44px}
.login-card h2{margin:0 0 4px}
.login-card .lede{margin:0 0 22px; text-align:center; max-width:none}
.login-card .form{grid-template-columns:1fr}
.login-card .field--wide{grid-column:auto}
.login-card .actions{flex-direction:column; align-items:stretch}
.login-card .btn{width:100%}

/* tabs -------------------------------------------------------------------- */
/* No overflow-x here: setting it to anything but visible forces overflow-y to
   auto too, which clips the dropdown panels off at the bar's bottom edge.
   Grouping cut the top level from 18 items to 6, so wrapping is a better
   narrow-screen fallback than sideways scrolling anyway. */
.tabs{display:flex; flex-wrap:wrap; gap:2px; padding:0 32px; background:#F4C989}
.tab{
  appearance:none; border:0; cursor:pointer; white-space:nowrap;
  padding:11px 17px; font:inherit; font-family:var(--display); font-size:13px; font-weight:600;
  color:#3D2200; background:transparent; border-radius:3px 3px 0 0;
}
.tab:hover{background:rgba(61,34,0,.12); color:#3D2200}
.tab.is-current{background:var(--paper); color:var(--ink)}
.tab:focus-visible{outline:2px solid var(--ink); outline-offset:-2px}
.tab[draggable="true"]{cursor:grab}
.tab--dragging{opacity:.4; cursor:grabbing}
.tab--drag-over{box-shadow:inset 2px 0 0 var(--ink)}
.tab-badge{
  display:inline-block; margin-left:6px; padding:1px 6px; border-radius:9px;
  background:var(--signal); color:#fff; font-size:11px; font-weight:700; line-height:1.4;
}

/* grouped/dropdown tabs ----------------------------------------------------- */
.tab-group{position:relative}
.tab-group[hidden]{display:none}
.tab-group[draggable="true"]{cursor:grab}
.tab-group-trigger{
  appearance:none; border:0; cursor:pointer; white-space:nowrap;
  padding:11px 17px; font:inherit; font-family:var(--display); font-size:13px; font-weight:600;
  color:#3D2200; background:transparent; border-radius:3px 3px 0 0;
  display:inline-flex; align-items:center; gap:4px;
}
.tab-group-trigger:hover{background:rgba(61,34,0,.12); color:#3D2200}
.tab-group-trigger:focus-visible{outline:2px solid var(--ink); outline-offset:-2px}
.tab-group.has-current .tab-group-trigger,
.tab-group.is-open .tab-group-trigger{background:var(--paper); color:var(--ink)}
.tab-caret{font-size:9px; opacity:.75}
.tab-dropdown{
  display:none; flex-direction:column; position:absolute; top:100%; left:0; min-width:190px;
  background:var(--paper); border:1px solid var(--rule); border-radius:0 0 3px 3px;
  box-shadow:0 8px 20px rgba(0,0,0,.14); padding:4px 0; z-index:20;
}
.tab-group.is-open .tab-dropdown{display:flex}
.tab-dropdown .tab{border-radius:0; text-align:left; padding:10px 17px}
.tab-dropdown .tab.is-current{background:rgba(61,34,0,.1)}

/* alert banner ------------------------------------------------------------- */
.alert-banner{
  margin:0; padding:12px 24px; background:#FBEAD3; border-bottom:1px solid var(--hazard);
  font-size:13.5px; color:#5C3A00; display:flex; align-items:center; gap:12px; flex-wrap:wrap;
}
.alert-banner[hidden]{display:none}
.alert-banner strong{color:var(--signal)}
.alert-banner button{
  color:var(--ink); font-weight:600; text-decoration:none; cursor:pointer;
  background:#FFFFFF; border:1px solid var(--hazard); border-radius:3px; font:inherit; font-size:13.5px;
  padding:8px 14px; white-space:nowrap; flex-shrink:0;
  min-height:44px; min-width:44px; display:inline-flex; align-items:center; justify-content:center;
}
.alert-banner button:hover{background:#FCF1E1}
.load-error-banner{
  margin:0; padding:12px 24px; background:#F8E2DD; border-bottom:1px solid var(--signal);
  font-size:13.5px; color:#5C1410; display:flex; align-items:center; gap:12px; flex-wrap:wrap;
}
.load-error-banner[hidden]{display:none}
.load-error-banner button{
  color:var(--ink); font-weight:600; text-decoration:none; cursor:pointer;
  background:#FFFFFF; border:1px solid var(--signal); border-radius:3px; font:inherit; font-size:13.5px;
  padding:8px 14px; white-space:nowrap; flex-shrink:0;
  min-height:44px; min-width:44px; display:inline-flex; align-items:center; justify-content:center;
}
.load-error-banner button:hover{background:#F8E2DD}
.alert-status{
  background:var(--card); border:1px solid var(--rule); border-radius:3px;
  padding:16px 18px; font-size:13.5px; max-width:560px; margin-bottom:14px;
}
.alert-status p{margin:0 0 6px}
.alert-status .k{color:var(--chalk)}

main{padding:40px 32px 32px}
.view{display:none}
.view.is-current{display:block}

/* summary strip ----------------------------------------------------------- */
.summary{display:grid; gap:1px; background:var(--rule); border:1px solid var(--rule);
  grid-template-columns:repeat(auto-fit,minmax(155px,1fr)); margin-bottom:26px}
.summary[hidden]{display:none}
.report-controls{display:flex; gap:24px; flex-wrap:wrap; margin-bottom:6px}
.report-controls label{display:flex; flex-direction:column; gap:5px; font-size:12.5px; font-weight:600; color:var(--ink)}
.report-controls select, .report-controls input[type="text"]{padding:8px 10px; font:inherit; font-size:13px; border:1px solid var(--rule); border-radius:2px; min-width:260px}
#reportsView h3{margin-top:30px}
#reportsView h3 .k{font-weight:400; color:var(--chalk); font-size:13px}
#reportMadeTable tfoot td, #reportReceivedTable tfoot td{font-weight:700; border-top:2px solid var(--ink)}
.stat{background:var(--card); padding:13px 15px}
.stat-label{font-size:10px; text-transform:uppercase; letter-spacing:.11em; color:var(--chalk)}
.stat-value{font-family:var(--display); font-size:22px; font-weight:700; margin-top:3px; letter-spacing:-.01em}
.stat--alert .stat-value{color:var(--signal)}
.stat--warn  .stat-value{color:#8A5A10}

/* claim cards ------------------------------------------------------------- */
.claims{display:flex; flex-direction:column; gap:14px}
.claim{
  background:var(--card); border:1px solid var(--rule); border-left:5px solid var(--rule);
  padding:16px 18px;
}
.claim[data-state="Overdue"], .claim[data-state="Breached"]{border-left-color:var(--signal)}
.claim[data-state="At risk"]{border-left-color:var(--hazard)}
.claim[data-state="On track"], .claim[data-state="Compliant"]{border-left-color:var(--go)}

.claim-head{display:flex; flex-wrap:wrap; gap:12px; align-items:baseline;
  justify-content:space-between}
.claim-no{font-family:var(--display); font-size:16px; font-weight:700}
.claim-no small{font-family:var(--sans); font-weight:400; color:var(--chalk); margin-left:9px; font-size:13px}
.claim-amount{font-family:var(--display); font-size:18px; font-weight:700}
.claim-amount small{display:block; text-align:right; font-size:11px; font-weight:400;
  color:var(--chalk); letter-spacing:.05em; text-transform:uppercase}

.badge{display:inline-block; padding:2px 8px; border-radius:2px; font-size:11px;
  font-weight:650; letter-spacing:.05em; text-transform:uppercase}
.badge--go{background:#E1EFE7; color:var(--go)}
.badge--warn{background:#FBEAD3; color:#8A5A10}
.badge--alert{background:#F5DAD4; color:var(--signal)}
.badge--flat{background:#EBE7DD; color:var(--chalk)}

/* the signature element: one tick per business day left on the s76 clock ---- */
.clock{margin:14px 0 4px}
.clock-label{font-size:11px; text-transform:uppercase; letter-spacing:.1em;
  color:var(--chalk); margin-bottom:6px}
.clock-ticks{display:flex; gap:3px; align-items:flex-end; height:20px}
.tick{flex:0 0 12px; height:10px; background:#E2DED3}
.tick.is-left{height:20px; background:var(--go)}
.clock[data-state="At risk"] .tick.is-left{background:var(--hazard)}
.clock[data-state="Overdue"] .tick.is-left,
.clock[data-state="Breached"] .tick.is-left{background:var(--signal)}
.clock-caption{font-size:12.5px; color:var(--chalk); margin-top:8px; max-width:min(100%, 78ch)}

.meta{display:grid; gap:2px 26px; grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
  margin-top:14px; padding-top:13px; border-top:1px solid var(--rule); font-size:13px}
.meta div{display:flex; justify-content:space-between; gap:12px; padding:3px 0}
.meta dt, .meta .k{color:var(--chalk)}
.meta .v{font-weight:550; font-variant-numeric:tabular-nums}
.meta .v--alert{color:var(--signal)}

.claim-actions{display:flex; flex-wrap:wrap; gap:8px; margin-top:14px}

.schedule-reasons{
  margin-top:14px; padding:12px 14px; background:var(--paper); border-radius:3px; font-size:13px;
}
.schedule-reasons strong{display:block; color:var(--ink); margin-bottom:4px}
.schedule-reasons p{margin:0}
.schedule-reasons--shortfall{background:#F5DAD4}
.schedule-reasons--shortfall strong{color:var(--signal)}
.schedule-pdf-block:not(:empty){margin-top:14px; padding-top:14px; border-top:1px solid var(--rule)}

/* modal ---------------------------------------------------------------- */
.modal-overlay{
  position:fixed; inset:0; background:rgba(36,40,45,.55); z-index:100;
  display:flex; align-items:center; justify-content:center; padding:20px;
}
.modal{
  background:var(--card); border-radius:4px; padding:26px 28px; width:100%;
  max-width:560px; max-height:90vh; overflow-y:auto;
}
.modal--wide{max-width:860px}
.modal h3{margin:0 0 18px}
.modal .field{margin-bottom:14px}
.modal-subject{margin:4px 0 0; font-weight:600; font-size:14px}
.modal-iframe{
  width:100%; height:320px; border:1px solid var(--rule); border-radius:3px;
  margin-top:4px; background:#fff;
}
.modal .actions{margin-top:16px}
.incoming-attach-block{margin-top:20px; padding-top:16px; border-top:1px solid var(--rule)}
.incoming-attach-block .hint{margin-bottom:10px}
.incoming-attach-results{
  display:flex; flex-direction:column; gap:2px; max-height:200px; overflow-y:auto;
  border:1px solid var(--rule); border-radius:3px; padding:4px;
}
.incoming-attach-result{
  display:flex; align-items:center; gap:8px; font-size:13px; padding:6px 8px;
  border-radius:2px; cursor:pointer;
}
.incoming-attach-result:hover{background:var(--paper)}
.incoming-attach-result.is-selected{background:var(--paper); font-weight:600}
.incoming-attach-result input{margin:0}
.incoming-attach-result .k{color:var(--chalk); font-weight:400; font-size:11px; margin-left:auto}
.schedule-pdf{display:flex; align-items:center; gap:10px; flex-wrap:wrap; font-size:13px}
.schedule-pdf .k{color:var(--chalk); font-size:12px}
.attachments-block{margin-top:14px; padding-top:14px; border-top:1px solid var(--rule)}
.attachments-list{display:flex; flex-direction:column; gap:6px; margin-bottom:10px}
.attachment{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  font-size:13px; padding:6px 0;
}
.attachment a{color:var(--accent); font-weight:600; text-decoration:none}
.attachment a:hover{text-decoration:underline}
.attachment .k{color:var(--chalk); font-size:12px}
.attachment-remove{
  appearance:none; border:0; background:none; color:var(--signal); cursor:pointer;
  font-size:16px; line-height:1; padding:0 4px; margin-left:auto;
}
.attachment-remove:hover{background:#F5DAD4; border-radius:3px}

.payments-block{margin-top:14px; padding-top:14px; border-top:1px solid var(--rule)}
.payments-list{display:flex; flex-direction:column; gap:2px}
.payment-row{
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  font-size:13px; padding:5px 0; border-bottom:1px solid var(--rule);
}
.payment-row .v{font-variant-numeric:tabular-nums; font-weight:600}
.payment-row--total{border-bottom:0; border-top:1px solid var(--rule); margin-top:2px; padding-top:8px; font-weight:600}
.payment-remove{
  appearance:none; border:0; background:none; color:var(--signal); cursor:pointer;
  font-size:16px; line-height:1; padding:0 4px;
}
.payment-remove:hover{background:#F5DAD4; border-radius:3px}

/* gantt chart --------------------------------------------------------------- */
.gantt-chart{
  border:1px solid var(--rule); background:var(--card); border-radius:3px;
  overflow-x:auto; margin-bottom:8px;
}
.gantt-chart[hidden]{display:none}
.gantt-months{
  display:grid; grid-template-columns:180px 1fr 56px 28px; min-width:640px;
  border-bottom:1px solid var(--rule); height:28px;
}
.gantt-months--financial{grid-template-columns:180px 1fr 56px 92px 92px 100px 28px; min-width:940px}
.gantt-money-head{font-size:10px; text-transform:uppercase; letter-spacing:.05em; color:var(--chalk);
  display:flex; align-items:center; justify-content:flex-end; padding-right:8px}
.gantt-months-track{position:relative; height:100%}
.gantt-month{position:absolute; top:0; left:0; height:100%;
  border-left:1px solid var(--rule); padding-left:4px; display:flex; align-items:center;
}
.gantt-month span{font-size:10.5px; color:var(--chalk); white-space:nowrap; text-transform:uppercase; letter-spacing:.04em}
.gantt-rows{min-width:640px}
.gantt-row{
  display:grid; grid-template-columns:180px 1fr 56px 28px; align-items:center;
  min-height:34px; border-bottom:1px solid var(--rule); font-size:12.5px;
}
.gantt-row--financial{grid-template-columns:180px 1fr 56px 92px 92px 100px 28px; min-width:940px}
.gantt-money{text-align:right; padding-right:8px; font-variant-numeric:tabular-nums; color:var(--ink)}
.gantt-money--editable{cursor:pointer}
.gantt-money--editable:hover{background:var(--paper); border-radius:2px}
.gantt-money--over{color:var(--signal); font-weight:600}
.gantt-row:last-child{border-bottom:0}
.gantt-label{padding:6px 10px 6px 12px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.gantt-track{position:relative; height:100%; padding:6px 4px}
.gantt-bar{
  position:absolute; top:8px; height:18px; background:#E3DFD3; border-radius:3px;
  overflow:hidden; min-width:3px;
}
.gantt-bar--editable{cursor:pointer}
.gantt-bar--editable:hover{outline:2px solid var(--accent); outline-offset:1px}
.gantt-bar-fill{position:absolute; left:0; top:0; height:100%; background:var(--accent)}
.gantt-pct{text-align:right; padding-right:8px; color:var(--chalk); font-variant-numeric:tabular-nums}
.gantt-delete{
  appearance:none; border:0; background:none; color:var(--signal); cursor:pointer;
  font-size:15px; line-height:1; padding:2px;
}
.gantt-delete:hover{background:#F5DAD4; border-radius:3px}

.attachment-upload{display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:4px}
.attachment-upload select{padding:5px 8px; font:inherit; font-size:12.5px; border:1px solid var(--rule); border-radius:2px}
.attachment-upload input[type=file]{font-size:12.5px; max-width:220px}
.attachment-upload input[type=text], .attachment-upload input[type=number]{
  padding:5px 8px; font:inherit; font-size:12.5px; border:1px solid var(--rule); border-radius:2px;
}
.block-heading{font-size:11px; text-transform:uppercase; letter-spacing:.09em; color:var(--chalk);
  margin:14px 0 4px; padding-top:10px; border-top:1px solid var(--rule)}
#orgSettingsForm .block-heading{grid-column:1/-1; border-top:0; padding-top:0; margin-top:6px}
#orgSettingsForm .block-heading:first-child{margin-top:0}
.logo-settings-row{display:flex; align-items:flex-start; gap:16px; margin-top:6px}
#settingLogoPreview{width:96px; height:96px; object-fit:contain; background:var(--paper);
  border:1px solid var(--rule); border-radius:6px; padding:8px; flex-shrink:0}
.logo-settings-controls{flex:1; min-width:0}
.logo-settings-controls input[type="file"]{display:block; font-size:13px}
.invoice-actions{display:flex; align-items:center; gap:4px; margin-left:auto}
.invoice-actions .attachment-remove{margin-left:0}

/* compact icon buttons: files-attached indicator and the paid checkmark,
   used in place of text buttons ("Files", "Mark as paid") to keep the
   invoice rows/cards narrow. */
.icn{display:block; flex-shrink:0}
/* Medium row-action buttons: big enough to hit accurately (32px box clears
   the usual touch-target floor) without the action cell dominating the row. */
/* Raised row-action buttons. The depth is in the button, never in the glyph:
   these icons are drawn at a 1.6px stroke, and a highlight-plus-shadow on a
   line that thin reads as blurred rather than lifted. The button carries a
   light top edge and a soft drop shadow, and presses in on click, so the
   affordance is physical while the icon stays exactly as legible as it was.
   Each action keeps its own colour - a green approve, a red delete - tinted
   through the gradient and the border rather than a flat fill, so the row
   still reads at a glance from across a site office. */
.icon-btn{
  appearance:none; display:inline-flex; align-items:center; justify-content:center; gap:4px;
  border:1px solid #CFC8B8; color:var(--chalk);
  background:linear-gradient(#FFFFFF, #EFEBE2);
  border-radius:3px; padding:7px 10px; font-size:15px; line-height:1; cursor:pointer;
  min-height:32px; min-width:32px;
  box-shadow:0 1px 0 rgba(255,255,255,.9) inset, 0 1px 2px rgba(36,40,45,.16), 0 2px 4px rgba(36,40,45,.08);
  transition:box-shadow .08s ease, transform .08s ease, background .12s ease;
}
.icon-btn:active{
  background:linear-gradient(#E6E1D6, #F5F1E9);
  box-shadow:0 1px 2px rgba(36,40,45,.26) inset;
  transform:translateY(1px);
}
@media (prefers-reduced-motion: reduce){
  .icon-btn{transition:none}
  .icon-btn:active{transform:none}
}
/* Scale the glyph with the button, without touching icons used elsewhere. */
.icon-btn .icn{width:17px; height:17px}
.icon-btn:hover{
  border-color:var(--accent); color:var(--accent);
  background:linear-gradient(#FFFFFF, #E9EFEB);
}
.icon-btn .icon-btn-count{font-size:11px; font-variant-numeric:tabular-nums}
.icon-btn--paid{
  border-color:#6FA98C; color:#1E5238; cursor:pointer;
  background:linear-gradient(#DCEFE4, #BEDCCC);
  box-shadow:0 1px 0 rgba(255,255,255,.75) inset, 0 1px 2px rgba(30,80,55,.24), 0 2px 4px rgba(30,80,55,.12);
}
.icon-btn--paid:hover{background:linear-gradient(#E8F5EE, #B2D5C2)}

/* Part paid is its own state, not a shade of paid: amber, because money is
   still owed on it, and a green tick on a half-paid invoice is exactly how
   a balance gets forgotten. */
.icon-btn--part-paid{
  border-color:#D9A960; color:#8A5A10;
  background:linear-gradient(#FEF6E8, #F6E3C4);
  box-shadow:0 1px 0 rgba(255,255,255,.85) inset, 0 1px 2px rgba(120,80,15,.22), 0 2px 4px rgba(120,80,15,.10);
}
.icon-btn--part-paid:hover{background:linear-gradient(#FFFCF6, #F0D6AE); border-color:var(--hazard)}
.paid-indicator{
  display:inline-flex; align-items:center; justify-content:center;
  width:32px; height:32px; border-radius:50%; background:#E1EFE7; color:var(--go);
  font-size:15px; line-height:1;
}
.paid-indicator--unpaid{
  background:var(--card); color:var(--chalk); border:1px solid var(--rule);
}
.icon-btn--mark-paid{
  border-color:var(--rule); color:var(--chalk); width:32px; height:32px;
  border-radius:50%; padding:0; justify-content:center;
}
.icon-btn--mark-paid:hover{border-color:var(--go); color:var(--go)}

/* the rest of the invoice-row action set (approve/reject/reopen/resubmit/
   due date/payment report/email/delete) - same compact icon-btn shell,
   just tinted per action so approve/reject/delete read at a glance. */
.icon-btn--go{
  border-color:#7FB295; color:var(--go);
  background:linear-gradient(#F4FBF7, #DCEDE3);
  box-shadow:0 1px 0 rgba(255,255,255,.9) inset, 0 1px 2px rgba(30,80,55,.20), 0 2px 4px rgba(30,80,55,.10);
}
.icon-btn--go:hover{background:linear-gradient(#FFFFFF, #CFE6D9); border-color:var(--go)}
.icon-btn--go:active{background:linear-gradient(#C8E0D3, #E6F2EC)}
.icon-btn--danger{
  border-color:#D89B92; color:var(--signal);
  background:linear-gradient(#FEF7F5, #F6E0DB);
  box-shadow:0 1px 0 rgba(255,255,255,.9) inset, 0 1px 2px rgba(120,35,25,.20), 0 2px 4px rgba(120,35,25,.10);
}
.icon-btn--danger:hover{background:linear-gradient(#FFFFFF, #F2CEC6); border-color:var(--signal)}
.icon-btn--danger:active{background:linear-gradient(#EDC4BB, #F9E4DF)}

/* forms ------------------------------------------------------------------- */
.contract-upload{
  background:var(--paper); border:1px dashed var(--rule); border-radius:3px;
  padding:16px 18px; max-width:900px; margin-bottom:18px;
}
.contract-upload h4{margin:0 0 4px}
.contract-upload input[type=file]{font-size:12.5px; margin-right:8px}
.contract-upload .hint + .btn, .contract-upload .hint + a.btn{margin-top:8px; display:inline-block}
.contract-evidence{margin-top:12px; font-size:12.5px}
.contract-evidence .field-row{
  display:flex; gap:10px; padding:6px 0; border-top:1px solid var(--rule);
  align-items:baseline;
}
.contract-evidence .field-row:first-child{border-top:0}
.contract-evidence .field-name{width:150px; flex-shrink:0; font-weight:600; color:var(--ink)}
.contract-evidence .field-value{width:140px; flex-shrink:0}
.contract-evidence .field-quote{color:var(--chalk); font-style:italic}
.spreadsheet-stepper{margin-top:12px}
.spreadsheet-stepper-nav{display:flex; align-items:center; gap:14px; font-size:13px; font-weight:600}
.spreadsheet-stepper-nav[hidden]{display:none}
.contract-evidence .field-value[data-found="false"]{color:#9AA5A1}

.form{display:grid; gap:16px 20px; grid-template-columns:repeat(auto-fit,minmax(250px,1fr));
  background:var(--card); border:1px solid var(--rule); padding:20px; max-width:min(100%, 1400px)}
.form[hidden]{display:none}
.field{display:flex; flex-direction:column; gap:5px}
.field[hidden]{display:none}
.field--wide{grid-column:1/-1}
/* Two related inputs on one line (a day and a time), collapsing to stacked
   on a narrow screen rather than squeezing both. */
.field-pair{display:grid; grid-template-columns:1fr 1fr; gap:12px}
@media (max-width:520px){.field-pair{grid-template-columns:1fr}}
label{font-size:12px; font-weight:600; letter-spacing:.02em}
input, select, textarea{
  font:inherit; padding:9px 11px; border:1px solid var(--rule); border-radius:2px;
  background:#fff; color:var(--ink); width:100%;
}
input:focus-visible, select:focus-visible, textarea:focus-visible, .btn:focus-visible{
  outline:2px solid var(--accent); outline-offset:1px
}
textarea{resize:vertical}
.hint{font-size:12px; color:var(--chalk); margin:0}
/* A quieter aside on the same line as a status value, rather than its own
   paragraph - used where the status is the point and the pointer to where
   you change it is secondary. */
.hint-inline{font-size:12px; color:var(--chalk); display:block; margin-top:2px}
.check{flex-direction:row; align-items:center; gap:9px}
.check input{width:auto}
.check label{font-weight:400; font-size:13px}
.actions{grid-column:1/-1; display:flex; flex-wrap:wrap; gap:14px; align-items:center}

.btn{appearance:none; cursor:pointer; font:inherit; font-family:var(--display); font-size:13px; font-weight:600;
  padding:9px 16px; border-radius:2px; border:1px solid var(--accent); background:#fff;
  color:var(--accent)}
.btn:hover{background:var(--accent); color:var(--paper)}
.btn--go{background:var(--accent); color:var(--paper); border-color:var(--accent)}
.btn--go:hover{background:#163A2F}
.btn--danger{border-color:var(--signal); color:var(--signal)}
.btn--danger:hover{background:var(--signal); color:#fff}
.form-msg{font-size:13px}
.form-msg[data-tone="error"]{color:var(--signal); font-weight:550}
.form-msg[data-tone="ok"]{color:var(--go); font-weight:550}

/* Australian-format date fields (see enhanceDateInput() in app.js) - the
   real <input type="date"> is kept for its value/validation but visually
   replaced by a typed dd/mm/yyyy field plus a calendar dropdown, so the
   date order never depends on the visitor's browser/OS locale. */
.au-date-field{position:relative; display:flex; width:100%}
.au-date-native{position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0}
.au-date-text{flex:1 1 auto; min-width:0; border-radius:2px 0 0 2px}
.au-date-toggle{flex:0 0 auto; width:36px; border:1px solid var(--rule); border-left:0;
  border-radius:0 2px 2px 0; background:#fff; cursor:pointer; font-size:14px;
  display:flex; align-items:center; justify-content:center; color:var(--ink)}
.au-date-toggle:hover{border-color:var(--accent); color:var(--accent); background:var(--paper)}
.au-date-calendar{position:absolute; top:calc(100% + 4px); left:0; z-index:40; width:236px;
  background:#fff; border:1px solid var(--rule); border-radius:4px; padding:10px;
  box-shadow:0 8px 24px rgba(36,40,45,.16)}
.au-date-calendar-header{display:flex; align-items:center; justify-content:space-between;
  margin-bottom:8px; font-size:13px; font-weight:600; color:var(--ink)}
.au-date-calendar-header button{appearance:none; border:0; background:transparent; cursor:pointer;
  font-size:16px; line-height:1; padding:2px 8px; border-radius:2px; color:var(--ink)}
.au-date-calendar-header button:hover{background:var(--paper)}
.au-date-grid{display:grid; grid-template-columns:repeat(7,1fr); gap:2px; text-align:center}
.au-date-grid-wd{font-size:10.5px; color:var(--chalk); font-weight:600; padding:3px 0}
.au-date-day{appearance:none; border:0; background:transparent; border-radius:50%;
  width:28px; height:28px; font:inherit; font-size:12.5px; cursor:pointer; color:var(--ink)}
.au-date-day:hover{background:var(--paper)}
.au-date-day--today{font-weight:700; color:var(--accent)}
.au-date-day--selected{background:var(--accent); color:#fff}
.au-date-today-btn{margin-top:8px; width:100%; appearance:none; border:1px solid var(--rule);
  background:#fff; border-radius:2px; padding:6px; font:inherit; font-size:12px; font-weight:600;
  cursor:pointer; color:var(--ink)}
.au-date-today-btn:hover{border-color:var(--accent); color:var(--accent)}

/* tables ------------------------------------------------------------------ */
/* A select sitting inside a table cell: quiet until you interact with it, so
   a column of them doesn't read as a wall of form controls. */
.cell-select{
  font:inherit; font-size:12.5px; color:var(--ink);
  padding:4px 6px; max-width:190px;
  background:transparent; border:1px solid transparent; border-radius:2px;
}
.cell-select:hover{border-color:var(--rule); background:var(--card)}
.cell-select:focus{border-color:var(--accent); background:var(--card); outline:none}
.cell-select:disabled{opacity:.5}

/* The "these conditions are from" selector above the import file picker. */
.field--inline{display:flex; align-items:center; gap:10px; margin-bottom:10px; font-size:13px}
.field--inline select{font:inherit; font-size:13px; padding:6px 8px; border:1px solid var(--rule); border-radius:2px}

.table-scroll{overflow-x:auto; -webkit-overflow-scrolling:touch; margin-bottom:0}
.grid{width:100%; border-collapse:collapse; background:var(--card);
  border:1px solid var(--rule); font-size:13.5px}
.grid th, .grid td{padding:9px 12px; text-align:left; border-bottom:1px solid var(--rule); white-space:nowrap}
.grid th{font-size:11px; text-transform:uppercase; letter-spacing:.09em;
  color:var(--chalk); background:var(--paper)}
/* long free-text columns (order/variation descriptions) wrap onto multiple
   lines instead of forcing the whole table into a horizontal scroll. */
.grid td.td-wrap{white-space:normal; max-width:420px; min-width:220px}

/* Approval conditions is almost entirely free text - the condition wording,
   category, responsibility and timing are all sentences, not labels. The
   table-wide nowrap above would run each of them straight over the next
   column, so every cell in this one table wraps instead. Scoped by id
   deliberately: `.grid td` above is more specific than a bare class, so a
   class-only rule here loses the cascade and the text overflows again. */
#daConditionsTable td{white-space:normal; vertical-align:top; line-height:1.4}
#daConditionsTable th{white-space:nowrap}
#daConditionsTable td.da-requirement{min-width:300px; max-width:520px; overflow-wrap:anywhere}
#daConditionsTable td.da-evidence-cell{max-width:220px; color:var(--chalk); font-size:13px; overflow-wrap:anywhere}
/* Type badge and condition number stay on one line - they're short and the
   number is the thing you scan down. */
#daConditionsTable td:first-child, #daConditionsTable td:nth-child(2){white-space:nowrap}
#daConditionPreviewTable td{white-space:normal; vertical-align:top}

/* handover packs ------------------------------------------------------------
   Same wrapping problem as the conditions table - document names and notes
   are phrases, not labels - so the same id-scoped override applies. */
#handoverItemsTable td{white-space:normal; vertical-align:top; line-height:1.4}
#handoverItemsTable th{white-space:nowrap}
#handoverItemsTable td.handover-name{min-width:280px; max-width:460px; overflow-wrap:anywhere}
#handoverItemsTable td.handover-evidence-cell{max-width:220px; color:var(--chalk); font-size:13px; overflow-wrap:anywhere}
#handoverLotsTable td{vertical-align:top}
#handoverLotsTable tr.is-selected td{background:var(--paper)}

/* site diary and defects: free-text columns again, same id-scoped override. */
#diaryTable td{white-space:normal; vertical-align:top; line-height:1.4}
#diaryTable th{white-space:nowrap}
#diaryTable td.diary-text{min-width:180px; max-width:300px; overflow-wrap:anywhere}
#diaryTable td:first-child{white-space:nowrap}
#defectsTable td{white-space:normal; vertical-align:top; line-height:1.4}
#defectsTable th{white-space:nowrap}
#defectsTable td.defect-desc{min-width:260px; max-width:440px; overflow-wrap:anywhere}
#defectsTable td:first-child{white-space:nowrap}
#complianceTable td{vertical-align:top}

/* Tier 2 registers: free-text columns, same id-scoped wrapping override. */
#rfisTable td, #eotTable td, #instructionsTable td{white-space:normal; vertical-align:top; line-height:1.4}
#rfisTable th, #eotTable th, #instructionsTable th{white-space:nowrap}
#rfisTable td:first-child, #eotTable td:first-child, #instructionsTable td:first-child{white-space:nowrap}
#rfisTable td.rfi-subject{min-width:240px; max-width:380px; overflow-wrap:anywhere}
#rfisTable td.rfi-answer{min-width:180px; max-width:320px; overflow-wrap:anywhere}
#eotTable td.eot-desc{min-width:240px; max-width:420px; overflow-wrap:anywhere}
#instructionsTable td.instruction-subject{min-width:240px; max-width:380px; overflow-wrap:anywhere}
#instructionsTable td.instruction-actions{min-width:180px; max-width:320px; overflow-wrap:anywhere}

/* Tier 3: cashflow chart, inspection plans, performance -----------------------
   Chart colours are the app's own go/hazard tokens, checked for colour-vision
   separation (worst adjacent pair dE 13.6 protan, 27.1 normal). Amber falls
   below 3:1 against the light surface, which is why the table beneath the
   chart is not optional - it carries the numbers. */
.chart-figure{margin:0 0 22px; background:var(--card); border:1px solid var(--rule); padding:16px 18px}
.chart-figure[hidden]{display:none}
.chart-caption{
  display:flex; justify-content:space-between; align-items:baseline; gap:16px;
  flex-wrap:wrap; margin-bottom:12px;
}
.chart-title{font-family:var(--display); font-weight:700; font-size:13px; text-transform:uppercase; letter-spacing:.08em; color:var(--chalk)}
.chart-legend{display:flex; gap:16px; flex-wrap:wrap}
.legend-item{display:inline-flex; align-items:center; gap:6px; font-size:12.5px; color:var(--chalk)}
.legend-swatch{width:11px; height:11px; border-radius:2px; flex-shrink:0}
.legend-swatch--paid{background:var(--go)}
.legend-swatch--due{background:var(--hazard)}
.chart-scroll{overflow-x:auto}
.chart-bar--paid{fill:var(--go)}
.chart-bar--due{fill:var(--hazard)}
.chart-grid{stroke:var(--rule); stroke-width:1}
.chart-axis{stroke:var(--chalk); stroke-width:1}
.chart-tick{fill:var(--chalk); font-family:var(--sans); font-size:11px}
.chart-tick--muted{opacity:.65}

#itpPointsTable td, #performanceTable td{white-space:normal; vertical-align:top; line-height:1.4}
#itpPointsTable th, #performanceTable th{white-space:nowrap}
#itpPointsTable td.itp-desc{min-width:260px; max-width:440px; overflow-wrap:anywhere}
#itpPointsTable td.itp-evidence-cell{max-width:200px; color:var(--chalk); font-size:13px; overflow-wrap:anywhere}
#itpPointsTable td:first-child{white-space:nowrap}
#performanceTable td.performance-comments{min-width:220px; max-width:400px; overflow-wrap:anywhere}
#itpTable td{vertical-align:top}
#itpTable tr.is-selected td{background:var(--paper)}
#cashflowTable td{white-space:nowrap}

/* Xero exchange: three numbered steps, because the order matters - exporting
   before confirming, and confirming only once Xero has actually accepted. */
.xero-step{display:flex; gap:14px; align-items:flex-start; padding:14px 0; border-top:1px solid var(--rule)}
.xero-step:first-of-type{border-top:0; padding-top:4px}
.xero-step > div{flex:1; min-width:0}
.xero-step strong{font-family:var(--display); font-size:14.5px}
.xero-step-n{
  flex-shrink:0; width:24px; height:24px; border-radius:50%;
  background:var(--accent); color:var(--header-ink);
  display:inline-flex; align-items:center; justify-content:center;
  font-family:var(--display); font-size:12.5px; font-weight:700; margin-top:2px;
}
.xero-h{
  font-family:var(--display); font-size:13px; font-weight:700; text-transform:uppercase;
  letter-spacing:.08em; color:var(--chalk); margin:22px 0 8px;
}
.xero-clean{
  margin:18px 0 0; padding:12px 14px; font-size:13.5px;
  background:#E1EFE7; border-left:3px solid var(--go); color:#1E5238;
}
#xeroReconcileResult[hidden]{display:none}
#xeroReconcileResult table td{white-space:nowrap}

/* A lot reference that opens its pack - a button, not a link, since it
   changes what's shown rather than navigating anywhere. */
.link-btn{
  appearance:none; background:none; border:0; padding:0; font:inherit; font-weight:600;
  color:var(--accent); cursor:pointer; text-align:left; text-decoration:underline;
  text-underline-offset:2px;
}
.link-btn:hover{color:var(--ink)}
.link-btn:focus-visible{outline:2px solid var(--accent); outline-offset:2px}

.pack-progress{display:flex; align-items:center; gap:8px; min-width:150px}
.pack-progress-bar{
  flex:1; height:8px; background:var(--rule); border-radius:4px; overflow:hidden; min-width:80px;
}
.pack-progress-bar span{display:block; height:100%; background:var(--go); border-radius:4px}
.pack-progress-label{font-size:12px; color:var(--chalk); font-variant-numeric:tabular-nums; white-space:nowrap}
.grid .num, .grid td.num{text-align:right; font-variant-numeric:tabular-nums}
.grid tbody tr:last-child td{border-bottom:0}
.grid-total-row td{font-weight:700; border-top:2px solid var(--ink); background:var(--paper)}
.grid-section-row td{font-family:var(--display); font-weight:700; font-size:12.5px;
  text-transform:uppercase; letter-spacing:.07em; background:var(--paper); color:var(--ink);
  border-top:1px solid var(--rule)}
.grid-section-row .k{text-transform:none; letter-spacing:normal; font-weight:400; color:var(--chalk)}

/* Month bands on the Invoices table are buttons that open and shut their
   rows. The button fills the cell so the whole band is the click target -
   a 12px chevron is a poor thing to have to aim at. Padding moves from the
   cell to the button for the same reason. */
.grid-section-row.has-toggle td{padding:0}
.month-toggle{
  display:flex; align-items:center; gap:9px; width:100%;
  font:inherit; color:inherit; text-align:left; cursor:pointer;
  background:none; border:0; padding:9px 12px;
  /* Browsers reset text-transform and letter-spacing on form controls, and
     the band would quietly stop being uppercase the moment it became a
     button. Inherit them back from the cell. */
  text-transform:inherit; letter-spacing:inherit;
}
.month-toggle:hover{background:rgba(0,0,0,.04)}
.month-toggle:focus-visible{outline:2px solid var(--accent); outline-offset:-2px}
.month-toggle[disabled]{cursor:default; opacity:1}
/* While a search or filter is on, every month is forced open and the
   chevron would be a control that does nothing - hide it rather than
   showing a dead one. */
.month-toggle[disabled] .month-chev{visibility:hidden}
.month-chev{flex:none; color:var(--chalk); transition:transform .15s ease}
.grid-section-row.is-open .month-chev{transform:rotate(90deg)}
@media (prefers-reduced-motion:reduce){.month-chev{transition:none}}
.month-name{flex:none}
/* The band is the one row in this table allowed to wrap - on a narrow
   screen the count/total/owing tail would otherwise force the whole table
   into a horizontal scroll. */
.grid-section-row.has-toggle td, .month-toggle .k{white-space:normal}
.month-owing{color:var(--signal); font-weight:600}

/* Expand-all / collapse-all, sitting with the status and search controls. */
.month-controls{display:flex; gap:8px; align-items:flex-end}
.month-controls[hidden]{display:none}

/* a filename shown as a file-type glyph instead of the raw (often long)
   filename text - hover/focus for a tooltip with the real name. */
.file-icon-link{
  display:inline-flex; align-items:center; justify-content:center;
  width:30px; height:30px; border-radius:4px; color:var(--chalk);
  text-decoration:none; border:1px solid transparent;
}
.file-icon-link:hover, .file-icon-link:focus-visible{
  background:var(--paper); border-color:var(--rule); color:var(--accent);
}

.empty{padding:40px 20px; text-align:center; color:var(--chalk);
  border:1px dashed var(--rule); background:var(--card)}

.result{background:var(--card); border:1px solid var(--rule); padding:18px;
  margin-top:20px; max-width:900px}
.result h4{margin:0 0 4px; font-size:14px}
.result p{margin:0 0 14px; font-size:13px; color:var(--chalk)}
.result .big{font-size:20px; font-weight:650; color:var(--ink); letter-spacing:-.02em}

.colophon{margin-top:48px; padding:24px 32px 36px; border-top:1px solid var(--rule);
  font-size:12px; color:var(--chalk); max-width:min(100%, 95ch)}
.colophon p{margin:0 0 6px}

@media (max-width:640px){
  main{padding:24px 20px}
  .masthead{padding:20px 20px 16px}
  .tabs{padding:0 20px}
  .project-picker select{min-width:0; width:100%}
  .form{padding:16px}
}
@media (prefers-reduced-motion:reduce){*{transition:none!important; animation:none!important}}
