/* Vanguard — drop bury operations
 *
 * Palette comes from utility locate marking. Orange is the APWA code
 * for communication lines, which is the work. Green and red are the
 * flag colours used on site. Nothing here is decorative.
 *
 * Built for two very different readers: an office on a desktop, and a
 * tech holding a phone in a front yard in direct sun. That is why the
 * contrast is hard, the numbers are large, and the touch targets are
 * generous rather than tidy.
 */

:root {
  --locate:      #F26522;   /* communications orange */
  --locate-dark: #C44A11;
  --flag-green:  #1E7B45;
  --flag-red:    #C22B2B;
  --flag-amber:  #B4770B;

  --ink:         #14171A;
  --ink-2:       #4A5157;
  --ink-3:       #767E85;
  --rule:        #D6D2CB;
  --rule-soft:   #E9E6E0;
  --paper:       #FBFAF7;
  --surface:     #FFFFFF;
  --chrome:      #1A1D21;

  --gutter: 1.25rem;
  --r-lg: 10px;
  --r-md: 7px;
  --r-sm: 5px;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: 'Barlow', system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
}

[hidden] { display: none !important; }

h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.01em; }

button, input, select, textarea { font: inherit; }

:focus-visible {
  outline: 3px solid var(--locate);
  outline-offset: 2px;
}

.mono { font-variant-numeric: tabular-nums; }
.hint { color: var(--ink-3); font-weight: 400; }


/* ---------- wordmark ---------- */

.wordmark {
  font-family: 'Barlow Semi Condensed', 'Barlow', sans-serif;
  font-weight: 700;
  font-size: 2.75rem;
  letter-spacing: 0.02em;
  line-height: 1;
  margin: 0;
}
.wordmark.small { font-size: 1.35rem; color: #fff; }


/* ---------- sign in ---------- */

.signin {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: var(--gutter);
  background: var(--chrome);
}

.signin-panel {
  width: min(100%, 26rem);
  background: var(--surface);
  padding: 2rem 1.75rem 1.75rem;
  border-top: 6px solid var(--locate);
}

.signin-sub {
  margin: 0.25rem 0 1.75rem;
  color: var(--ink-2);
}


/* ---------- forms ---------- */

label {
  display: block;
  margin: 0.9rem 0 0.3rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--ink-2);
}

input, select, textarea {
  width: 100%;
  padding: 0.7rem 0.75rem;
  border: 1.5px solid var(--rule);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink);
}

input:focus, select:focus, textarea:focus { border-color: var(--locate); }

textarea { resize: vertical; }

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 0.75rem; }
.grid-3 { display: grid; grid-template-columns: 2fr 0.7fr 1fr; gap: 0 0.75rem; }

.btn-primary {
  margin-top: 1.5rem;
  width: 100%;
  padding: 0.85rem 1rem;
  border: none;
  border-radius: var(--r-sm);
  background: var(--locate);
  color: #fff;
  font-weight: 600;
  cursor: pointer;
}
.btn-primary:hover { background: var(--locate-dark); }
.btn-primary[disabled] { background: var(--ink-3); cursor: default; }

.btn-quiet {
  padding: 0.6rem 0.9rem;
  border: 1.5px solid var(--rule);
  border-radius: var(--r-sm);
  background: transparent;
  color: inherit;
  cursor: pointer;
}
.btn-quiet:hover { border-color: var(--ink-2); }

.field-error {
  margin: 0.75rem 0 0;
  padding: 0.6rem 0.7rem;
  background: #FBEBEB;
  border-left: 4px solid var(--flag-red);
  color: var(--flag-red);
  font-size: 0.9rem;
}


/* ---------- chrome ---------- */

.topbar {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0.7rem var(--gutter);
  background: var(--chrome);
  color: #fff;
}

.nav { display: flex; gap: 0.25rem; margin-right: auto; }

.nav button {
  padding: 0.45rem 0.8rem;
  border: none;
  background: transparent;
  color: #B9BEC4;
  font-weight: 600;
  cursor: pointer;
  border-bottom: 3px solid transparent;
}
.nav button[aria-current="page"] { color: #fff; border-bottom-color: var(--locate); }

.who { display: flex; align-items: center; gap: 0.9rem; font-size: 0.9rem; color: #B9BEC4; }
.who .btn-quiet { border-color: #3A4148; color: #E6E9EC; padding: 0.35rem 0.7rem; }

main { padding: var(--gutter); max-width: 68rem; margin: 0 auto; }

/* A dense grid is a data surface: a wider monitor should show MORE
 * columns, not the same columns stretched. Those pages lose the cap.
 *
 * Everything else keeps one, whatever the theme. A pay table spread
 * across a 2000px monitor puts the job number and the amount three
 * feet apart, which is harder to read, not easier. */
body[data-wide="true"] main { max-width: none; }
body[data-wide="false"] main { max-width: 74rem; }


/* ---------- page heads ---------- */

.page-head {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  margin-bottom: 1.25rem;
  padding-bottom: 0.75rem;
  border-bottom: 2px solid var(--ink);
}
.page-head h2 { font-size: 1.5rem; }
.page-head .count { color: var(--ink-3); margin-right: auto; }
.page-head button { margin-top: 0; width: auto; }


/* ---------- the money, which is why anyone opens this ---------- */

.total-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 2.5rem;
  padding: 1.25rem 0 1.5rem;
}
.total {
  display: flex;
  flex-direction: column-reverse;   /* figure reads first, label supports */
}
.total .figure {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 2.75rem;
  font-weight: 700;
  line-height: 1;
}
.total .label { font-size: 0.85rem; color: var(--ink-2); font-weight: 600; }
.total.owed .figure { color: var(--flag-red); }


/* ---------- job rows: the stripe is the status ---------- */

.rows { display: flex; flex-direction: column; gap: 2px; }

.row {
  display: grid;
  grid-template-columns: 6px 1fr auto;
  gap: 0 1rem;
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--rule-soft);
  border-left: none;
  padding: 0;
  text-align: left;
  width: 100%;
  font: inherit;
  color: inherit;
}
.row > .stripe { align-self: stretch; }
.row > .body   { padding: 0.85rem 0; min-width: 0; }
.row > .end    { padding: 0.85rem 1rem 0.85rem 0; text-align: right; }

.stripe            { background: var(--ink-3); }
.stripe.paid       { background: var(--flag-green); }
.stripe.unpaid     { background: var(--flag-red); }
.stripe.short      { background: var(--flag-red); }
.stripe.over       { background: var(--flag-amber); }
.stripe.notchecked { background: var(--rule); }
.stripe.open       { background: var(--locate); }

.row .job {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-weight: 700;
  font-size: 1.15rem;
}
.row .meta {
  color: var(--ink-2);
  font-size: 0.9rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.row .amount {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-weight: 700;
  font-size: 1.35rem;
}
.row .state { font-size: 0.85rem; font-weight: 600; color: var(--ink-2); }
.row .state.unpaid, .row .state.short { color: var(--flag-red); }
.row .state.paid  { color: var(--flag-green); }
.row .state.over  { color: var(--flag-amber); }

button.row { cursor: pointer; }
button.row:hover { border-color: var(--ink-3); }


/* ---------- empty states are an invitation ---------- */

.empty {
  padding: 3rem 1.5rem;
  background: var(--surface);
  border: 1px dashed var(--rule);
  text-align: center;
  color: var(--ink-2);
  border-radius: var(--r-lg);
}
.empty strong { display: block; color: var(--ink); margin-bottom: 0.35rem; }


/* ---------- dialogs ---------- */

dialog {
  width: min(100%, 34rem);
  padding: 1.5rem;
  border: none;
  border-top: 6px solid var(--locate);
  background: var(--surface);
  color: var(--ink);
}
dialog::backdrop { background: rgba(20, 23, 26, 0.6); }
dialog h2 { font-size: 1.25rem; margin-bottom: 0.5rem; }

.dlg-actions {
  display: flex;
  gap: 0.6rem;
  justify-content: flex-end;
  margin-top: 1.5rem;
}
.dlg-actions .btn-primary { margin-top: 0; width: auto; }

.preview {
  margin-top: 1.25rem;
  padding: 0.85rem 1rem;
  background: var(--paper);
  border-left: 4px solid var(--ink);
  font-size: 0.95rem;
}
.preview dl { display: grid; grid-template-columns: 1fr auto; gap: 0.2rem 1rem; margin: 0; }
.preview dt { color: var(--ink-2); }
.preview dd { margin: 0; font-weight: 600; }
.preview .total-line { border-top: 1.5px solid var(--rule); margin-top: 0.4rem; padding-top: 0.4rem; }


/* ---------- phone ---------- */

@media (max-width: 640px) {
  :root { --gutter: 0.9rem; }
  .topbar { flex-wrap: wrap; gap: 0.75rem 1rem; }
  .nav { order: 3; width: 100%; margin-right: 0; }
  .who { margin-left: auto; }
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .total .figure { font-size: 2.25rem; }
  .row .amount { font-size: 1.5rem; }
  .row > .body { padding: 1rem 0; }
  .row > .end  { padding: 1rem 0.85rem 1rem 0; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}


/* ---------- invoice preview: both sides at once ----------
 *
 * An admin deciding what to invoice is also deciding what someone
 * gets paid, so their view sits right next to the company's rather
 * than being something you go and check separately.
 */

.two-views {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
}

.view-col h3 {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--ink-2);
  margin-bottom: 0.4rem;
  padding-bottom: 0.3rem;
  border-bottom: 1.5px solid var(--rule);
}

.view-col.tech-view h3 {
  color: var(--locate-dark);
  border-bottom-color: var(--locate);
}

.profit-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-top: 1rem;
  padding-top: 0.7rem;
  border-top: 2px solid var(--ink);
}
.profit-line .label  { font-weight: 600; }
.profit-line .figure {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-weight: 700;
  font-size: 1.6rem;
  line-height: 1;
}

@media (max-width: 640px) {
  .two-views { grid-template-columns: 1fr; gap: 1rem; }
}

.section-head {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--ink-2);
  margin: 1.5rem 0 0.5rem;
  padding-bottom: 0.3rem;
  border-bottom: 1.5px solid var(--rule);
}
#dlg-detail h2 { font-size: 1.4rem; }
#dlg-detail #d-meta { margin: 0.15rem 0 1.25rem; }


/* ===============================================================
 * Dark console
 *
 * The office reads this on a monitor for hours; the tech screen stays
 * light because it is read on a phone outdoors. Locate orange carries
 * across both so the product still looks like one thing.
 * =============================================================== */

body[data-theme="dark"] {
  --ink:       #E8EAEC;
  --ink-2:     #9AA2AA;
  --ink-3:     #6C757D;
  --rule:      #333A41;
  --rule-soft: #262C32;
  --paper:     #15181B;
  --surface:   #1C2126;
  --chrome:    #0F1215;
  --locate:      #FF7A33;
  --locate-dark: #E45E14;
  --flag-red:    #E2564F;
  --flag-amber:  #D9930F;
}
body[data-theme="dark"] { --flag-green: #3DAE6B; }

body[data-theme="dark"] input,
body[data-theme="dark"] select,
body[data-theme="dark"] textarea {
  background: #12161A;
  color: var(--ink);
  border-color: var(--rule);
}
body[data-theme="dark"] dialog { background: var(--surface); color: var(--ink); }
body[data-theme="dark"] .empty { background: var(--surface); }
body[data-theme="dark"] .field-error { background: #2A1A1A; }
body[data-theme="dark"] .preview { background: #12161A; border-left-color: var(--locate); }
body[data-theme="dark"] .page-head { border-bottom-color: var(--rule); }


/* ---------- console chrome ---------- */

.console { margin-top: 0.25rem; }

.console-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 0.8rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  margin-bottom: 0.6rem;
  border-radius: var(--r-lg);
}

.console-bar select.assign-tech { width: auto; min-width: 13rem; padding: 0.45rem 0.6rem; }

.btn-primary.compact,
.btn-quiet.compact {
  margin-top: 0;
  width: auto;
  padding: 0.45rem 0.8rem;
  font-size: 0.9rem;
}

.sel-count { color: var(--locate); font-weight: 600; font-size: 0.9rem; }

.console-search {
  width: auto;
  min-width: 16rem;
  margin-left: auto;
  padding: 0.45rem 0.6rem;
}


/* ---------- the grid ---------- */

.grid-wrap {
  overflow: auto;
  max-height: calc(100dvh - 14rem);
  border: 1px solid var(--rule);
  background: var(--surface);
  border-radius: var(--r-lg);
}

table.grid {
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;      /* honour the colgroup widths */
  width: max-content;
  min-width: 100%;
  font-size: 0.82rem;
}

table.grid td:not(.wrap) {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

table.grid th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--chrome);
  color: var(--ink-2);
  text-align: left;
  font-weight: 600;
  padding: 0;
  border-bottom: 2px solid var(--rule);
  white-space: nowrap;
}

table.grid td {
  height: 2.9rem;                 /* consistent row rhythm */
  padding: 0.4rem 0.75rem;
  border-bottom: 1px solid var(--rule-soft);
  vertical-align: middle;
  line-height: 1.35;
}

table.grid tbody tr:nth-child(even) { background: rgba(255,255,255,0.02); }
table.grid tbody tr:hover { background: rgba(255,122,51,0.06); }
table.grid tbody tr.is-selected { background: rgba(255,122,51,0.12); }

button.sort {
  background: none;
  border: none;
  padding: 0;
  color: inherit;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
button.sort::after { content: ''; }
button.sort.asc::after  { content: ' ↑'; color: var(--locate); }
button.sort.desc::after { content: ' ↓'; color: var(--locate); }

.c-check { width: 2.1rem; }
.c-check input { width: 1.05rem; height: 1.05rem; accent-color: var(--locate); }
.strong { font-weight: 700; }
.center { text-align: center; }

table.grid td.wrap { color: var(--ink-2); }

/* The clamp lives on a div inside the cell. Putting it on the td
 * itself replaces display:table-cell and breaks the row. */
.clamp {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.35;
  max-height: calc(1.35em * 3);
}

/* resize handle sits on the right edge of each heading */
table.grid th { position: relative; }
.col-resize {
  position: absolute;
  top: 0; right: -3px; bottom: 0;
  width: 7px;
  cursor: col-resize;
  touch-action: none;
  z-index: 3;
}
.col-resize:hover { background: var(--locate); opacity: 0.5; }
body.resizing { cursor: col-resize; user-select: none; }

.btn-quiet.compact.on { border-color: var(--locate); color: var(--locate); }

/* Locate clearance not reached — you can dig, but know that you are
 * jumping the date. */
td.pending-locate {
  background: rgba(217, 147, 15, 0.22);
  color: #FFD98A;
  font-weight: 600;
}
body[data-theme="light"] td.pending-locate { background: #FFF3C4; color: #6B4E00; }

td.flagged  { color: var(--locate); font-weight: 700; }
td.overdue  { color: var(--flag-red); font-weight: 700; }

.link-btn {
  background: none;
  border: none;
  padding: 0;
  color: var(--locate);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.grid-empty { padding: 2.5rem; text-align: center; color: var(--ink-2); }

@media (max-width: 900px) {
  .console-search { margin-left: 0; width: 100%; }
  .grid-wrap { max-height: none; }
}


/* ---------- inline editing ----------
 *
 * Every cell an admin can change, they change in place. The affordance
 * is deliberately quiet — a dispatcher scanning 200 rows should not be
 * looking at 4,000 edit buttons — and only appears on hover.
 */

td.editable { cursor: text; }
td.editable:hover {
  box-shadow: inset 0 0 0 1px var(--rule);
  background: rgba(255,122,51,0.05);
}

/* The cell keeps its size and just marks itself as the one being
 * edited. The editor itself floats above the grid, so opening one
 * never re-lays out the row. */
td.editing {
  box-shadow: inset 0 0 0 2px var(--locate);
  background: rgba(255,122,51,0.08);
}

.cell-pop {
  position: fixed;
  z-index: 70;
  padding: 3px;
  background: var(--surface);
  border: 1px solid var(--locate);
  border-radius: var(--r-sm);
  box-shadow: 0 10px 28px rgba(0,0,0,0.5);
}

.cell-input {
  width: 100%;
  padding: 0.4rem 0.5rem;
  font-size: 0.85rem;
  border: none;
  border-radius: 3px;
  background: transparent;
  color: var(--ink);
}
.cell-input:focus { outline: none; }
textarea.cell-input { resize: vertical; min-height: 5rem; line-height: 1.4; }

.pop-hint {
  padding: 0.2rem 0.5rem 0.15rem;
  font-size: 0.7rem;
  color: var(--ink-3);
}

td.saving { opacity: 0.5; }
td.saved  { box-shadow: inset 0 0 0 2px var(--flag-green); }

td.muted { color: var(--ink-3); }


/* ---------- selection bar: appears only when it has something to say ---------- */

.sel-bar {
  display: none;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.8rem;
  margin-bottom: 0.6rem;
  background: rgba(255,122,51,0.10);
  border: 1px solid var(--locate);
  border-radius: var(--r-md);
}
.sel-bar.on { display: flex; }

.bar-hint { color: var(--ink-3); font-size: 0.85rem; }
.console-bar .bar-hint { margin-right: auto; }


/* ---------- uniform checkboxes ----------
 * One size everywhere, centred in the cell, big enough to hit without
 * aiming. The header box and the row boxes were different sizes.
 */

table.grid .c-check {
  padding: 0;
  text-align: center;
  vertical-align: middle;
}
table.grid .c-check input[type="checkbox"] {
  width: 18px;
  height: 18px;
  margin: 0;
  padding: 0;
  vertical-align: middle;
  accent-color: var(--locate);
  cursor: pointer;
}
table.grid thead .c-check { padding: 0.55rem 0; }


/* ---------- column heading: one control for sort and filter ---------- */

button.col-head {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  width: 100%;
  padding: 0.6rem 0.75rem;
  background: none;
  border: none;
  color: inherit;
  font: inherit;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
}
button.col-head:hover { color: var(--ink); background: rgba(255,255,255,0.04); }

.col-label { overflow: hidden; text-overflow: ellipsis; }

.sort-mark::after { color: var(--locate); font-size: 0.8em; }
.sort-mark.asc::after  { content: '↑'; }
.sort-mark.desc::after { content: '↓'; }

/* a filtered column says so without you opening it */
.filter-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--locate);
  flex: none;
}
table.grid th.filtered button.col-head { color: var(--locate); }


/* ---------- the column menu ---------- */

.col-menu {
  position: fixed;
  z-index: 60;
  min-width: 15rem;
  padding: 0.5rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  box-shadow: 0 12px 32px rgba(0,0,0,0.45);
}

.menu-sort { display: flex; gap: 0.3rem; margin-bottom: 0.5rem; }

.menu-item {
  flex: 1;
  padding: 0.4rem 0.6rem;
  background: none;
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  color: var(--ink);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
  text-align: center;
}
.menu-item:hover { border-color: var(--locate); }
.menu-item.on { border-color: var(--locate); color: var(--locate); }
.menu-item.quiet {
  width: 100%;
  margin-top: 0.5rem;
  border-style: dashed;
  color: var(--ink-2);
}

.menu-label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 0.3rem;
}

.menu-filter .f {
  width: 100%;
  padding: 0.4rem 0.5rem;
  font-size: 0.85rem;
  border-radius: var(--r-sm);
}
.menu-filter .f-range { display: flex; gap: 0.4rem; }
.f-labelled { flex: 1; display: block; }
.f-labelled span {
  display: block;
  font-size: 0.7rem;
  color: var(--ink-3);
  margin-bottom: 0.15rem;
}

.btn-quiet.compact[disabled] { opacity: 0.45; cursor: default; }


/* ---------- address editor ----------
 * Four fields pretending to be one. Displayed whole in the grid,
 * edited in parts, because parsing a typed address back into columns
 * is guesswork and city has to stay filterable.
 */

.addr-editor { min-width: 22rem; }

.addr-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}
.addr-grid .span-2 { grid-column: 1 / -1; }
.addr-grid .f { width: 100%; padding: 0.4rem 0.5rem; font-size: 0.85rem; }


/* ---------- job detail ----------
 * Work order first, invoice second. Two questions in the order you
 * would actually ask them.
 */

#dlg-detail { width: min(100%, 46rem); max-height: 88vh; overflow: auto; }

.facts {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.3rem 1.25rem;
  margin: 0 0 0.5rem;
  font-size: 0.9rem;
}
.facts dt { color: var(--ink-3); }
.facts dd { margin: 0; }

.note-label {
  margin-top: 0.7rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.note-body {
  margin: 0.15rem 0 0;
  padding: 0.5rem 0.7rem;
  background: var(--paper);
  border-left: 3px solid var(--rule);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: 0.9rem;
  white-space: pre-wrap;
}

table.detail-lines {
  width: 100%;
  border-collapse: collapse;
  margin-top: 0.5rem;
  font-size: 0.9rem;
}
table.detail-lines th {
  text-align: left;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding: 0.3rem 0.5rem;
  border-bottom: 1.5px solid var(--rule);
}
table.detail-lines td {
  padding: 0.45rem 0.5rem;
  border-bottom: 1px solid var(--rule-soft);
}
table.detail-lines .num { text-align: right; font-variant-numeric: tabular-nums; }
table.detail-lines tfoot td {
  border-top: 1.5px solid var(--rule);
  border-bottom: none;
  font-weight: 700;
}
table.detail-lines td.state { font-weight: 600; font-size: 0.85rem; }
table.detail-lines td.state.paid        { color: var(--flag-green); }
table.detail-lines td.state.unpaid,
table.detail-lines td.state.short       { color: var(--flag-red); }
table.detail-lines td.state.over        { color: var(--flag-amber); }
table.detail-lines td.state.not_checked { color: var(--ink-3); }

/* archive grid */
td.codes { font-variant-numeric: tabular-nums; color: var(--ink-2); }
td.amount-cell {
  text-align: right;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}


/* ---------- photo capture ----------
 * On a phone these open the camera directly. Required ones are marked,
 * and a filled slot turns green so a tech can see at a glance what is
 * still outstanding without reading a list.
 */

.req { color: var(--flag-red); font-weight: 700; }
.hint.small { font-size: 0.8rem; margin: 0.35rem 0 0; }

.photo-set {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 0.6rem;
  margin-top: 0.5rem;
}

.photo-field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.7rem;
  background: var(--paper);
  border: 1.5px dashed var(--rule);
  border-radius: var(--r-md);
}
.photo-field label { margin: 0; font-size: 0.85rem; }
.photo-field.has-photo {
  border-style: solid;
  border-color: var(--flag-green);
}

.photo-input {
  width: 100%;
  padding: 0.3rem;
  font-size: 0.8rem;
  border: none;
  background: none;
}
.photo-input::file-selector-button {
  padding: 0.35rem 0.7rem;
  margin-right: 0.5rem;
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 0.8rem;
  cursor: pointer;
}
.photo-input::file-selector-button:hover { border-color: var(--locate); }

.photo-name { font-size: 0.78rem; color: var(--ink-3); word-break: break-all; }
.photo-field.has-photo .photo-name { color: var(--flag-green); }
.photo-help { font-size: 0.75rem; color: var(--ink-3); }

#dlg-invoice { width: min(100%, 44rem); max-height: 90vh; overflow: auto; }


/* ---------- account menu ---------- */

.who-btn {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.35rem 0.6rem;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.who-btn:hover { border-color: #3A4148; }
.who-btn .caret {
  width: 0; height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  opacity: 0.7;
}

.who-menu {
  position: fixed;
  z-index: 80;
  min-width: 15rem;
  padding: 0.75rem;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  box-shadow: 0 14px 36px rgba(0,0,0,0.45);
}

.who-menu-head {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding-bottom: 0.6rem;
  margin-bottom: 0.6rem;
  border-bottom: 1px solid var(--rule-soft);
}
.who-menu-head strong { font-size: 0.95rem; }
#wm-email { font-size: 0.82rem; color: var(--ink-2); word-break: break-all; }
#wm-role {
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--locate);
  font-weight: 700;
}

.theme-picker { display: flex; gap: 0.3rem; margin-bottom: 0.3rem; }
.theme-picker .menu-item { padding: 0.35rem 0.4rem; font-size: 0.8rem; }

.field-ok {
  margin: 0.75rem 0 0;
  padding: 0.6rem 0.7rem;
  background: rgba(61,174,107,0.12);
  border-left: 4px solid var(--flag-green);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  color: var(--flag-green);
  font-size: 0.9rem;
}

#dlg-password { width: min(100%, 24rem); }

/* the light theme needs the console rules too, now that anyone can
 * choose it */
body[data-theme="light"] table.grid tbody tr:nth-child(even) { background: rgba(0,0,0,0.02); }
body[data-theme="light"] table.grid tbody tr:hover { background: rgba(242,101,34,0.07); }
body[data-theme="light"] table.grid tbody tr.is-selected { background: rgba(242,101,34,0.14); }
body[data-theme="light"] table.grid th { background: #EFECE6; color: var(--ink-2); }
body[data-theme="light"] button.col-head:hover { background: rgba(0,0,0,0.04); }
body[data-theme="light"] td.flagged { color: var(--locate-dark); }
body[data-theme="light"] .sel-bar { background: rgba(242,101,34,0.10); }
body[data-theme="light"] .who-menu { box-shadow: 0 14px 36px rgba(0,0,0,0.18); }
body[data-theme="light"] .col-menu,
body[data-theme="light"] .cell-pop { box-shadow: 0 10px 28px rgba(0,0,0,0.18); }


/* ---------- the job being invoiced ----------
 * A tech is standing in a front yard with a phone. Which job this is
 * should not be a single number in a heading they have to trust.
 */

.job-card {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2rem;
  align-items: flex-start;
  justify-content: space-between;
  padding: 0.85rem 1rem;
  margin: 0.5rem 0 1rem;
  background: var(--paper);
  border-left: 4px solid var(--locate);
  border-radius: 0 var(--r-md) var(--r-md) 0;
}

.job-card-main { min-width: 0; }

.job-card-number {
  display: block;
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1.1;
}

.job-card-address {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.92rem;
  color: var(--ink-2);
}

.job-card-facts {
  display: grid;
  grid-template-columns: max-content max-content;
  gap: 0.15rem 0.75rem;
  margin: 0;
  font-size: 0.82rem;
}
.job-card-facts dt { color: var(--ink-3); }
.job-card-facts dd { margin: 0; font-weight: 600; }

@media (max-width: 560px) {
  .job-card-facts { grid-template-columns: max-content 1fr; }
}


/* A tech's board is a short queue, not a dense console. Give the rows
 * room and let the age carry weight. */
body[data-theme] .console .btn-primary.compact { padding: 0.4rem 0.9rem; }

@media (max-width: 640px) {
  table.grid { font-size: 0.9rem; }
  table.grid td { height: auto; padding: 0.7rem 0.75rem; }
}


/* ---------- focus ----------
 * The two questions a dispatcher asks every morning. Today is what is
 * late or clear to dig; tomorrow is the half you can still do
 * something about, which is why it gets equal weight rather than
 * being buried in a filter.
 */

.focus {
  display: grid;
  /* Fixed columns rather than auto-fit: two cards sized to their own
   * content end up different widths, which reads as one mattering
   * more than the other. */
  grid-template-columns: repeat(2, minmax(0, 17rem));
  gap: 0.6rem;
  margin-bottom: 0.7rem;
}

.focus-card {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.6rem 0.8rem;
  min-height: 5.5rem;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 4px solid var(--ink-3);
  border-radius: var(--r-md);
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.focus-card:hover:not([disabled]) { border-color: var(--locate); }
.focus-card.on {
  border-color: var(--locate);
  border-left-color: var(--locate);
  background: rgba(255,122,51,0.07);
}
.focus-card[disabled] { cursor: default; opacity: 0.6; }

.focus-card.today    { border-left-color: var(--flag-red); }
.focus-card.tomorrow { border-left-color: var(--flag-amber); }
.focus-card.today[disabled],
.focus-card.tomorrow[disabled] { border-left-color: var(--rule); }

.focus-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
.focus-title { font-weight: 700; font-size: 0.9rem; }
.focus-count {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1;
}
.focus-card.today .focus-count    { color: var(--flag-red); }
.focus-card.tomorrow .focus-count { color: var(--flag-amber); }
.focus-card[disabled] .focus-count { color: var(--ink-3); }

.focus-parts { margin: 0; padding: 0; list-style: none; font-size: 0.8rem; }
.focus-parts-one { font-size: 0.8rem; color: var(--ink-2); }
.focus-parts li { color: var(--ink-2); }
.focus-parts strong { color: var(--ink); }

.focus-sample {
  font-size: 0.76rem;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.focus-none   { font-size: 0.8rem; color: var(--ink-3); }
.focus-action {
  margin-top: auto;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--locate);
}
.focus-card[disabled] .focus-action { display: none; }

.bar-hint.focused { color: var(--locate); font-weight: 600; }


/* ---------- planned route ----------
 * Two days side by side. Cards big enough to hit with a thumb, drag
 * handles for a mouse, arrows for everyone else.
 */

.route-days {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  align-items: start;
}

.route-day {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.route-day-head {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  padding: 0.8rem 1rem;
  border-bottom: 2px solid var(--rule);
  background: var(--paper);
}
.route-day-head h3 { font-size: 1.1rem; }
.route-day-date { color: var(--ink-3); font-size: 0.85rem; margin-right: auto; }
.route-count { color: var(--locate); font-weight: 700; font-size: 0.85rem; }

.route-list { padding: 0.6rem; min-height: 6rem; display: flex; flex-direction: column; gap: 0.5rem; }

.route-empty {
  margin: 0;
  padding: 1.5rem 1rem;
  text-align: center;
  color: var(--ink-3);
  font-size: 0.9rem;
}

.route-card {
  display: grid;
  grid-template-columns: auto auto 1fr;
  grid-template-rows: auto auto;
  gap: 0.15rem 0.6rem;
  align-items: start;
  padding: 0.7rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
}
.route-card.is-dragging { opacity: 0.35; }

.route-grip {
  grid-row: 1 / 3;
  align-self: center;
  padding: 0.4rem 0.2rem;
  background: none;
  border: none;
  color: var(--ink-3);
  font-size: 0.9rem;
  letter-spacing: -2px;
  cursor: grab;
  touch-action: none;      /* the drag must win over the scroll */
}
.route-grip:active { cursor: grabbing; }

.route-stop {
  grid-row: 1 / 3;
  align-self: center;
  display: grid;
  place-items: center;
  width: 1.9rem; height: 1.9rem;
  background: var(--locate);
  color: #fff;
  border-radius: 50%;
  font-weight: 700;
  font-size: 0.9rem;
}

.route-body { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.route-job  { font-family: 'Barlow Semi Condensed', sans-serif;
              font-size: 1.15rem; font-weight: 700; }
.route-addr { font-size: 0.85rem; color: var(--ink-2); }
.route-phone { font-size: 0.85rem; color: var(--locate); width: max-content; }

.route-tags { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.2rem; }
.route-tag {
  padding: 0.1rem 0.4rem;
  font-size: 0.72rem;
  font-weight: 700;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--ink-2);
}
.route-tag.warn { border-color: var(--flag-amber); color: var(--flag-amber); }

.route-acts {
  grid-column: 3;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: 0.4rem;
}
.route-act {
  min-width: 2.1rem;
  padding: 0.3rem 0.5rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  color: var(--ink);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}
.route-act:hover:not([disabled]) { border-color: var(--locate); }
.route-act[disabled] { opacity: 0.35; cursor: default; }
.route-act.wide { min-width: 0; }
.route-act.danger:hover { border-color: var(--flag-red); color: var(--flag-red); }

.route-gone { color: var(--ink-3); font-size: 0.85rem; }

.route-ghost {
  position: fixed;
  z-index: 90;
  pointer-events: none;
  opacity: 0.9;
  box-shadow: 0 12px 30px rgba(0,0,0,0.4);
  transform: rotate(-1deg);
}

.route-placeholder {
  border: 2px dashed var(--locate);
  border-radius: var(--r-md);
  background: rgba(255,122,51,0.06);
}

.toast {
  position: fixed;
  left: 50%;
  bottom: 1.5rem;
  transform: translate(-50%, 1rem);
  z-index: 95;
  padding: 0.7rem 1.1rem;
  background: var(--chrome);
  color: #fff;
  border-radius: 999px;
  box-shadow: 0 10px 28px rgba(0,0,0,0.35);
  font-size: 0.9rem;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.toast.on { opacity: 1; transform: translate(-50%, 0); }

@media (max-width: 720px) {
  .route-days { grid-template-columns: 1fr; }
}


/* ---------- grouped navigation ----------
 * A tech's work is one thing seen two ways, so it sits under one
 * heading that says which view you are in.
 */

.nav button.nav-group {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.nav button.nav-group .caret {
  width: 0; height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  opacity: 0.7;
}

.nav-menu {
  position: fixed;
  z-index: 80;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-width: 11rem;
  padding: 0.4rem;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  box-shadow: 0 12px 32px rgba(0,0,0,0.4);
}
.nav-menu .menu-item { text-align: left; }


/* ---------- my pay ----------
 * Two questions: how much am I owed, and when does each week land.
 * The expected date is the number a tech actually wants — not when
 * it was processed, when it should be in the bank.
 */

.pay-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 0.7rem;
  margin-bottom: 0.9rem;
}

.pay-card {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 1rem 1.1rem;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 4px solid var(--rule);
  border-radius: var(--r-md);
  color: inherit;
  font: inherit;
}
button.pay-card { cursor: pointer; }
button.pay-card:hover:not([disabled]) { border-color: var(--locate); }
button.pay-card[disabled] { cursor: default; }
.pay-card.owed { border-left-color: var(--flag-red); }
.pay-card.owed[disabled] { border-left-color: var(--flag-green); }

.pay-figure {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 2.4rem;
  font-weight: 700;
  line-height: 1;
}
.pay-card.owed .pay-figure { color: var(--flag-red); }
.pay-card.owed[disabled] .pay-figure { color: var(--flag-green); }
.pay-label { font-weight: 600; font-size: 0.9rem; }
.pay-sub   { font-size: 0.82rem; color: var(--ink-3); }

.pay .console-bar { align-items: flex-end; }
.pay .console-bar .f-labelled { flex: none; width: 10rem; }
.pay .console-bar .bar-hint { margin-left: auto; }

.pay-weeks { display: flex; flex-direction: column; gap: 0.8rem; }

.pay-week {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.pay-week-head {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.8rem 1rem;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}

.pay-week-dates { display: flex; flex-direction: column; gap: 0.1rem; }
.pay-week-range { font-weight: 700; font-size: 1.02rem; }
.pay-week-expect { font-size: 0.85rem; color: var(--locate); font-weight: 600; }

.pay-week-totals { display: flex; gap: 1.75rem; }
.pay-fig { display: flex; flex-direction: column-reverse; }
.pay-fig .v {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 1.5rem; font-weight: 700; line-height: 1;
}
.pay-fig .k { font-size: 0.75rem; color: var(--ink-3); font-weight: 600; }
.pay-fig.good .v { color: var(--flag-green); }
.pay-fig.part .v { color: var(--flag-amber); }
.pay-fig.none .v { color: var(--ink-3); }

.pay-week table.detail-lines { margin: 0; }
.pay-week table.detail-lines th { padding-left: 1rem; }
.pay-week table.detail-lines td { padding-left: 1rem; }

#dlg-outstanding { width: min(100%, 44rem); max-height: 85vh; overflow: auto; }


/* ---------- photos in the detail view ----------
 * Thumbnails that open full size in a new tab. A tech looking back at
 * a job wants to check what they photographed, not squint at it.
 */

.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: 0.6rem;
  margin: 0.35rem 0 0.9rem;
}

.photo-thumb {
  margin: 0;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  overflow: hidden;
}
.photo-thumb a { display: block; line-height: 0; }
.photo-thumb img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
}
.photo-thumb:hover { border-color: var(--locate); }

.photo-thumb figcaption {
  padding: 0.35rem 0.5rem;
  font-size: 0.75rem;
  color: var(--ink-2);
  line-height: 1.3;
}

.photo-missing {
  display: grid;
  place-items: center;
  aspect-ratio: 4 / 3;
  color: var(--ink-3);
  font-size: 0.8rem;
}

table.detail-lines .link-btn { font: inherit; font-weight: 700; }

td.amount-cell.ok      { color: var(--flag-green); }
table.grid td.state.paid        { color: var(--flag-green); font-weight: 600; }
table.grid td.state.unpaid,
table.grid td.state.short       { color: var(--flag-red); font-weight: 600; }
table.grid td.state.over        { color: var(--flag-amber); font-weight: 600; }
table.grid td.state.not_checked { color: var(--ink-3); }


/* ---------- payroll ---------- */

.panel {
  padding: 1rem 1.1rem 1.2rem;
  margin-bottom: 0.9rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
}
.panel > .section-head:first-child { margin-top: 0; }

.import-drop {
  padding: 1.1rem;
  border: 2px dashed var(--rule);
  border-radius: var(--r-md);
  text-align: center;
}
.import-drop label {
  display: block;
  margin: 0 0 0.5rem;
  font-size: 0.95rem;
  color: var(--ink-2);
  cursor: pointer;
}
.import-drop input[type="file"] { width: auto; border: none; background: none; }
.import-drop input[type="file"]::file-selector-button {
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}
.import-drop input[type="file"]::file-selector-button:hover { border-color: var(--locate); }

.import-preview { margin-top: 0.9rem; }

.import-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 2rem;
  padding: 0.9rem 0 0.4rem;
}

.import-preview table.detail-lines { margin-top: 0.6rem; }
.import-preview .btn-primary { width: auto; }

.payroll .console-bar { align-items: flex-end; margin-top: 0.6rem; }
.payroll .console-bar .f-labelled { flex: none; width: 11rem; }
.payroll .console-bar .bar-hint { margin-left: auto; }


/* ---------- team ---------- */

.person {
  display: grid;
  /* Name, role, then whatever needs acting on. Most rows carry
   * nothing in that third column, and a mostly-empty row is the point:
   * it means there is nothing to do. */
  grid-template-columns: minmax(13rem, max-content) max-content minmax(0, 1fr) auto;
  gap: 0.4rem 1.25rem;
  justify-content: start;
  align-items: center;
  padding: 0.6rem 0.9rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
}
.person.inactive { opacity: 0.55; }

.person-main { display: flex; flex-direction: column; min-width: 0; }
.person-name { font-weight: 700; }
.person-email {
  font-size: 0.82rem;
  color: var(--ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
}

.person-roles { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.role-tag {
  padding: 0.12rem 0.45rem;
  font-size: 0.72rem;
  font-weight: 700;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--ink-2);
}
.role-tag.admin, .role-tag.manager, .role-tag.office {
  border-color: var(--locate); color: var(--locate);
}
.role-tag.lead { border-color: var(--flag-green); color: var(--flag-green); }
.role-tag.off  { border-color: var(--flag-red);   color: var(--flag-red); }

.person-detail,
.person-counts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.9rem;
  font-size: 0.82rem;
  color: var(--ink-2);
}
.person-counts { color: var(--ink-3); white-space: nowrap; }

.role-picker { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-bottom: 0.3rem; }
.role-picker .menu-item { flex: none; padding: 0.35rem 0.7rem; }

.tech-fields {
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--rule-soft);
}

#dlg-person { width: min(100%, 32rem); max-height: 90vh; overflow: auto; }

@media (max-width: 820px) {
  .person { grid-template-columns: 1fr auto; }
  .person-roles, .person-detail, .person-counts { grid-column: 1 / -1; }
}


/* ---------- payroll queue and paystubs ---------- */

.queue-amount {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 1.5rem;
  font-weight: 700;
  text-align: right;
  white-space: nowrap;
}

.warn-text { color: var(--flag-amber); font-weight: 600; }

.pay-fig.net .v  { color: var(--locate); }
.pay-fig.neg .v  { color: var(--flag-red); }

table.detail-lines td.neg { color: var(--flag-red); }

.line-kind {
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}
.line-detail { color: var(--flag-amber); font-size: 0.82rem; }

.adj-form {
  margin-top: 1rem;
  padding: 0.8rem 0.9rem;
  background: var(--paper);
  border: 1px dashed var(--rule);
  border-radius: var(--r-md);
}
.adj-row {
  display: grid;
  grid-template-columns: 2fr 1fr 1.5fr auto;
  gap: 0.45rem;
  align-items: center;
}
.adj-row .f { width: 100%; padding: 0.4rem 0.5rem; font-size: 0.85rem; }
.adj-row .btn-quiet { margin: 0; }

#dlg-stub { width: min(96vw, 56rem); max-height: 90vh; overflow: auto; }
#dlg-stub table.detail-lines { font-size: 0.85rem; }
#dlg-stub table.detail-lines th,
#dlg-stub table.detail-lines td { padding: 0.4rem 0.45rem; }

@media (max-width: 720px) {
  .adj-row { grid-template-columns: 1fr; }
}


/* ---------- claims comparison ---------- */

.claims-head {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  justify-content: space-between;
}
.claims-head .section-head { margin: 0 0 0.5rem; flex: 1; }

table.detail-lines td.state.different_code   { color: var(--flag-amber); font-weight: 600; }
table.detail-lines td.state.paid_less        { color: var(--flag-red); font-weight: 600; }
table.detail-lines td.state.paid_more        { color: var(--flag-green); font-weight: 600; }
table.detail-lines td.state.not_invoiced     { color: var(--ink-3); }
table.detail-lines td.state.awaiting_payment { color: var(--ink-3); }
table.detail-lines td.state.matches          { color: var(--flag-green); }

#dlg-ff { width: min(100%, 40rem); max-height: 90vh; overflow: auto; }


/* ---------- fulfillment ---------- */

.fulfillment .console-bar { margin-bottom: 0.8rem; }
.fulfillment .import-stats { padding-top: 0; margin-bottom: 0.8rem; }
.fulfillment table.detail-lines { margin-top: 0.4rem; }
.fulfillment .empty { margin-top: 0.6rem; }


/* the credential block in the person editor */
#dlg-person .grid-2 { gap: 0 0.75rem; }
#dlg-person .section-head { margin-top: 1rem; }
.console-bar .warn-text { margin-left: 0.75rem; }


/* ---------- welcome ----------
 * A tech's own details. Empty fields are left out rather than shown
 * blank, so the page never looks half filled in.
 */

.welcome {
  display: grid;
  grid-template-columns: 15rem 1fr;
  gap: 1.5rem;
  align-items: start;
  padding: 1.25rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
}

.welcome-photo {
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--paper);
}
.welcome-photo img {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
}
.welcome-initials {
  display: grid;
  place-items: center;
  aspect-ratio: 3 / 4;
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 4rem;
  font-weight: 700;
  color: var(--ink-3);
}

.welcome-table { width: 100%; border-collapse: collapse; }
.welcome-table th,
.welcome-table td {
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--rule-soft);
  text-align: left;
  font-size: 0.95rem;
}
.welcome-table th {
  width: 14rem;
  background: var(--paper);
  color: var(--ink-2);
  font-weight: 600;
}
.welcome-table a { color: var(--locate); }
.welcome-table td.badge-expired { color: var(--flag-red); }

/* badge photo in the person editor */
.badge-field {
  display: grid;
  grid-template-columns: 6rem 1fr;
  gap: 0.75rem;
  align-items: center;
  margin-bottom: 0.4rem;
}
.badge-preview {
  display: grid;
  place-items: center;
  aspect-ratio: 3 / 4;
  border: 1px dashed var(--rule);
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--paper);
}
.badge-preview img { width: 100%; height: 100%; object-fit: cover; }

@media (max-width: 700px) {
  .welcome { grid-template-columns: 1fr; }
  .welcome-photo { max-width: 14rem; }
  .welcome-table th { width: 9rem; }
}


/* ---------- pay tables ----------
 * Columns sized to their content rather than sharing the width out
 * evenly. Text left, money right, and the two of them close enough
 * together to read as one row.
 */

.pay-week table.detail-lines,
#dlg-outstanding table.detail-lines,
.fulfillment table.detail-lines {
  table-layout: fixed;
  width: 100%;
}

.pay-week table.detail-lines th:nth-child(1),
.fulfillment table.detail-lines th:nth-child(1) { width: 7rem; }   /* job */
.pay-week table.detail-lines th:nth-child(2),
.fulfillment table.detail-lines th:nth-child(2) { width: 7rem; }   /* completed */
.pay-week table.detail-lines th:nth-child(3),
.fulfillment table.detail-lines th:nth-child(3) { width: 9rem; }   /* line */
.pay-week table.detail-lines th:nth-child(4),
.fulfillment table.detail-lines th:nth-child(4) { width: 6.5rem; } /* your code */
.pay-week table.detail-lines th:nth-child(5),
.fulfillment table.detail-lines th:nth-child(5) { width: 6.5rem; } /* paid as */
.pay-week table.detail-lines th:nth-child(6),
.fulfillment table.detail-lines th:nth-child(6) { width: 7rem; }   /* you billed */
.pay-week table.detail-lines th:nth-child(7),
.fulfillment table.detail-lines th:nth-child(7) { width: 7.5rem; } /* you were paid */
.pay-week table.detail-lines th:nth-child(8),
.fulfillment table.detail-lines th:nth-child(8) { width: auto; }   /* status */

/* the two codes read as a pair, so centre them between the labels
 * either side */
.pay-week table.detail-lines td:nth-child(4),
.pay-week table.detail-lines td:nth-child(5),
.pay-week table.detail-lines th:nth-child(4),
.pay-week table.detail-lines th:nth-child(5),
.fulfillment table.detail-lines td:nth-child(4),
.fulfillment table.detail-lines td:nth-child(5) { text-align: center; }

.pay-week table.detail-lines td,
.fulfillment table.detail-lines td {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* the money columns sit next to each other rather than at opposite
 * ends of the screen */
.pay-week table.detail-lines td.num,
.fulfillment table.detail-lines td.num { padding-right: 1.25rem; }

.pay-summary { max-width: 46rem; }

@media (max-width: 860px) {
  .pay-week table.detail-lines,
  .fulfillment table.detail-lines { table-layout: auto; }
  .pay-week table.detail-lines th:nth-child(2),
  .pay-week table.detail-lines td:nth-child(2) { display: none; }
}


/* three cards across, so the statements picker sits alongside the
 * two figures rather than taking a band of its own */
.pay-summary {
  max-width: none;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}
.pay-summary .pay-card:last-child .pay-figure { color: var(--ink-2); }
button.pay-card:hover:not([disabled]) { border-left-color: var(--locate); }

#dlg-statements { width: min(100%, 32rem); max-height: 85vh; overflow: auto; }
#dlg-statements .rows { gap: 0.4rem; }


/* ---------- recurring pay ---------- */

.person-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; }

#dlg-recurring { width: min(100%, 40rem); max-height: 90vh; overflow: auto; }
#dlg-recurring .grid-3 { grid-template-columns: 1fr 1fr 1fr; }
#dlg-recurring table.detail-lines { margin-bottom: 0.5rem; }

table.detail-lines tr.is-done td { opacity: 0.5; }


/* ---------- loans ---------- */

.loan-total {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}
.loan-total .v {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 1.7rem;
  font-weight: 700;
  color: var(--flag-red);
}
.loan-total .k { color: var(--ink-2); font-size: 0.88rem; }

.loan-note {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  margin: 0.75rem 0;
  padding: 0.7rem 0.9rem;
  background: rgba(194,43,43,0.08);
  border-left: 4px solid var(--flag-red);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: 0.9rem;
}
.loan-note span { color: var(--ink-2); font-size: 0.85rem; }

.dlg-actions.inline { justify-content: flex-start; margin-top: 0.5rem; }

.adj-row.two { grid-template-columns: 1fr auto; }
table.detail-lines td.line-kind { font-size: 0.68rem; }


/* ---------- early pay ----------
 * The outstanding jobs sit under the statement as a list with a
 * button each: the decision is per job, so the list is the interface.
 */

.advance-box {
  margin-top: 1.25rem;
  padding: 0.9rem 1rem 1rem;
  background: var(--paper);
  border: 1px dashed var(--rule);
  border-radius: var(--r-md);
}
.advance-box .section-head { margin: 0 0 0.4rem; border-bottom: none; }
.advance-box table.detail-lines { margin-top: 0.2rem; }
.advance-box .btn-quiet.compact { padding: 0.25rem 0.6rem; font-size: 0.8rem; }

/* a missed job is a thing to act on, so it does not look like a
 * neutral list */
.advance-box.has-missed {
  border-style: solid;
  border-color: var(--flag-amber);
  background: rgba(217,147,15,0.06);
}
.advance-box.has-missed .section-head { color: var(--flag-amber); }


/* ---------- payroll widths ----------
 * Panels, not a grid. Tables inside them size to their content rather
 * than sharing the width out, so a name and its amount stay together.
 */

.payroll .panel table.detail-lines,
#dlg-stub table.detail-lines,
#dlg-recurring table.detail-lines {
  table-layout: fixed;
  width: 100%;
}

/* payroll queue: name, detail, amount, button */
.payroll .person {
  grid-template-columns: minmax(10rem, 1.1fr) minmax(12rem, 1.4fr) auto auto;
}

/* the per-tech batch breakdown */
#dlg-detail table.detail-lines th:nth-child(1) { width: 34%; }
#dlg-detail table.detail-lines th:nth-child(2) { width: 8%; }
#dlg-detail table.detail-lines th:nth-child(3),
#dlg-detail table.detail-lines th:nth-child(4) { width: 12%; }

/* paystub lines: type, description, job, qty, billed, paid, amount, act */
#dlg-stub table.detail-lines th:nth-child(1) { width: 4.5rem; }
#dlg-stub table.detail-lines th:nth-child(3) { width: 5.5rem; }
#dlg-stub table.detail-lines th:nth-child(4) { width: 3rem; }
#dlg-stub table.detail-lines th:nth-child(5),
#dlg-stub table.detail-lines th:nth-child(6) { width: 6rem; }
#dlg-stub table.detail-lines th:nth-child(7) { width: 6rem; }
#dlg-stub table.detail-lines th:nth-child(8) { width: 5rem; }

/* a line where billed and paid disagree */
#dlg-stub table.detail-lines tr.mismatch td { background: rgba(217,147,15,0.07); }
#dlg-stub table.detail-lines td.muted { color: var(--ink-3); }

#dlg-stub table.detail-lines td:nth-child(2) {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* the missed-jobs list inside a draft */
.advance-box table.detail-lines { table-layout: fixed; width: 100%; }
.advance-box th:nth-child(1) { width: 6.5rem; }
.advance-box th:nth-child(2) { width: 7rem; }
.advance-box th:nth-child(4) { width: 5.5rem; }
.advance-box th:nth-child(5) { width: 10rem; }
.advance-box th:nth-child(6) { width: 7rem; }
.advance-box th:nth-child(7) { width: 6.5rem; }

.import-stats { max-width: 46rem; }


/* ---------- payroll cards ---------- */

.payroll .pay-summary {
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  max-width: 62rem;
  margin-bottom: 1rem;
}
.payroll .pay-card { padding: 0.85rem 1rem; }
.payroll .pay-figure { font-size: 1.9rem; }
.payroll .pay-card.owed .pay-figure { color: var(--locate); }
.payroll .pay-card.qb { border-left-color: var(--flag-amber); }
.payroll .pay-card.qb .pay-figure { color: var(--flag-amber); }
.payroll .pay-card.qb[disabled] {
  border-left-color: var(--flag-green);
}
.payroll .pay-card.qb[disabled] .pay-figure { color: var(--flag-green); }

.payout-total {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--locate);
  margin-right: auto;
}

#dlg-payouts { width: min(100%, 50rem); max-height: 88vh; overflow: auto; }
#dlg-payouts .console-bar { margin-top: 0.8rem; align-items: center; }
#dlg-payouts .console-bar .f { width: 12rem; padding: 0.4rem 0.5rem; }
#dlg-payouts table.detail-lines th:nth-child(1) { width: 2rem; }
#dlg-payouts input[type="checkbox"] { width: 17px; height: 17px; accent-color: var(--locate); }

#dlg-allstubs { width: min(100%, 34rem); max-height: 85vh; overflow: auto; }


table.detail-lines td.state.agreed         { color: var(--flag-green); }
table.detail-lines td.state.not_paid       { color: var(--flag-red); font-weight: 600; }
table.detail-lines td.state.not_invoiced   { color: var(--flag-amber); font-weight: 600; }
table.detail-lines td.state.short_paid     { color: var(--flag-red); font-weight: 600; }
table.detail-lines td.state.over_paid      { color: var(--flag-amber); }


/* ---------- paystub lines: centred ----------
 * Left-aligned columns leave a value stranded at the far edge of a
 * wide cell, so the eye has to travel to pair a job with its money.
 * Centring keeps each value under its own heading.
 */

#dlg-stub table.detail-lines th,
#dlg-stub table.detail-lines td { text-align: center; }

/* description stays left: it is a sentence, not a value, and centring
 * ragged text is harder to read, not easier */
#dlg-stub table.detail-lines th:nth-child(2),
#dlg-stub table.detail-lines td:nth-child(2) { text-align: left; }

/* money keeps its digits lined up under the heading */
#dlg-stub table.detail-lines td.num {
  text-align: center;
  font-variant-numeric: tabular-nums;
  padding-right: 0.45rem;
}

/* the same treatment for the two lists inside a draft */
.advance-box table.detail-lines th,
.advance-box table.detail-lines td,
.advance-box table.detail-lines td.num { text-align: center; }

#dlg-payouts table.detail-lines th,
#dlg-payouts table.detail-lines td,
#dlg-payouts table.detail-lines td.num { text-align: center; }
#dlg-payouts table.detail-lines th:nth-child(2),
#dlg-payouts table.detail-lines td:nth-child(2) { text-align: left; }

#dlg-recurring table.detail-lines th,
#dlg-recurring table.detail-lines td,
#dlg-recurring table.detail-lines td.num { text-align: center; }
#dlg-recurring table.detail-lines th:nth-child(1),
#dlg-recurring table.detail-lines td:nth-child(1) { text-align: left; }


/* a draft is work in progress, so it reads as unfinished rather than
 * as another queued item */
.payroll .person.draft-row {
  border-left: 4px solid var(--locate);
  background: rgba(255,122,51,0.05);
}
.payroll .menu-label { margin: 0.75rem 0 0.35rem; }
.payroll .menu-label:first-of-type { margin-top: 0; }


/* ---------- team rows ----------
 * Labelled facts in a tight grid. A bare 0133 next to a bare 2 tells
 * you nothing until you know which is the tech number and which is
 * the tier.
 */

.person-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 1.1rem;
  justify-content: flex-start;
}

.fact { display: flex; flex-direction: column; line-height: 1.2; }
.fact-k {
  font-size: 0.62rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.fact-v { font-size: 0.85rem; font-weight: 600; white-space: nowrap; }

.fact.warn .fact-v { color: var(--flag-amber); }
.fact.bad  .fact-k,
.fact.bad  .fact-v { color: var(--flag-red); }

.team .console-bar .f {
  flex: 1;
  max-width: 26rem;
  padding: 0.4rem 0.6rem;
}
/* Create User sits at the right: the search is what you reach for
 * most, so it gets the near edge. */
.team .console-bar .btn-primary { order: 9; margin-left: auto; }
.team .console-bar .bar-hint { order: 5; }
.team .console-bar .warn-text { order: 6; }
.team .rows { gap: 0.4rem; }

/* the adjustments dialog picks its own tech now */
#dlg-recurring #rec-tech { margin-bottom: 0.25rem; }

@media (max-width: 820px) {
  .person { grid-template-columns: 1fr auto; }
  .person-roles, .person-facts { grid-column: 1 / -1; }
}


/* ---------- adjustments dialog ---------- */

#dlg-recurring { width: min(96vw, 52rem); max-height: 90vh; overflow: auto; }
#dlg-recurring table.detail-lines { table-layout: auto; }
#dlg-recurring th:nth-child(1) { width: 12rem; }
#dlg-recurring #adj-form {
  margin-top: 0.9rem;
  padding: 0.9rem 1rem 0.4rem;
  background: var(--paper);
  border: 1px dashed var(--rule);
  border-radius: var(--r-md);
}
#dlg-recurring #adj-form .section-head { margin-top: 0; border-bottom: none; }

/* a card that opens something rather than reporting a figure */
.pay-card.plain { justify-content: center; min-height: 4.5rem; }
.pay-card.plain .pay-label { font-size: 1.05rem; }


/* ---------- pay periods ----------
 * A week per row, with its state said plainly. This is a list of what
 * is left to do, so the state has to be readable without counting.
 */

.period {
  display: grid;
  grid-template-columns: minmax(12rem, auto) minmax(14rem, 1fr) auto;
  gap: 0.4rem 1.25rem;
  align-items: center;
  width: 100%;
  padding: 0.7rem 0.9rem;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 4px solid var(--rule);
  border-radius: var(--r-md);
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.period:hover { border-color: var(--locate); }

.period.needs_import { border-left-color: var(--ink-3); }
.period.needs_review { border-left-color: var(--flag-amber); }
.period.finalized    { border-left-color: var(--flag-green); }

.period-when { display: flex; flex-direction: column; }
.period-range { font-weight: 700; font-size: 1rem; }

.period-state { display: flex; flex-direction: column; gap: 0.1rem; }
.period-badge {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.period.needs_import .period-badge { color: var(--ink-3); }
.period.needs_review .period-badge { color: var(--flag-amber); }
.period.finalized    .period-badge { color: var(--flag-green); }
.period-why { font-size: 0.8rem; color: var(--ink-3); }

.period-figs { display: flex; flex-wrap: wrap; gap: 0.15rem 1.25rem; }

.payroll .panel .claims-head .f {
  flex: 1;
  max-width: 18rem;
  padding: 0.35rem 0.6rem;
}

#dlg-period { width: min(96vw, 46rem); max-height: 90vh; overflow: auto; }
#dlg-period .person { grid-template-columns: minmax(9rem, auto) 1fr auto auto; }
#dlg-batches { width: min(100%, 38rem); max-height: 85vh; overflow: auto; }

@media (max-width: 820px) {
  .period { grid-template-columns: 1fr; }
}

/* an advance that has already missed a remittance */
.period-figs .fact.bad .fact-k,
.period-figs .fact.bad .fact-v,
.person-facts .fact.bad .fact-v { color: var(--flag-red); }
.period-figs .fact.warn .fact-v { color: var(--flag-amber); }

.crew-box {
  margin-top: 1rem;
  padding: 0.8rem 1rem;
  background: var(--paper);
  border-left: 4px solid var(--locate);
  border-radius: 0 var(--r-md) var(--r-md) 0;
}
.crew-box .section-head { margin: 0 0 0.35rem; border-bottom: none; }

.panel.warn-panel {
  border-color: var(--flag-amber);
  background: rgba(217,147,15,0.05);
}
.panel.warn-panel .section-head { color: var(--flag-amber); }

/* whose job it was, on a lead's pay screen */
.crew-name { color: var(--locate); font-weight: 600; }
.pay-week table.detail-lines td.warn-text,
#dlg-outstanding td.warn-text { color: var(--flag-amber); }


/* ---------- collapsing ----------
 * A long page of weeks is a page nobody reads. The header carries
 * enough to decide whether to open it.
 */

.pay-week-head {
  width: 100%;
  text-align: left;
  border: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.pay-week.closed .pay-week-head { border-bottom: none; }
.pay-week-head:hover { background: rgba(255,122,51,0.06); }

.week-caret,
.period-caret {
  display: inline-block;
  width: 1rem;
  color: var(--ink-3);
  font-size: 0.8rem;
}
.week-count { color: var(--ink-3); font-size: 0.82rem; margin-left: 0.75rem; }

.period-box {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  overflow: hidden;
}
.period-box.open { border-color: var(--locate); }
.period-box .period {
  border: none;
  border-left: 4px solid var(--rule);
  border-radius: 0;
  background: none;
}
.period-box.open .period { border-bottom: 1px solid var(--rule); }

.period-detail {
  padding: 0.7rem 0.9rem 0.9rem;
  background: var(--paper);
}
.period-detail .rows { gap: 0.4rem; }
.period-detail .console-bar { margin-top: 0.7rem; }
/* checkbox · name · facts · counts · button — five columns, so the
 * action button stays in the last one instead of wrapping under the
 * name. The checkbox column is fixed and narrow. */
.period-detail .person {
  grid-template-columns: 1.4rem minmax(9rem, auto) 1fr auto auto;
  align-items: center;
}
/* the button reads clearly as the row's action, pinned right */
.period-detail .person > .btn-primary,
.period-detail .person > .btn-quiet {
  justify-self: end;
}


/* ---------- recon ----------
 * A list that is meant to empty. Decided rows stay visible but fade,
 * so the eye goes to what is still open.
 *
 * The columns are sized rather than shared out: the actions need a
 * fixed amount of room, and without it the buttons squeeze into each
 * other as soon as a row has three of them.
 */

/* The widths have to ADD UP to the panel, or the last column hangs
 * off the edge. Budget is roughly 70rem inside the page cap:
 * 5 + 8 + 6 + 4.5 + 4.5 + 5.5 + 5.5 + 5.5 + 3.5 + 6 + 13 = 67rem,
 * leaving a little slack. */
.recon-table { table-layout: fixed; width: 100%; }
.recon-table th:nth-child(1)  { width: 2rem; }     /* checkbox */
.recon-table th:nth-child(2)  { width: 5rem; }     /* job */
.recon-table th:nth-child(3)  { width: 8rem; }     /* tech */
.recon-table th:nth-child(4)  { width: 6rem; }     /* completed */
.recon-table th:nth-child(5),
.recon-table th:nth-child(6)  { width: 4.5rem; }   /* codes */
.recon-table th:nth-child(7),
.recon-table th:nth-child(8),
.recon-table th:nth-child(9)  { width: 5.5rem; }   /* money */
.recon-table th:nth-child(10) { width: 3.5rem; }   /* age */
.recon-table th:nth-child(11) { width: 6rem; }     /* status */
.recon-table th:nth-child(12) { width: 13rem; }    /* actions */
.recon-table td.pick input { width: 16px; height: 16px; accent-color: var(--locate); }

.recon-table th,
.recon-table td { text-align: center; padding: 0.4rem 0.3rem; }
.recon-table th { font-size: 0.66rem; }
/* tech name (now col 3) and job (col 2) read left */
.recon-table th:nth-child(3),
.recon-table td:nth-child(3),
.recon-table td:nth-child(2) { text-align: left; }
.recon-table td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.recon-actions {
  display: flex;
  gap: 0.25rem;
  justify-content: flex-end;
  flex-wrap: nowrap;
}
.recon-actions .route-act,
.recon-actions .btn-quiet.compact {
  padding: 0.2rem 0.42rem;
  font-size: 0.72rem;
  white-space: nowrap;
}
.recon-actions .state { font-size: 0.72rem; }

/* A last resort rather than a layout: if a narrow window still does
 * not fit, scroll the table rather than letting it run off the card. */
.payroll .panel { overflow-x: auto; }
.recon-actions .state { font-size: 0.76rem; margin-right: 0.3rem; }

.inline-pick {
  padding: 0.2rem 0.35rem;
  font-size: 0.76rem;
  max-width: 9rem;
}

.payroll .panel .menu-label { margin: 1rem 0 0.2rem; }
.payroll .panel .menu-label:first-of-type { margin-top: 0.2rem; }
.payroll .panel .hint.small { margin: 0 0 0.4rem; }

/* the two cards at the top do not need a whole row each */
.payroll .pay-summary { max-width: 44rem; }

/* Held is a parked job, not a finished one, so it stays legible
 * rather than fading like a decided row. */
.recon-table tr.is-held td { opacity: 1; }

@media (max-width: 1180px) {
  .recon-table { table-layout: auto; }
  .recon-table th:nth-child(4),
  .recon-table td:nth-child(3) { display: none; }
}

#dlg-allperiods { width: min(100%, 40rem); max-height: 85vh; overflow: auto; }
#dlg-allperiods .amount.muted { color: var(--ink-3); }
#dlg-allperiods .state.finalized    { color: var(--flag-green); }
#dlg-allperiods .state.needs_review { color: var(--flag-amber); }
#dlg-allperiods .state.needs_import { color: var(--ink-3); }


/* ---------- CMT submissions ----------
 * Stage tabs across the top, because the only question on opening the
 * page is "what needs me", and that is one of five answers.
 */

.cmt-tabs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 0.5rem;
  max-width: 60rem;
  margin-bottom: 0.8rem;
}

.cmt-tab {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.6rem 0.8rem;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 4px solid var(--rule);
  border-radius: var(--r-md);
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.cmt-tab:hover { border-color: var(--locate); }
.cmt-tab.on { border-color: var(--locate); background: rgba(255,122,51,0.06); }

.cmt-tab-count {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1;
}
.cmt-tab-label { font-size: 0.78rem; color: var(--ink-2); }

.cmt-tab.ready          { border-left-color: var(--locate); }
.cmt-tab.awaiting_scope { border-left-color: var(--ink-3); }
.cmt-tab.approved       { border-left-color: var(--flag-amber); }
.cmt-tab.submitted      { border-left-color: var(--flag-green); }
.cmt-tab.rejected       { border-left-color: var(--flag-red); }


@media (max-width: 900px) {
  .cmt-row { grid-template-columns: auto 1fr; }
  .cmt-facts, .cmt-actions { grid-column: 1 / -1; }
}

/* the pictures being approved */
.cmt-photos {
  grid-column: 2 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: flex-start;
  margin-top: 0.4rem;
}
.cmt-thumb {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  width: 7rem;
  text-decoration: none;
  color: var(--ink-3);
}
.cmt-thumb img {
  width: 7rem;
  height: 5rem;
  object-fit: cover;
  border-radius: var(--r-sm);
  border: 1px solid var(--rule);
  background: var(--paper);
}
.cmt-thumb:hover img { border-color: var(--locate); }
.cmt-thumb-label { font-size: 0.68rem; text-align: center; }


/* ---------- CMT table ----------
 * A column per fact, scanned down. The card version was denser and
 * harder to compare at the same time, which is the worst of both.
 */

.cmt-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}
.cmt-table th {
  text-align: left;
  padding: 0.45rem 0.55rem;
  font-size: 0.66rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-3);
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}
.cmt-table td {
  padding: 0.55rem 0.55rem;
  border-bottom: 1px solid var(--rule);
  vertical-align: middle;
}
.cmt-table tbody tr:hover { background: rgba(255,255,255,0.02); }

.cmt-table td.strong { font-weight: 700; }
.cmt-table td.mono   { font-size: 0.78rem; color: var(--ink-2); }
.cmt-table td.muted  { color: var(--ink-3); }
.cmt-table td.num    { text-align: center; }

/* Address and comments are the two that run long. They get the room
 * and truncate rather than wrapping every row to three lines. */
.cmt-table td.cmt-address,
.cmt-table td.cmt-comment {
  max-width: 16rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cmt-table td.cmt-comment { color: var(--ink-2); font-style: italic; }

.cmt-table td.pick { width: 2rem; }
.cmt-pick { width: 17px; height: 17px; accent-color: var(--locate); }

.cmt-table tr.ready td    { border-left: 0; }
.cmt-table tr.rejected td:first-child { box-shadow: inset 3px 0 0 var(--flag-red); }

.cmt-actions { white-space: nowrap; text-align: right; }
.cmt-action-row {
  display: flex;
  gap: 0.3rem;
  justify-content: flex-end;
  align-items: center;
}
.cmt-action-row .btn-quiet.compact,
.cmt-action-row .route-act {
  padding: 0.2rem 0.5rem;
  font-size: 0.75rem;
}

.cmt-photo-row td {
  background: var(--paper);
  padding: 0.7rem 0.9rem;
}

/* ---------- one CMT form, in full ---------- */

#dlg-cmt { width: min(96vw, 52rem); max-height: 90vh; overflow: auto; }

.cmt-detail {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0.7rem 1.25rem;
  margin-bottom: 0.5rem;
}
.cmt-detail-item { display: flex; flex-direction: column; gap: 0.15rem; }
.cmt-detail-v { font-size: 1rem; font-weight: 600; }
.cmt-detail-item.good .cmt-detail-v { color: var(--flag-green); }
.cmt-detail-item.warn .cmt-detail-v { color: var(--flag-amber); }
.cmt-detail-item.bad  .cmt-detail-v { color: var(--flag-red); }

.cmt-detail-block {
  margin: 0 0 0.6rem;
  padding: 0.6rem 0.8rem;
  background: var(--paper);
  border-radius: var(--r-md);
  font-size: 0.95rem;
  line-height: 1.45;
}
.cmt-detail-block.bad { color: var(--flag-red); }

/* Bigger here than in the table: this is the screen for looking. */
.cmt-photos.big .cmt-thumb { width: 11rem; }
.cmt-photos.big .cmt-thumb img { width: 11rem; height: 8rem; }
.cmt-photos.big .cmt-thumb-label { font-size: 0.75rem; }

/* bore stages, and the money each tab is worth */
.cmt-tab-sub { font-size: 0.72rem; color: var(--ink-3); }
.cmt-tab.bore-not_sent { border-left-color: var(--flag-amber); }
.cmt-tab.bore-unpaid   { border-left-color: var(--flag-red); }
.cmt-tab.bore-sent     { border-left-color: var(--locate); }
.cmt-tab.bore-paid     { border-left-color: var(--flag-green); }

#dlg-bore { width: min(96vw, 52rem); max-height: 90vh; overflow: auto; }



/* the bore invoice email */
#dlg-boremail { width: min(96vw, 48rem); max-height: 90vh; overflow: auto; }
.bore-email-body {
  width: 100%;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85rem;
  line-height: 1.5;
  padding: 0.7rem 0.8rem;
  background: var(--paper);
  color: var(--ink-1);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  resize: vertical;
}
#dlg-boremail .console-bar { margin: 0.6rem 0; align-items: center; }
#dlg-boremail a.btn-quiet { text-decoration: none; display: inline-flex; align-items: center; }

/* ---------- repeats ---------- */

.cmt-tab.rep-undecided  { border-left-color: var(--flag-red); }
.cmt-tab.rep-incomplete { border-left-color: var(--flag-amber); }
.cmt-tab.rep-ready      { border-left-color: var(--locate); }
.cmt-tab.rep-sent       { border-left-color: var(--ink-3); }
.cmt-tab.rep-resolved   { border-left-color: var(--flag-green); }
.cmt-tab.rep-valid      { border-left-color: var(--ink-3); }

#dlg-repeat { width: min(96vw, 52rem); max-height: 90vh; overflow: auto; }
#dlg-techrepeat { width: min(96vw, 44rem); max-height: 90vh; overflow: auto; }

.repeat-form {
  display: grid;
  gap: 0.7rem;
  margin-bottom: 0.8rem;
}
.repeat-field { display: flex; flex-direction: column; gap: 0.25rem; }
.repeat-field label { font-size: 0.82rem; color: var(--ink-2); }
.repeat-field .req { color: var(--flag-red); }
.repeat-field .f { width: 100%; }

/* additional codes on a fulfillment invoice */
.ff-addons-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.ff-addons-head .section-head { margin-bottom: 0; }
.ff-addon-row {
  display: flex;
  gap: 0.4rem;
  align-items: center;
  margin-bottom: 0.4rem;
}
.ff-addon-row .f { flex: 1; }
.ff-addon-row .ff-addon-qty { flex: 0 0 5rem; }


/* recon bulk-action bar, one per group */
.recon-bulk {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin: 0.3rem 0 0.5rem;
  padding: 0.4rem 0.6rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
}
.recon-bulk-all {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.82rem;
  margin-right: auto;
}
.recon-bulk-all input { width: 16px; height: 16px; accent-color: var(--locate); }
.recon-bulk .btn-quiet.compact,
.recon-bulk .route-act { padding: 0.2rem 0.55rem; font-size: 0.76rem; }

/* the amount-due figure on a built statement's preview row */
.person-facts .fact.due .fact-k { color: var(--flag-green); }
.person-facts .fact.due .fact-v {
  color: var(--flag-green);
  font-size: 1.15rem;
  font-weight: 700;
}

/* draft-stub checkboxes for bulk finalize */
.period-detail .person { position: relative; }
.stub-pick { width: 17px; height: 17px; accent-color: var(--locate); margin-right: 0.2rem; }
.stub-pick-gap { display: inline-block; width: 17px; margin-right: 0.2rem; }


/* ---------- Comcast ---------- */

.comcast-job { margin-bottom: 0.8rem; }
.comcast-job .cmt-facts { margin: 0.4rem 0 0.7rem; }

/* the four stamp buttons — big, tappable, one live at a time */
.comcast-marks {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.5rem;
}
.comcast-mark {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  padding: 0.7rem 0.5rem;
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink-3);
  font: inherit;
  cursor: not-allowed;
  min-height: 3.6rem;
}
.comcast-mark-label { font-weight: 700; font-size: 0.9rem; }
.comcast-mark-sub   { font-size: 0.7rem; }
.comcast-mark-time  { font-size: 0.85rem; color: var(--flag-green); font-weight: 600; }

/* the next mark to make: bright, tappable */
.comcast-mark.live {
  background: var(--locate);
  border-color: var(--locate);
  color: #fff;
  cursor: pointer;
}
.comcast-mark.live .comcast-mark-sub { color: rgba(255,255,255,0.85); }
.comcast-mark.live:hover { filter: brightness(1.05); }

/* already stamped: quiet, with the time */
.comcast-mark.done {
  background: var(--paper);
  border-color: var(--flag-green);
  color: var(--ink-1);
}

@media (max-width: 560px) {
  .comcast-marks { grid-template-columns: repeat(2, 1fr); }
}

/* editor + consumables grids */
.comcast-grid,
.consumables-grid {
  display: grid;
  gap: 0.6rem 0.8rem;
}
.comcast-grid { grid-template-columns: repeat(3, 1fr); }
.consumables-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.comcast-field { display: flex; flex-direction: column; gap: 0.2rem; }
.comcast-field label { font-size: 0.78rem; color: var(--ink-2); }
.comcast-field input, .comcast-field select, .comcast-field textarea { width: 100%; }

#dlg-comcast { width: min(96vw, 46rem); max-height: 90vh; overflow: auto; }
#dlg-consumables { width: min(96vw, 40rem); max-height: 90vh; overflow: auto; }

.cmt-table td.state.notchecked { color: var(--ink-3); }


/* ============================================================
   Comcast — tech mobile job flow
   A field tech, on their phone, at a job site. One tap at the
   right moment. Dark slate that reads in a truck cab and in sun;
   a single safety-amber signal for the live action; green only
   for what's done. The live action is the hero — everything else
   stays quiet.
   ============================================================ */

.cx {
  --cx-ink:      #0d1117;   /* deepest — page */
  --cx-surface:  #161b23;   /* a job card */
  --cx-raised:   #1e252f;   /* a step, elevated */
  --cx-line:     #2a323d;   /* hairlines */
  --cx-text:     #eef2f6;   /* primary text */
  --cx-dim:      #8896a5;   /* secondary */
  --cx-faint:    #55606d;   /* tertiary */
  --cx-go:       #ff8a1e;   /* safety amber — the live action */
  --cx-go-deep:  #e8720a;
  --cx-done:     #3fb768;   /* completed marks */

  max-width: 32rem;
  margin: 0 auto;
  padding: 0.25rem 0 3rem;
  color: var(--cx-text);
}

/* the day header — understated */
.cx-day { padding: 0.4rem 0.25rem 1rem; }
.cx-day-date {
  font-size: 1.35rem;
  font-weight: 650;
  letter-spacing: -0.02em;
  line-height: 1.15;
}
.cx-day-count { color: var(--cx-dim); font-size: 0.92rem; margin-top: 0.15rem; }

.cx-empty {
  text-align: center;
  color: var(--cx-dim);
  padding: 4rem 1rem;
}
.cx-empty-mark { font-size: 2.5rem; color: var(--cx-faint); margin-bottom: 0.5rem; }

/* ---- a job card ---- */
.cx-job {
  background: var(--cx-surface);
  border: 1px solid var(--cx-line);
  border-radius: 20px;
  padding: 1.1rem 1.1rem 0.9rem;
  margin-bottom: 1rem;
  box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 8px 24px rgba(0,0,0,0.18);
}

.cx-job-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}
.cx-job-site {
  font-size: 1.15rem;
  font-weight: 680;
  letter-spacing: -0.01em;
}
.cx-job-sub { color: var(--cx-dim); font-size: 0.85rem; margin-top: 0.2rem; }

.cx-job-total { text-align: right; flex: none; }
.cx-job-total-val {
  display: block;
  font-size: 1.25rem;
  font-weight: 680;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.cx-job-total-lab {
  display: block;
  font-size: 0.68rem;
  color: var(--cx-faint);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-top: 0.2rem;
}

/* ---- the timeline rail ---- */
.cx-rail {
  position: relative;
  margin: 0.25rem 0 1.1rem;
  padding-left: 0.25rem;
}
.cx-step {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 0.85rem;
  padding: 0.5rem 0;
  min-height: 2.2rem;
}
/* the connecting line runs through the nodes */
.cx-step::before {
  content: "";
  position: absolute;
  left: 0.53rem;
  top: 1.5rem;
  bottom: -0.5rem;
  width: 2px;
  background: var(--cx-line);
}
.cx-step:last-child::before { display: none; }
.cx-step.done::before { background: var(--cx-done); }

.cx-step-node {
  position: relative;
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 50%;
  border: 2px solid var(--cx-line);
  background: var(--cx-surface);
  align-self: flex-start;
  margin-top: 0.1rem;
  z-index: 1;
}
.cx-step.done .cx-step-node {
  border-color: var(--cx-done);
  background: var(--cx-done);
}
.cx-step.done .cx-step-node::after {
  content: "\2713";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.7rem;
  font-weight: 800;
  color: var(--cx-ink);
}
.cx-step.next .cx-step-node {
  border-color: var(--cx-go);
  box-shadow: 0 0 0 4px rgba(255,138,30,0.15);
  animation: cx-pulse 2s ease-in-out infinite;
}
@keyframes cx-pulse {
  0%, 100% { box-shadow: 0 0 0 4px rgba(255,138,30,0.15); }
  50%      { box-shadow: 0 0 0 7px rgba(255,138,30,0.05); }
}

.cx-step-body { flex: 1; }
.cx-step-label {
  font-size: 0.95rem;
  font-weight: 550;
  color: var(--cx-dim);
}
.cx-step.done .cx-step-label { color: var(--cx-text); }
.cx-step.next .cx-step-label { color: var(--cx-text); font-weight: 640; }

.cx-step-time {
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
  color: var(--cx-done);
  font-weight: 600;
  margin-top: 0.1rem;
}
.cx-step-waiting {
  color: var(--cx-go);
  font-weight: 600;
  font-variant-numeric: normal;
}
.cx-step-gap {
  flex: none;
  align-self: center;
  font-size: 0.72rem;
  color: var(--cx-faint);
  font-variant-numeric: tabular-nums;
}

/* ---- the hero: one big action ---- */
.cx-go {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.15rem;
  width: 100%;
  min-height: 4.6rem;
  border: none;
  border-radius: 16px;
  background: linear-gradient(180deg, var(--cx-go) 0%, var(--cx-go-deep) 100%);
  color: #241200;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(255,138,30,0.28);
  transition: transform 0.08s ease, box-shadow 0.15s ease, filter 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}
.cx-go:active { transform: scale(0.985); box-shadow: 0 2px 8px rgba(255,138,30,0.25); }
.cx-go-main { font-size: 1.25rem; font-weight: 720; letter-spacing: -0.01em; }
.cx-go-sub  { font-size: 0.82rem; font-weight: 550; opacity: 0.72; }

/* the final mark reads as a finish line — deeper, decisive */
.cx-go-home {
  background: linear-gradient(180deg, #3fb768 0%, #2f9553 100%);
  color: #04240f;
  box-shadow: 0 4px 14px rgba(63,183,104,0.28);
}
.cx-go-home:active { box-shadow: 0 2px 8px rgba(63,183,104,0.25); }

.cx-go-firing { filter: saturate(1.3) brightness(1.1); pointer-events: none; }

/* the done state */
.cx-done {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  padding: 1.1rem;
  border-radius: 16px;
  background: rgba(63,183,104,0.08);
  border: 1px solid rgba(63,183,104,0.25);
}
.cx-done-check {
  width: 2.4rem; height: 2.4rem;
  border-radius: 50%;
  background: var(--cx-done);
  color: var(--cx-ink);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.3rem; font-weight: 800;
  margin-bottom: 0.15rem;
}
.cx-done-text { font-size: 1.05rem; font-weight: 650; }
.cx-done-sub  { font-size: 0.85rem; color: var(--cx-dim); font-variant-numeric: tabular-nums; }

/* consumables — secondary, quiet */
.cx-consumables {
  display: block;
  width: 100%;
  margin-top: 0.7rem;
  padding: 0.7rem;
  background: transparent;
  border: 1px solid var(--cx-line);
  border-radius: 12px;
  color: var(--cx-dim);
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}
.cx-consumables:active { border-color: var(--cx-go); color: var(--cx-text); }

@media (prefers-reduced-motion: reduce) {
  .cx-step.next .cx-step-node { animation: none; }
  .cx-go { transition: none; }
}


/* Comcast — day grouping, locked future jobs, tech notes */

.cx-daygroup {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin: 1.6rem 0.25rem 0.7rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--cx-line);
}
.cx-daygroup:first-of-type { border-top: none; padding-top: 0.3rem; }
.cx-daygroup-label {
  font-size: 1rem;
  font-weight: 640;
  color: var(--cx-text);
}
.cx-daygroup-lock {
  font-size: 0.72rem;
  color: var(--cx-faint);
  font-weight: 500;
}

/* a locked (future) job — visible, dimmed, nothing actionable */
.cx-job-locked {
  opacity: 0.62;
  box-shadow: none;
  border-style: dashed;
}
.cx-job-locked .cx-job-site { color: var(--cx-dim); }

.cx-lock-badge { flex: none; }
.cx-lock-icon { font-size: 1.1rem; opacity: 0.7; }

.cx-job-addr {
  color: var(--cx-dim);
  font-size: 0.82rem;
  margin-top: 0.2rem;
}

/* notes — a quiet line that expands to an editor */
.cx-notes { margin-top: 0.7rem; }
.cx-notes-view {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
  padding: 0.7rem 0.8rem;
  background: rgba(255,255,255,0.02);
  border: 1px solid var(--cx-line);
  border-radius: 12px;
  color: var(--cx-dim);
  font-size: 0.9rem;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.cx-notes-view:active { border-color: var(--cx-go); }
.cx-notes-icon { font-size: 0.95rem; flex: none; }
.cx-notes-text {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cx-notes-editor { }
.cx-notes-input {
  width: 100%;
  padding: 0.7rem 0.8rem;
  background: var(--cx-raised);
  border: 1px solid var(--cx-go);
  border-radius: 12px;
  color: var(--cx-text);
  font: inherit;
  font-size: 0.92rem;
  resize: vertical;
  -webkit-tap-highlight-color: transparent;
}
.cx-notes-acts {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.5rem;
}
.cx-notes-save {
  flex: 1;
  padding: 0.6rem;
  background: var(--cx-go);
  color: #241200;
  border: none;
  border-radius: 10px;
  font-weight: 640;
  font-size: 0.9rem;
  cursor: pointer;
}
.cx-notes-cancel {
  padding: 0.6rem 1rem;
  background: transparent;
  color: var(--cx-dim);
  border: 1px solid var(--cx-line);
  border-radius: 10px;
  font-size: 0.9rem;
  cursor: pointer;
}

/* comcast import + budget flag (admin board only) */
.import-problem {
  display: flex; gap: 0.6rem; align-items: baseline;
  padding: 0.4rem 0.6rem; font-size: 0.85rem;
  border-bottom: 1px solid var(--rule);
}
.cmt-table td.num.over { color: var(--flag-red); font-weight: 700; }
.cmt-table td.num.muted { color: var(--ink-3); }

/* tappable address → directions */
.cx-addr-link {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  color: var(--cx-go);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.cx-addr-link:active { text-decoration: underline; }
.cx-addr-pin { font-size: 0.8rem; flex: none; }

/* Comcast admin — expandable job detail row */
.cx-clickable { cursor: pointer; }
.cx-clickable:hover { background: rgba(255,255,255,0.03); }
.cx-clickable.cx-open { background: rgba(255,138,30,0.06); }
.cx-clickable.cx-open td { border-bottom-color: transparent; }

.cx-detail-row > td { padding: 0 !important; background: var(--paper); }
.cx-detail {
  padding: 1.1rem 1.3rem 1.3rem;
  border-left: 3px solid var(--locate);
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

/* the four marks as a horizontal timeline */
.cx-detail-marks {
  display: flex;
  gap: 0;
  flex-wrap: wrap;
}
.cx-detail-mark {
  position: relative;
  flex: 1;
  min-width: 8rem;
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  padding: 0 1rem 0 0;
}
.cx-detail-mark-node {
  flex: none;
  width: 0.9rem; height: 0.9rem;
  border-radius: 50%;
  border: 2px solid var(--rule);
  background: var(--surface);
  margin-top: 0.15rem;
}
.cx-detail-mark.done .cx-detail-mark-node {
  border-color: var(--flag-green);
  background: var(--flag-green);
}
.cx-detail-mark-label {
  font-size: 0.8rem; font-weight: 600; color: var(--ink-2);
}
.cx-detail-mark.done .cx-detail-mark-label { color: var(--ink-1); }
.cx-detail-mark-time {
  font-size: 0.85rem; font-weight: 600; color: var(--flag-green);
  font-variant-numeric: tabular-nums; margin-top: 0.1rem;
}
.cx-detail-mark-pending { font-size: 0.78rem; color: var(--ink-3); margin-top: 0.1rem; }
.cx-detail-mark-gap {
  position: absolute; right: 0.5rem; top: 0.15rem;
  font-size: 0.7rem; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

/* the figures row */
.cx-detail-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1.6rem;
  padding: 0.9rem 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.cx-detail-fig { display: flex; flex-direction: column; gap: 0.1rem; }
.cx-detail-fig-v {
  font-size: 1.1rem; font-weight: 680;
  font-variant-numeric: tabular-nums;
}
.cx-detail-fig-k {
  font-size: 0.68rem; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--ink-3);
}
.cx-detail-fig.bad .cx-detail-fig-v { color: var(--flag-red); }

/* reference meta */
.cx-detail-meta { display: flex; flex-direction: column; gap: 0.3rem; }
.cx-detail-metaline { display: flex; gap: 0.6rem; font-size: 0.86rem; }
.cx-detail-meta-k {
  flex: none; width: 6.5rem; color: var(--ink-3);
  font-size: 0.78rem; padding-top: 0.05rem;
}

/* Comcast tech — Today/Completed tabs, completed cards, pending edits */
.cx-tabs {
  display: flex; gap: 0.5rem;
  margin: 0.25rem 0 1rem; padding: 0.3rem;
  background: var(--cx-surface); border-radius: 12px;
}
.cx-tab {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 0.4rem;
  padding: 0.6rem; border: none; border-radius: 9px;
  background: transparent; color: var(--cx-dim);
  font-size: 0.95rem; font-weight: 600; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.cx-tab.on { background: var(--cx-raised); color: var(--cx-text); }
.cx-tab-count {
  font-size: 0.72rem; padding: 0.05rem 0.4rem; border-radius: 999px;
  background: var(--cx-go); color: #241200; font-weight: 700;
}

.cx-job-done .cx-job-total-val { color: var(--cx-done); }
.cx-done-times {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 0.5rem; margin: 0.7rem 0;
}
.cx-done-time {
  display: flex; flex-direction: column; gap: 0.15rem;
  padding: 0.5rem; background: var(--cx-raised); border-radius: 9px; text-align: center;
}
.cx-done-time-label {
  font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--cx-faint);
}
.cx-done-time-val {
  font-size: 0.95rem; font-weight: 650; font-variant-numeric: tabular-nums; color: var(--cx-text);
}
.cx-done-summary {
  font-size: 0.9rem; color: var(--cx-dim); text-align: center; margin-bottom: 0.5rem;
  font-variant-numeric: tabular-nums;
}
.cx-pending-badge {
  flex: none; padding: 0.3rem 0.7rem; border-radius: 999px;
  background: rgba(255,138,30,0.15); color: var(--cx-go);
  font-size: 0.78rem; font-weight: 650;
}
.cx-pending-note {
  margin-top: 0.6rem; padding: 0.7rem 0.8rem;
  background: rgba(255,138,30,0.08); border: 1px solid rgba(255,138,30,0.25);
  border-radius: 10px; font-size: 0.82rem; color: var(--cx-dim);
}

/* Recon — client tabs + Comcast time-edit approvals */
.recon-client-tabs {
  display: flex; gap: 0.5rem; margin-bottom: 1.2rem;
  border-bottom: 1px solid var(--rule);
}
.recon-client-tab {
  display: flex; align-items: center; gap: 0.4rem;
  padding: 0.6rem 1.1rem; border: none; background: transparent;
  color: var(--ink-3); font-size: 0.98rem; font-weight: 600;
  cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.recon-client-tab.on { color: var(--ink-1); border-bottom-color: var(--locate); }
.recon-client-badge {
  font-size: 0.72rem; padding: 0.05rem 0.4rem; border-radius: 999px;
  background: var(--locate); color: #fff; font-weight: 700;
}

.recon-edit {
  padding: 0.8rem 0.95rem; margin-bottom: 0.6rem;
  background: var(--surface); border: 1px solid var(--rule);
  border-left: 3px solid var(--rule); border-radius: 10px;
}
.recon-edit.more { border-left-color: var(--flag-red); }
.recon-edit.less { border-left-color: var(--flag-green); }

.recon-edit-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin-bottom: 0.55rem;
}
.recon-edit-id { display: flex; flex-direction: column; gap: 0.05rem; min-width: 0; }
.recon-edit-meta { font-size: 0.78rem; color: var(--ink-3); }
.recon-edit-money { text-align: right; flex: none; }
.recon-edit-diff {
  display: block; font-weight: 750; font-size: 1.05rem;
  font-variant-numeric: tabular-nums; line-height: 1.1;
}
.recon-edit-diff.more { color: var(--flag-red); }
.recon-edit-diff.less { color: var(--flag-green); }
.recon-edit-diff.same { color: var(--ink-3); font-weight: 600; font-size: 0.9rem; }
.recon-edit-hours {
  font-size: 0.72rem; color: var(--ink-3); font-variant-numeric: tabular-nums;
}

/* the four marks, compact — only changed ones stand out */
.recon-edit-marks {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 0.1rem 1.4rem; margin-bottom: 0.5rem;
}
.recon-edit-mline {
  display: flex; align-items: baseline; gap: 0.5rem;
  font-size: 0.83rem; padding: 0.12rem 0;
}
.recon-edit-mk {
  flex: none; width: 4rem; color: var(--ink-3); font-size: 0.78rem;
}
.recon-edit-unch { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.recon-edit-mline.changed .recon-edit-mk { color: var(--ink-1); font-weight: 600; }
.recon-edit-old {
  color: var(--ink-3); text-decoration: line-through;
  font-variant-numeric: tabular-nums; font-size: 0.8rem;
}
.recon-edit-to { color: var(--ink-3); }
.recon-edit-new {
  font-weight: 650; font-variant-numeric: tabular-nums; color: var(--ink-1);
}

.recon-edit-note {
  font-style: italic; color: var(--ink-2); font-size: 0.82rem;
  margin-bottom: 0.55rem;
}
.recon-edit-acts { display: flex; gap: 0.45rem; }
.recon-edit-acts .btn-primary.compact,
.recon-edit-acts .route-act { padding: 0.3rem 0.9rem; font-size: 0.82rem; }

@media (max-width: 520px) {
  .recon-edit-marks { grid-template-columns: 1fr; }
}

/* editable proposed-time inputs in the approval card */
.recon-edit-input {
  padding: 0.2rem 0.4rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 6px;
  color: var(--ink-1);
  font: inherit;
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
  width: auto;
  min-width: 6.5rem;
}
.recon-edit-mline.changed .recon-edit-input {
  border-color: var(--locate);
  font-weight: 650;
}

/* Comcast recon — the "agrees" collapsible */
.recon-ok-details { margin-top: 0.6rem; }
.recon-ok-details summary {
  cursor: pointer; color: var(--ink-3); font-size: 0.85rem; padding: 0.4rem 0;
}
.recon-ok-details summary:hover { color: var(--ink-1); }

/* address on a time-edit approval */
.recon-edit-addr {
  display: inline-flex; align-items: center; gap: 0.3rem;
  margin: 0.1rem 0 0.55rem; font-size: 0.83rem;
  color: var(--locate); text-decoration: none;
}
.recon-edit-addr:hover { text-decoration: underline; }
.recon-edit-pin { font-size: 0.78rem; flex: none; }
