/* ============================================================
   Manny Solutions Operations — UI design system (Phase 1)
   Built from scratch. Light skin, flat surfaces, one accent.
   Rules (binding, see DevResources/UI-Style-Guide):
   - No gradients, no decoration. Color only as small status tags.
   - Base font 15px, 44px+ touch targets, visible focus.
   - Compact forms: field width matches content.
   - Grids keep Excel column order.
   ============================================================ */

:root {
    /* Palette — flat, calm */
    --bg:            #f5f6f8;
    --surface:       #ffffff;
    --surface-2:     #f9fafb;
    --border:        #e3e6ea;
    --border-strong: #cdd2d9;
    --text:          #1f2733;
    --text-2:        #5c6672;
    --text-3:        #8b95a1;
    --primary:       #1b6ee0;
    --primary-soft:  #e8f1fd;
    --primary-deep:  #14509f;
    --green:         #13795b;
    --green-soft:    #e3f5ee;
    --red:           #c23934;
    --red-soft:      #fdeceb;
    --amber:         #9a6700;
    --amber-soft:    #fff3d6;
    --violet:        #6b4fd8;
    --violet-soft:   #efeafc;
    --gray-tag:      #5c6672;
    --gray-tag-soft: #eef0f2;

    /* Type */
    --font: "Segoe UI", system-ui, -apple-system, Roboto, "Helvetica Neue", Arial, sans-serif;
    --mono: Consolas, "Courier New", monospace;
    --fs:      15px;
    --fs-sm:   13px;
    --fs-lg:   17px;
    --fs-xl:   22px;

    /* Rhythm */
    --pad:     14px;
    --radius:  8px;
    --radius-sm: 5px;
    --sidebar-w: 232px;
    --topbar-h:  56px;
    --speed:   170ms;
    --shadow:  0 1px 2px rgba(31, 39, 51, .06);
    --shadow-lg: 0 10px 34px rgba(31, 39, 51, .18);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
    font-family: var(--font);
    font-size: var(--fs);
    color: var(--text);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 { margin: 0 0 .45em; font-weight: 600; line-height: 1.25; }
h1 { font-size: var(--fs-xl); }
h2 { font-size: 18px; }
h3 { font-size: 16px; }
p  { margin: 0 0 .8em; line-height: 1.5; }
a  { color: var(--primary); text-decoration: none; }
a:hover { text-decoration: underline; }
hr { border: 0; border-top: 1px solid var(--border); margin: 14px 0; }
code, .mono { font-family: var(--mono); font-size: .93em; }

:focus-visible {
    outline: 3px solid var(--primary);
    outline-offset: 1px;
    border-radius: 3px;
}

/* ---------- App frame ----------
   The navigation moved from a left rail to the top bar, so the page
   gets that width back. The drawer below is the small-screen fallback
   and is out of flow at every size. */
.app { display: flex; min-height: 100vh; }
.app-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.content { flex: 1; padding: 16px 22px 40px; outline: none; }
.content > .screen { max-width: 1760px; margin: 0 auto; }

/* ---------- Small-screen drawer (the old sidebar) ---------- */
.sidebar {
    width: var(--sidebar-w);
    background: #10131a;
    color: #c8ceda;
    display: flex;
    flex-direction: column;
    position: fixed; left: 0; top: 0; bottom: 0;
    overflow-y: auto;
    z-index: 70;
    transform: translateX(-100%);
    transition: transform 200ms ease-out;
}
.sidebar.open { transform: none; box-shadow: var(--shadow-lg); }
.sidebar-brand {
    display: flex; align-items: center; gap: 10px;
    padding: 15px 16px 13px;
    color: #fff; font-size: 16px; font-weight: 600;
    border-bottom: 1px solid rgba(255,255,255,.08);
}
.sidebar-brand .logo {
    width: 30px; height: 30px; border-radius: 7px;
    background: var(--primary); color: #fff;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 13px; font-weight: 700; letter-spacing: .5px;
}
.sidebar-section {
    padding: 14px 16px 4px;
    font-size: 11px; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: #6d7787;
}
.sidebar-foot {
    margin-top: auto; padding: 12px 16px;
    font-size: 12px; color: #6d7787;
    border-top: 1px solid rgba(255,255,255,.08);
}

/* Backdrop behind the open drawer. */
#nav-scrim { position: fixed; inset: 0; background: rgba(16,19,26,.45); z-index: 65; display: none; }
#nav-scrim.on { display: block; }

/* ---------- Navigation items (top bar, More menu, drawer) ---------- */
.nav-item {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 16px;
    min-height: 40px;
    color: #c8ceda; font-size: 14px;
    cursor: pointer; border-left: 3px solid transparent;
    transition: background var(--speed), color var(--speed);
}
.nav-item:hover { background: rgba(255,255,255,.06); color: #fff; text-decoration: none; }
.nav-item.active {
    background: rgba(27,110,224,.18);
    border-left-color: var(--primary);
    color: #fff;
}
.nav-item .ico { width: 20px; text-align: center; font-size: 15px; flex-shrink: 0; }

/* ---------- Topbar: one row, sticky ----------
   Identity, navigation and the session's own tools all share the dark
   ground the navigation has always used. No second row: the height it
   used to take is height the grids below now get. */
.topbar {
    display: flex; align-items: center; gap: 12px;
    background: #10131a;
    min-height: var(--topbar-h);
    padding: 0 14px 0 22px;
    position: sticky; top: 0; z-index: 60;
}

.tb-brand {
    display: flex; align-items: center; gap: 10px;
    /* Once you are signed in this is the least useful thing on the bar,
       so it is the first to give ground: the name ellipses away and the
       mark stays. */
    flex: 0 3 auto; min-width: 0;
    color: #fff; font-size: 15px; font-weight: 600; text-decoration: none;
}
.tb-brand:hover { color: #fff; text-decoration: none; }
.tb-brand .logo {
    width: 28px; height: 28px; border-radius: 7px;
    background: var(--primary); color: #fff;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 12.5px; font-weight: 700; letter-spacing: .5px; flex-shrink: 0;
}
.tb-brand-name { white-space: nowrap; max-width: 230px; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* The navigation holds its size. Its items cannot wrap and cannot be
   made shorter, so a narrowed .topnav does not narrow them - it lets
   them spill out of it and over whatever sits to its right. */
.topnav { display: flex; align-items: stretch; margin-left: 10px; flex-shrink: 0; }
.topnav .nav-item {
    min-height: var(--topbar-h);
    padding: 0 13px;
    border-left: 0;
    border-bottom: 3px solid transparent;
    white-space: nowrap;
}
.topnav .nav-item.active {
    background: rgba(27,110,224,.22);
    border-left-color: transparent;
    border-bottom-color: var(--primary);
    color: #fff;
}
.topnav .nav-item .ico { font-size: 14px; width: 16px; }

/* The overflow menu: everything that is not an everyday destination. */
.nav-more { position: relative; display: flex; }
.nav-more-btn { background: none; border: 0; font: inherit; }
.nav-more-btn .caret { font-size: 10px; margin-left: 1px; }
.nav-menu {
    position: absolute; top: 100%; left: 0;
    min-width: 236px;
    background: #10131a;
    border: 1px solid rgba(255,255,255,.10);
    border-radius: 0 0 var(--radius) var(--radius);
    box-shadow: var(--shadow-lg);
    padding: 6px 0; z-index: 75;
}
.nav-menu .nav-item { min-height: 38px; padding: 8px 16px; }
.nav-menu-section {
    padding: 11px 16px 4px;
    font-size: 11px; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: #6d7787;
}

.topbar-spacer { flex: 1; }

/* ---------- Topbar right: search, who you are, the way out ----------
   These sit on the dark bar now, so they are drawn for it. None of them
   may squash the navigation, so the give in the row comes from them
   instead: the search narrows to a floor it is still usable at and the
   names ellipse. The responsive rules at the end of the file take them
   away altogether in order of least use. */
.global-search { position: relative; flex: 0 1 240px; min-width: 130px; }
/* The base input rule is defined further down the file, so this needs
   the extra specificity or the magnifier sits on top of the text. */
.topbar .global-search input {
    width: 100%; padding-left: 32px;
    background: rgba(255,255,255,.07);
    border-color: rgba(255,255,255,.2);
    color: #fff;
}
.topbar .global-search input::placeholder { color: var(--text-3); }
/* Typing turns the box back into an ordinary field, so what you have
   typed reads the way it does everywhere else in the app. The border
   is restated because the rule above outranks the shared :focus one. */
.topbar .global-search input:focus {
    background: var(--surface); color: var(--text);
    border-color: var(--primary);
}
.global-search .ico { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--text-3); }

.user-chip {
    display: flex; align-items: center; gap: 8px;
    flex: 0 2 auto; min-width: 0;
    font-size: var(--fs-sm); color: #c8ceda;
    padding: 5px 8px; border-radius: var(--radius-sm);
    white-space: nowrap;
}
.user-chip .avatar {
    width: 32px; height: 32px; border-radius: 50%;
    background: var(--primary-soft); color: var(--primary-deep);
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 12.5px; flex-shrink: 0;
}
/* A long name is cut short rather than allowed to push the chip into
   the navigation; the initials are what identify the session anyway. */
.user-chip .user-name { color: #fff; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* Name and role share a line, so the role needs something to part it
   from the name. */
.user-chip .user-role { color: #8b95a1; flex-shrink: 0; }
.user-chip .user-role::before { content: "·"; margin-right: 7px; }

.topbar .btn {
    flex-shrink: 0;
    background: transparent; color: #c8ceda;
    border-color: rgba(255,255,255,.22);
}
.topbar .btn:hover { background: rgba(255,255,255,.08); color: #fff; }

.hamburger { display: none; }

/* ---------- Cards / panels ---------- */
.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    margin-bottom: 16px;
}
.card-head {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 12px var(--pad);
    border-bottom: 1px solid var(--border);
}
.card-head h3 { margin: 0; }
.card-head .spacer { flex: 1; }
.card-body { padding: var(--pad); }
.card-body.flush { padding: 0; }
.card-foot { padding: 10px var(--pad); border-top: 1px solid var(--border); }

/* Stat cards */
.stat-row { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); margin-bottom: 16px; }
.stat-card {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); box-shadow: var(--shadow);
    padding: 12px 14px;
}
.stat-card .lbl { font-size: 12.5px; color: var(--text-3); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; }
.stat-card .val { font-size: 21px; font-weight: 700; margin-top: 3px; font-variant-numeric: tabular-nums; }
.stat-card .sub { font-size: var(--fs-sm); color: var(--text-2); margin-top: 2px; }

/* ---------- Grid helpers ---------- */
.grid { display: grid; gap: 16px; }
.grid.cols-2 { grid-template-columns: 1fr 1fr; }
.grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 1100px) { .grid.cols-2, .grid.cols-3 { grid-template-columns: 1fr; } }

.screen-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.screen-head h1 { margin: 0; }
.screen-head .spacer { flex: 1; }
.screen-sub { color: var(--text-2); font-size: var(--fs-sm); margin: -8px 0 14px; }

/* ---------- Buttons ---------- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    font: inherit; font-size: 14px; font-weight: 600;
    min-height: 38px; padding: 7px 15px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-strong);
    background: var(--surface); color: var(--text);
    cursor: pointer; user-select: none;
    transition: background var(--speed), border-color var(--speed), color var(--speed);
    white-space: nowrap;
}
.btn:hover { background: var(--surface-2); text-decoration: none; }
.btn.primary { background: var(--primary); border-color: var(--primary); color: #fff; }
.btn.primary:hover { background: var(--primary-deep); border-color: var(--primary-deep); }
.btn.danger { color: var(--red); border-color: #eac6c4; }
.btn.danger:hover { background: var(--red-soft); }
.btn.ghost { border-color: transparent; background: transparent; color: var(--primary); }
.btn.ghost:hover { background: var(--primary-soft); }
.btn.sm { min-height: 30px; padding: 3px 10px; font-size: 13px; }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn-ai { color: var(--violet); border-color: #d9cff6; }
.btn-ai:hover { background: var(--violet-soft); }

/* ---------- Forms: compact, content-width ---------- */
label { font-size: var(--fs-sm); font-weight: 600; color: var(--text-2); display: block; margin-bottom: 3px; }
input[type="text"], input[type="number"], input[type="date"], input[type="email"],
input[type="password"], input[type="time"], input[type="search"], select, textarea {
    font: inherit; font-size: 14px;
    color: var(--text); background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    padding: 7px 9px; min-height: 38px;
    transition: border-color var(--speed), box-shadow var(--speed);
    max-width: 100%;
}
textarea { min-height: 74px; line-height: 1.45; }
input:focus, select:focus, textarea:focus {
    outline: none; border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(27,110,224,.16);
}
input[readonly], .field-ro { background: var(--surface-2); color: var(--text-2); }
input.num, td.num input { text-align: right; font-variant-numeric: tabular-nums; }

/* Field-width rule: size to content, never full width by default */
.w-3ch  { width: 4.8em; }
.w-4ch  { width: 5.6em; }
.w-6ch  { width: 7.2em; }
.w-8ch  { width: 9em; }
.w-12ch { width: 12.5em; }
.w-16ch { width: 16em; }
.w-24ch { width: 24em; }
.w-full { width: 100%; }

/* One-line field flow, like an Excel row */
.frow { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: flex-end; margin-bottom: 12px; }
.frow:last-child { margin-bottom: 0; }
.fcol { display: flex; flex-direction: column; }
.fhint { font-size: 12px; color: var(--text-3); margin-top: 3px; }
.fset { border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; margin: 0 0 14px; }
.fset legend { font-size: var(--fs-sm); font-weight: 700; color: var(--text-2); padding: 0 6px; }

.switch { position: relative; display: inline-flex; align-items: center; gap: 8px; cursor: pointer; min-height: 28px; }
.switch input { position: absolute; opacity: 0; }
.switch .track {
    width: 40px; height: 22px; border-radius: 11px;
    background: var(--border-strong); transition: background var(--speed);
    flex-shrink: 0; position: relative;
}
.switch .track::after {
    content: ""; position: absolute; top: 2px; left: 2px;
    width: 18px; height: 18px; border-radius: 50%;
    background: #fff; box-shadow: var(--shadow);
    transition: left var(--speed);
}
.switch input:checked + .track { background: var(--green); }
.switch input:checked + .track::after { left: 20px; }
.switch input:focus-visible + .track { outline: 3px solid var(--primary); outline-offset: 1px; }
.switch .sw-label { font-size: 14px; font-weight: 500; color: var(--text); }

/* ---------- Tags (the ONLY colored decoration) ---------- */
.tag {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 12px; font-weight: 700; line-height: 1;
    padding: 4px 8px; border-radius: 10px;
    white-space: nowrap;
}
.tag.gray   { background: var(--gray-tag-soft); color: var(--gray-tag); }
.tag.blue   { background: var(--primary-soft);  color: var(--primary-deep); }
.tag.green  { background: var(--green-soft);    color: var(--green); }
.tag.red    { background: var(--red-soft);      color: var(--red); }
.tag.amber  { background: var(--amber-soft);    color: var(--amber); }
.tag.violet { background: var(--violet-soft);   color: var(--violet); }
.tag.dot::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.txt-green { color: var(--green); font-weight: 600; }
.txt-red   { color: var(--red);   font-weight: 600; }
.txt-mut   { color: var(--text-3); }
.txt-sm    { font-size: var(--fs-sm); }
.edited-tag { font-size: 10.5px; padding: 2px 6px; border-radius: 8px; background: var(--amber-soft); color: var(--amber); font-weight: 700; }

/* ---------- Tables ---------- */
.tbl-wrap { overflow-x: auto; }
table.tbl { width: 100%; border-collapse: collapse; font-size: 14px; }
.tbl th, .tbl td { padding: 8px 10px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: middle; }
.tbl th {
    font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
    color: var(--text-3); background: var(--surface-2);
    position: sticky; top: 0; z-index: 2;
}
/* A heading takes a second line rather than widening the column it
   names: it breaks at its spaces, and a .nowrap the grid puts on its
   cells cannot hold it on one line. Bottom alignment keeps a one-line
   and a two-line heading in the same row reading off the same line. */
.tbl thead th {
    white-space: normal;
    overflow-wrap: break-word;
    line-height: 1.25;
    vertical-align: bottom;
}
/* A row header - the label down the left of a key-and-value card, not
   the title of a column - keeps the single line it has always had. */
.tbl tbody th { white-space: nowrap; }
.tbl th.sortable { cursor: pointer; user-select: none; }
.tbl th.sortable:hover { color: var(--text); }
.tbl th .arrow { font-size: 10px; margin-left: 3px; }
/* .num says the cell carries a figure, so it right-aligns wherever it
   sits - heading, row or total row - and the heading lands over the
   digits instead of at the far side of the column it names. */
.tbl th.num, .tbl td.num { text-align: right; font-variant-numeric: tabular-nums; }
/* .right is a class on its own, so inside a table it loses to the
   left-aligned th/td rule above: a "Totals" label written to finish
   beside the figures starts its span instead. Headings and total rows
   get it back; the rows themselves keep the alignment they have. */
.tbl th.right, .tbl tfoot td.right { text-align: right; }
.tbl tbody tr { transition: background var(--speed); }
.tbl tbody tr:hover { background: var(--surface-2); }
.tbl tbody tr.clickable { cursor: pointer; }
.tbl tfoot td { font-weight: 700; background: var(--surface-2); border-top: 2px solid var(--border-strong); }
.tbl .row-actions { white-space: nowrap; text-align: right; }
.tbl .row-actions a { margin-left: 10px; font-size: var(--fs-sm); }
tr.flash-save { animation: flashSave 1.1s ease-out; }
@keyframes flashSave { 0% { background: var(--green-soft); } 100% { background: transparent; } }

/* Editable grid cells (Excel-like) */
.tbl td.cell-edit { padding: 2px 4px; }
.tbl td.cell-edit input, .tbl td.cell-edit select { border-color: transparent; background: transparent; min-height: 32px; }
.tbl td.cell-edit input:hover, .tbl td.cell-edit select:hover { border-color: var(--border-strong); background: var(--surface); }
.tbl td.cell-edit input:focus, .tbl td.cell-edit select:focus { border-color: var(--primary); background: var(--surface); }

/* Table chrome: search / pagination */
.tbl-chrome { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 10px var(--pad); }
.tbl-chrome .spacer { flex: 1; }
.tbl-chrome input[type="search"] { width: 220px; }
.tbl-pager { display: flex; align-items: center; gap: 6px; font-size: var(--fs-sm); color: var(--text-2); padding: 10px var(--pad); flex-wrap: wrap; }
.tbl-pager .spacer { flex: 1; }
.tbl-pager button {
    min-width: 34px; min-height: 34px; border: 1px solid var(--border-strong);
    background: var(--surface); border-radius: var(--radius-sm);
    font: inherit; font-size: 13px; cursor: pointer;
}
.tbl-pager button.cur { background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 700; }
.tbl-pager button:disabled { opacity: .4; cursor: default; }
.tbl-pager select { min-height: 34px; padding: 4px 6px; }
.tbl-empty { padding: 34px; text-align: center; color: var(--text-3); }

/* ---------- Filter bar ---------- */
.filterbar {
    display: flex; flex-wrap: wrap; gap: 8px 10px; align-items: flex-end;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 10px 12px; margin-bottom: 14px;
}
.filterbar .fcol label { margin-bottom: 2px; }
.filterbar .range-pair { display: flex; align-items: center; gap: 5px; }
.filterbar .range-pair span { color: var(--text-3); font-size: 13px; }
.filterbar .fb-clear { margin-left: auto; }

/* ---------- Tabs ---------- */
.tabs { display: flex; gap: 2px; border-bottom: 2px solid var(--border); margin-bottom: 16px; overflow-x: auto; }
.tabs .tab {
    padding: 10px 16px; min-height: 44px;
    font-size: 14px; font-weight: 600; color: var(--text-2);
    border: 0; background: none; cursor: pointer;
    border-bottom: 3px solid transparent; margin-bottom: -2px;
    white-space: nowrap; font-family: inherit;
    transition: color var(--speed), border-color var(--speed);
}
.tabs .tab:hover { color: var(--text); }
.tabs .tab.active { color: var(--primary); border-bottom-color: var(--primary); }
.tab-pane { animation: fadeIn var(--speed) ease-out; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: none; } }

/* ---------- Pipeline board ---------- */
.kanban { display: flex; gap: 12px; overflow-x: auto; padding-bottom: 10px; align-items: flex-start; }
.kanban-col {
    min-width: 250px; width: 250px; flex-shrink: 0;
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: var(--radius);
}
.kanban-col-head {
    display: flex; align-items: center; gap: 8px;
    padding: 10px 12px; border-bottom: 1px solid var(--border);
    font-size: 13px; font-weight: 700;
}
.kanban-col-head .cnt { margin-left: auto; color: var(--text-3); font-weight: 600; }
.kanban-cards { padding: 8px; display: flex; flex-direction: column; gap: 8px; min-height: 40px; }
.kanban-card {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius-sm); box-shadow: var(--shadow);
    padding: 10px 11px; cursor: pointer;
    transition: box-shadow var(--speed), transform var(--speed);
}
.kanban-card:hover { box-shadow: var(--shadow-lg); transform: translateY(-1px); }
.kanban-card .kc-no { font-weight: 700; font-size: 13.5px; }
.kanban-card .kc-title { font-size: 13px; color: var(--text-2); margin: 2px 0 6px; }
.kanban-card .kc-foot { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-3); }
.kanban-card .kc-foot .amt { margin-left: auto; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }

/* ---------- Labor phone dashboard ---------- */
.labor-page { max-width: 560px; margin: 0 auto; }
.labor-greet { padding: 6px 2px 14px; }
.labor-greet .hi { font-size: 21px; font-weight: 700; }
.labor-greet .dt { color: var(--text-2); font-size: 15px; }
.labor-sect { font-size: 13px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--text-3); margin: 18px 2px 8px; }
.task-card {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: 12px; box-shadow: var(--shadow);
    padding: 16px; margin-bottom: 12px;
}
.task-card .tc-code { font-size: 16px; font-weight: 800; }
.task-card .tc-desc { font-size: 15.5px; margin: 2px 0; }
.task-card .tc-proj { font-size: 13.5px; color: var(--text-2); margin-bottom: 10px; }
.task-card .tc-timer {
    font-family: var(--mono); font-size: 34px; font-weight: 700;
    text-align: center; margin: 8px 0 12px; letter-spacing: 2px;
    font-variant-numeric: tabular-nums;
}
.task-card .tc-total { font-size: 13.5px; color: var(--text-2); text-align: center; margin-bottom: 10px; }
.btn-timer {
    display: block; width: 100%; min-height: 72px;
    font-size: 24px; font-weight: 800; letter-spacing: 1px;
    border: 0; border-radius: 12px; cursor: pointer; font-family: inherit;
    transition: filter var(--speed);
}
.btn-timer:active { filter: brightness(.92); }
.btn-timer.start { background: var(--green); color: #fff; }
.btn-timer.end { background: var(--red); color: #fff; }
.tc-complete-row { text-align: right; margin-top: 10px; }
.tc-complete-row a { font-size: 13px; color: var(--text-3); text-decoration: underline; }

/* ---------- Modal / drawer / toast ---------- */
.overlay {
    position: fixed; inset: 0; background: rgba(16, 19, 26, .45);
    z-index: 90; animation: fadeIn var(--speed);
}
.modal {
    position: fixed; z-index: 95; top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    background: var(--surface); border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    width: min(560px, calc(100vw - 32px));
    max-height: calc(100vh - 60px); overflow: auto;
    animation: popIn var(--speed) ease-out;
}
.modal.wide { width: min(880px, calc(100vw - 32px)); }
@keyframes popIn { from { opacity: 0; transform: translate(-50%, -48%); } to { opacity: 1; transform: translate(-50%, -50%); } }
.modal-head { display: flex; align-items: center; padding: 14px 18px; border-bottom: 1px solid var(--border); }
.modal-head h3 { margin: 0; flex: 1; }
.modal-body { padding: 18px; }
.modal-foot { display: flex; justify-content: flex-end; gap: 10px; padding: 13px 18px; border-top: 1px solid var(--border); }
.modal-x { border: 0; background: none; font-size: 20px; cursor: pointer; color: var(--text-3); min-width: 36px; min-height: 36px; }
.confirm-sentence { font-size: 16px; line-height: 1.55; }

.drawer {
    position: fixed; z-index: 95; top: 0; right: 0; bottom: 0;
    width: min(480px, 94vw);
    background: var(--surface); box-shadow: var(--shadow-lg);
    display: flex; flex-direction: column;
    animation: slideIn 200ms ease-out;
}
@keyframes slideIn { from { transform: translateX(30px); opacity: 0; } to { transform: none; opacity: 1; } }
.drawer-head { display: flex; align-items: center; padding: 14px 18px; border-bottom: 1px solid var(--border); }
.drawer-head h3 { margin: 0; flex: 1; }
.drawer-body { padding: 18px; overflow-y: auto; flex: 1; }

.toast-root { position: fixed; right: 18px; bottom: 18px; z-index: 120; display: flex; flex-direction: column; gap: 8px; }
.toast {
    background: #1f2733; color: #fff;
    border-radius: var(--radius-sm); box-shadow: var(--shadow-lg);
    padding: 11px 16px; font-size: 14px;
    display: flex; align-items: center; gap: 9px;
    max-width: 380px; animation: toastIn 200ms ease-out;
}
@keyframes toastIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.toast.ok::before { content: "✓"; color: #5ad8a6; font-weight: 800; }
.toast.err::before { content: "!"; color: #ff8a80; font-weight: 800; }
.toast.info::before { content: "i"; color: #8ab8ff; font-weight: 800; font-style: italic; }

/* ---------- Loaders ---------- */
.skel { position: relative; overflow: hidden; background: var(--gray-tag-soft); border-radius: var(--radius-sm); min-height: 14px; }
.skel::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.75), transparent);
    animation: shimmer 1.15s infinite;
}
@keyframes shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
.spinner {
    width: 22px; height: 22px; border-radius: 50%;
    border: 3px solid var(--border); border-top-color: var(--primary);
    animation: spin .7s linear infinite; display: inline-block;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading-block { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 36px; color: var(--text-2); }

/* ---------- Stepper (import wizard) ---------- */
.stepper { display: flex; gap: 0; margin-bottom: 18px; overflow-x: auto; }
.step { display: flex; align-items: center; gap: 9px; padding: 0 18px 0 0; flex-shrink: 0; }
.step .s-num {
    width: 34px; height: 34px; border-radius: 50%;
    background: var(--gray-tag-soft); color: var(--text-2);
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 14px; flex-shrink: 0;
}
.step.done .s-num { background: var(--green-soft); color: var(--green); }
.step.cur .s-num { background: var(--primary); color: #fff; }
.step .s-lbl { font-size: 13.5px; font-weight: 600; color: var(--text-2); white-space: nowrap; }
.step.cur .s-lbl { color: var(--text); }
.step:not(:last-child)::after { content: ""; width: 34px; height: 2px; background: var(--border-strong); margin-left: 16px; }

/* ---------- Timeline (logs) ---------- */
.timeline { list-style: none; margin: 0; padding: 0 0 0 18px; border-left: 2px solid var(--border); }
.timeline li { position: relative; padding: 0 0 16px 16px; }
.timeline li::before {
    content: ""; position: absolute; left: -23px; top: 4px;
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--surface); border: 2px solid var(--primary);
}
.timeline .tl-when { font-size: 12.5px; color: var(--text-3); }

/* ---------- Waterfall / variance rows ---------- */
.variance-link { cursor: pointer; }
.variance-link:hover { text-decoration: underline; }

/* ---------- Document preview (quote / PO paper) ---------- */
.doc-paper {
    background: #fff; border: 1px solid var(--border);
    box-shadow: var(--shadow); border-radius: 4px;
    max-width: 820px; margin: 0 auto; padding: 40px 46px;
    font-size: 14px; line-height: 1.5;
}
.doc-paper .doc-head { display: flex; justify-content: space-between; gap: 20px; border-bottom: 3px solid var(--text); padding-bottom: 14px; margin-bottom: 18px; }
.doc-paper h2 { letter-spacing: .03em; }
.doc-paper table { width: 100%; border-collapse: collapse; margin: 10px 0; }
.doc-paper th, .doc-paper td { border: 1px solid var(--border-strong); padding: 6px 9px; font-size: 13px; }
.doc-paper th { background: var(--surface-2); text-align: left; }
/* The document aligns its own figures with the .right and .center
   utilities, which this table's heading rule outranks - so Qty, Unit
   and Amount would print their titles over the wrong edge of the
   columns beneath them. */
.doc-paper th.right { text-align: right; }
.doc-paper th.center { text-align: center; }
.doc-editable { border: 1px dashed var(--border-strong); border-radius: var(--radius-sm); padding: 9px 11px; background: #fffdf4; }
.doc-editable:focus { outline: 2px solid var(--primary); background: #fff; }

/* ---------- Login ---------- */
.login-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; background: var(--bg); }
.login-card { width: min(400px, calc(100vw - 32px)); background: var(--surface); border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow-lg); padding: 30px; }

/* ---------- Utility ---------- */
.mt-0 { margin-top: 0; } .mb-0 { margin-bottom: 0; }
.mt-1 { margin-top: 8px; } .mb-1 { margin-bottom: 8px; }
.mt-2 { margin-top: 16px; } .mb-2 { margin-bottom: 16px; }
.flex { display: flex; align-items: center; gap: 10px; }
.flex .spacer { flex: 1; }
.right { text-align: right; }
.center { text-align: center; }
.nowrap { white-space: nowrap; }
.hidden { display: none !important; }
.avatar-sm {
    width: 26px; height: 26px; border-radius: 50%;
    background: var(--primary-soft); color: var(--primary-deep);
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 11px; flex-shrink: 0;
}
.color-dot { width: 12px; height: 12px; border-radius: 50%; display: inline-block; vertical-align: -1px; margin-right: 5px; }
.kv { display: grid; grid-template-columns: auto 1fr; gap: 5px 16px; font-size: 14px; }
.kv dt { color: var(--text-3); font-weight: 600; }
.kv dd { margin: 0; font-variant-numeric: tabular-nums; }

/* ---------- Responsive ----------
   One row means everything competes for the same width. Between the
   breakpoints the bar absorbs the squeeze itself - the two names ellipse
   and the search narrows, and none of that can put anything on top of
   anything else. The breakpoints are for what narrowing cannot save, and
   they give up the pieces in order of least use: the org name shortens
   and the role drops first, then the search, and only at 980px does the
   menu itself collapse into the drawer and the hamburger appear. */
@media (max-width: 1320px) {
    .tb-brand-name { max-width: 150px; }
    .global-search { flex-basis: 170px; }
    .user-chip .user-role { display: none; }
}
/* Narrower still and the menu and the search cannot both fit. The menu
   wins, since the search is a shortcut to places the menu also
   reaches. */
@media (max-width: 1120px) {
    .global-search { display: none; }
}
/* With the menu in the drawer the bar is its own again, so the search
   comes back. */
@media (max-width: 980px) {
    .topnav { display: none; }
    .global-search { display: block; }
    .hamburger {
        display: inline-flex; order: -1;
        border: 1px solid rgba(255,255,255,.22);
        background: transparent; color: #fff; border-radius: var(--radius-sm);
        min-width: 42px; min-height: 42px; align-items: center; justify-content: center;
        font-size: 18px; cursor: pointer;
    }
}
@media (max-width: 900px) {
    .content { padding: 12px 12px 40px; }
    .global-search { display: none; }
    .topbar { padding: 0 12px; gap: 8px; }
    .user-chip { font-size: 12px; padding: 5px 4px; }
}
/* On a phone the chip is the avatar alone - the name is the only thing
   left to give up before the bar stops fitting. */
@media (max-width: 560px) {
    .tb-brand-name { display: none; }
    .user-chip .user-name { display: none; }
}

@media print {
    .sidebar, .topbar, .filterbar, .tbl-chrome, .tbl-pager, .btn, .tabs,
    .sel-bar, .sel-cell, #nav-scrim { display: none !important; }
    .content { padding: 0; }
    .card, .doc-paper { border: 0; box-shadow: none; }
    body { background: #fff; }
}

/* ============================================================
   Pre-Start alignment additions (branch PrestartTasks)
   ============================================================ */

/* Task groups + split-wizard section rows */
.tbl .group-row td {
    background: var(--surface-2);
    border-top: 2px solid var(--border-strong);
    font-size: var(--fs-sm);
}

/* Wide grids (Labor / MATEQ): first columns stay readable while scrolling */
.tbl-wrap { overflow-x: auto; }
.tbl .num-cell { font-family: var(--mono); }

/* Document preview: shows where a page break falls on the printed PDF */
.doc-pagebreak {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 20px 0 12px;
    font-size: 11px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-3);
}
.doc-pagebreak::before,
.doc-pagebreak::after {
    content: "";
    flex: 1;
    border-top: 1px dashed var(--border-strong);
}

/* ---- Wide tables: keep the horizontal scrollbar reachable ----
   On a long list the bar sits below the fold, so scrolling sideways
   means scrolling to the bottom first. Pinning the scroll container to
   the viewport keeps it on screen while the rows scroll inside it.
   The subtracted height is everything above the rows, the topbar
   included, so it follows the topbar whenever that changes. */
.tbl-wrap.sticky-x {
    max-height: calc(100vh - 224px);
    overflow: auto;
    overscroll-behavior-x: contain;
}
.tbl-wrap.sticky-x table.tbl { margin-bottom: 0; }
.tbl-wrap.sticky-x .tbl th { position: sticky; top: 0; z-index: 3; }
@media (max-width: 900px) {
    .tbl-wrap.sticky-x { max-height: calc(100vh - 170px); }
}

/* ---- Help dots: a "?" beside a field title, explanation on click ---- */
.help-dot {
    display: inline-flex; align-items: center; justify-content: center;
    width: 15px; height: 15px; padding: 0; margin-left: 5px;
    border: 1px solid var(--border-strong); border-radius: 50%;
    background: var(--surface); color: var(--text-3);
    font: 700 10px/1 var(--font); cursor: pointer;
    vertical-align: middle;
}
.help-dot:hover, .help-dot.open {
    background: var(--primary); border-color: var(--primary); color: #fff;
}
.help-bubble {
    position: absolute; z-index: 90; max-width: 280px;
    background: #10131a; color: #e8ebf0;
    padding: 8px 11px; border-radius: var(--radius-sm);
    font-size: var(--fs-sm); line-height: 1.45;
    box-shadow: var(--shadow-lg);
}

/* ---- Task status: a tag until you click it, then a picker ---- */
.status-cell { cursor: pointer; }
.status-cell select { max-width: 132px; }

/* Quote Log: numbers that are still free, shown the way the master
   register sheet does, but visibly not a real quote. */
.tbl tr.row-unused td { background: var(--surface-2); color: var(--text-3); }
.tbl tr.row-unused { cursor: default; }

/* Tiny inline action that sits beside a field label, e.g. the "+ Add"
   next to Customer on a new quote. */
.btn.xs {
    min-height: 20px; padding: 0 7px;
    font-size: 11.5px; font-weight: 600;
    margin-left: 6px; vertical-align: middle;
}

/* ---- Option rows ----
   For picking from a list: a real, visible checkbox or radio with its
   label. The .switch component deliberately hides its native input and
   draws a .track instead, which makes it wrong here: without a track
   there is nothing to see at all, and it does not stack into a list. */
.opt-row {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 8px 10px; margin: 5px 0;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    cursor: pointer; line-height: 1.4;
    transition: background var(--speed), border-color var(--speed);
}
.opt-row:hover { background: var(--surface-2); }
.opt-row input {
    width: 17px; height: 17px; margin: 1px 0 0; flex-shrink: 0;
    accent-color: var(--primary); cursor: pointer;
}
.opt-row input:disabled { cursor: not-allowed; }
.opt-row:has(input:checked) { border-color: var(--primary); background: var(--primary-soft); }
.opt-row:has(input:disabled) { opacity: .65; cursor: not-allowed; background: var(--surface-2); }
.opt-row .opt-label { font-size: 14px; color: var(--text); }
.opt-row .opt-note { display: block; font-size: 12.5px; color: var(--text-2); margin-top: 2px; }

/* Two columns when there are many options and the room allows it. */
.opt-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
@media (max-width: 720px) { .opt-grid { grid-template-columns: 1fr; } }

/* ============================================================
   Invoicing: the money tab, the custom-invoice builder,
   internal notes, and the markup percentage hints.
   ============================================================ */

/* Invoices carry more columns than payments and are what people work
   from, so they get the room rather than an even split. */
.money-grid { display: grid; gap: 16px; grid-template-columns: 1.9fr 1fr; align-items: start; }
@media (max-width: 1200px) { .money-grid { grid-template-columns: 1fr; } }

/* A markup box saying what percentage it works out to. */
.mk-hint {
    display: block;
    margin-top: 4px;
    font-size: var(--fs-sm);
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
}

/* --- the builder --- */
.inv-builder .card { margin-bottom: 16px; }

.inv-parties { display: grid; grid-template-columns: 1.4fr 1fr; gap: 26px; align-items: start; }
@media (max-width: 900px) { .inv-parties { grid-template-columns: 1fr; gap: 16px; } }

.inv-party > label { display: block; margin-bottom: 4px; }
.inv-party textarea { font-family: var(--font); line-height: 1.45; }

/* The job facts that are fixed: shown, not editable, except the P.O. */
.jobfacts { width: 100%; border-collapse: collapse; margin-top: 12px; }
.jobfacts td { padding: 4px 0; vertical-align: middle; border: 0; }
.jobfacts td.k {
    width: 78px; color: var(--text-3); font-size: var(--fs-sm);
    font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
}

/* The right-hand block, laid out like the printed document. */
.inv-meta { border-left: 3px solid var(--border); padding-left: 22px; }
@media (max-width: 900px) { .inv-meta { border-left: 0; padding-left: 0; } }
.inv-word {
    font-size: 26px; font-weight: 800; letter-spacing: .17em;
    color: var(--text); margin-bottom: 12px;
}
.inv-meta .frow { margin-bottom: 8px; }

/* --- the source strip --- */
.src-strip { max-height: 330px; overflow: auto; }
.tbl.compact th, .tbl.compact td { padding: 5px 9px; font-size: var(--fs-sm); }

/* Work another invoice already bills. Struck through and faded, but
   still readable - it is there to be seen, not hidden. */
.src-billed td { color: var(--text-3); }
.src-billed .src-desc { text-decoration: line-through; }

/* --- billed items --- */
#ib-items td { vertical-align: middle; }
#ib-items input { width: 100%; }
#ib-items tfoot .total-row td {
    background: var(--surface-2); font-size: var(--fs-lg);
    border-top: 2px solid var(--border-strong);
}
#ib-items .ib-empty td { padding: 0; }

/* --- internal notes --- */
.note-list { max-height: 300px; overflow: auto; margin-bottom: 14px; }
.note-item {
    border-left: 3px solid var(--border-strong);
    padding: 8px 0 8px 11px; margin-bottom: 10px;
}
.note-meta { font-size: var(--fs-sm); color: var(--text-3); margin-bottom: 3px; }
.note-body { line-height: 1.45; white-space: pre-wrap; }

/* ============================================================
   Row selection, searchable dropdowns, and the softer grid cell.
   ============================================================ */

/* ---- Ticking rows: highlight, and a bar that acts on them ----
   On a grid wide enough to scroll sideways the "remove" link ends up
   far from the description, so by the time you reach it you can no
   longer see what you are about to delete. A ticked row stays
   highlighted the whole way across, and the bar names every line it is
   about to remove before it removes anything. */
.tbl th.sel-cell, .tbl td.sel-cell {
    width: 36px; text-align: center;
    padding-left: 9px; padding-right: 4px;
    cursor: pointer;
}
/* The box at the head of the column is a control, not a heading, so it
   stays in the middle of the row however tall a wrapped heading beside
   it makes that row. */
.tbl thead th.sel-cell { vertical-align: middle; }
.tbl th.sel-cell input, .tbl td.sel-cell input {
    width: 16px; height: 16px; min-height: 0;
    cursor: pointer; accent-color: var(--primary);
    vertical-align: middle;
}
.tbl tbody tr.is-selected { background: var(--primary-soft); }
.tbl tbody tr.is-selected:hover { background: #dce9fa; }
.tbl tbody tr.is-selected > td { border-bottom-color: #c6dbf6; }
/* The first cell carries a marker so the row still reads as selected
   once it is scrolled a long way to the right. */
.tbl tbody tr.is-selected > td.sel-cell { box-shadow: inset 3px 0 0 var(--primary); }

.sel-bar { display: none; }
.sel-bar.on {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 9px var(--pad);
    background: var(--primary-soft);
    border-bottom: 1px solid #c6dbf6;
}
.sel-count { font-size: var(--fs-sm); color: var(--primary-deep); }
.sel-count b { font-size: var(--fs); }

/* What a bulk delete is about to take, spelled out. */
.sel-list {
    margin: 12px 0 0; padding-left: 20px;
    max-height: 220px; overflow: auto;
    font-size: var(--fs-sm); color: var(--text-2);
}
.sel-list li { margin-bottom: 3px; }

/* ---- A grid cell that is meant to be typed in, quietly ----
   Same as .cell-edit, but the box is outlined in the lightest grey at
   rest so it reads as an input without shouting. */
.tbl td.cell-edit input.cell-soft,
.tbl td.cell-edit select.cell-soft {
    border-color: var(--border);
    background: var(--surface);
}
.tbl td.cell-edit input.cell-soft:hover,
.tbl td.cell-edit select.cell-soft:hover { border-color: var(--border-strong); }

/* ---- Searchable dropdowns (MS.select) ----
   The native <select> stays in the DOM and keeps the value; this is the
   filter box in front of it. */
.ss { position: relative; display: inline-block; max-width: 100%; align-self: flex-start; }
.ss.ss-full { display: block; width: 100%; align-self: stretch; }
.ss > select {
    position: absolute; left: 0; bottom: 0;
    width: 1px; height: 1px; min-height: 0; padding: 0;
    opacity: 0; pointer-events: none; border: 0;
}
.ss-input { padding-right: 24px; }
.ss::after {
    content: "▾";
    position: absolute; right: 9px; top: 50%; transform: translateY(-50%);
    font-size: 10px; color: var(--text-3); pointer-events: none;
}
.ss-menu {
    position: absolute; z-index: 200;
    top: calc(100% + 3px); left: 0;
    min-width: 100%; max-width: min(420px, 80vw);
    max-height: 268px; overflow: auto;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg);
    display: none;
}
.ss.is-open .ss-menu { display: block; }
.ss-opt {
    padding: 7px 11px; font-size: 14px; cursor: pointer;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ss-opt:hover, .ss-opt.is-active { background: var(--primary-soft); }
.ss-opt.is-current { font-weight: 600; }
.ss-none { padding: 9px 11px; font-size: var(--fs-sm); color: var(--text-3); }

/* Inside a modal the menu has to clear the dialog's own stacking. */
.modal .ss-menu, .drawer .ss-menu { z-index: 200; }

/* ============================================================
   The pointer, everywhere something is actually clickable.
   Named controls set it one at a time above, which is how some of
   them came to be missed; these rules catch what is left by what
   the element is, not by what it was called.
   ============================================================ */

/* A button is a click by definition, but the browser draws an arrow
   over it. This covers the pager, the modal close, the hamburger and
   anything else built without the .btn class. */
button { cursor: pointer; }
button:disabled { cursor: not-allowed; }

/* An anchor with no href is this app's inline row action - "edit",
   "remove", "pay", "resend" - and the browser gives it no cursor at
   all, since as far as it knows the link goes nowhere. */
a:not([href]) { cursor: pointer; }

/* Ticks and radios wherever they sit: the buy-list column, the copy
   dialog, the labor columns picker. */
input[type="checkbox"], input[type="radio"] { cursor: pointer; }
input[type="checkbox"]:disabled, input[type="radio"]:disabled { cursor: not-allowed; }

/* A switch that cannot be moved must not offer to move. The label
   carries the cursor for the whole control, so it is the label that
   has to say no. */
.switch:has(input:disabled) { cursor: not-allowed; }

/* ============================================================
   Status master data, global search, text cells, the expandable
   Labor grid, invoice line details, and the phone.
   ============================================================ */

/* ---- Text cells: wrapped text that turns into a textarea on click ---- */
.txt-cell {
    white-space: pre-wrap; overflow-wrap: anywhere;
    min-width: 150px; max-width: 460px;
    padding: 6px 8px; line-height: 1.4; font-size: 14px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); cursor: text;
    transition: border-color var(--speed), background var(--speed);
}
.txt-cell:hover { border-color: var(--border-strong); }
.txt-cell:focus-visible { outline: 3px solid var(--primary); outline-offset: 1px; }
.txt-cell.is-empty { color: var(--text-3); font-style: italic; }
.txt-cell.is-editing { padding: 0; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(27,110,224,.16); }
.txt-cell-edit {
    display: block; width: 100%; min-height: 40px; resize: vertical;
    border: 0; padding: 6px 8px; font: inherit; font-size: 14px; line-height: 1.4;
    background: transparent;
}
.txt-cell-edit:focus { outline: none; box-shadow: none; border: 0; }
.tbl td.cell-text { padding: 3px 4px; vertical-align: top; }

/* ---- Status colour swatches (Master Data) ---- */
.sw-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-height: 38px; }
.sw-btn {
    width: 26px; height: 26px; border-radius: 50%; padding: 0;
    border: 3px solid transparent; box-shadow: 0 0 0 1px var(--border-strong);
    cursor: pointer; transition: transform var(--speed);
}
.sw-btn:hover { transform: scale(1.1); }
.sw-btn.on { border-color: #fff; box-shadow: 0 0 0 2px var(--text); }
.sw-gray   { background: var(--gray-tag); }
.sw-blue   { background: var(--primary); }
.sw-green  { background: var(--green); }
.sw-amber  { background: var(--amber); }
.sw-red    { background: var(--red); }
.sw-violet { background: var(--violet); }
.sw-custom { display: inline-flex; align-items: center; gap: 5px; margin: 0; font-weight: 500; }
.sw-custom input[type="color"] { width: 30px; height: 26px; padding: 0; border: 1px solid var(--border-strong); border-radius: 6px; background: none; cursor: pointer; }

/* ---- Global search: the suggestion menu and the results page ---- */
.gs-menu {
    position: absolute; top: calc(100% + 5px); left: 0; right: 0;
    min-width: 380px; max-width: min(520px, calc(100vw - 24px));
    background: var(--surface); color: var(--text);
    border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg); z-index: 85; overflow: hidden;
}
.gs-menu[hidden] { display: none; }
.hit {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 8px 12px; border-bottom: 1px solid var(--border);
    color: var(--text); text-decoration: none; text-align: left;
}
.hit:last-child { border-bottom: 0; }
.hit:hover, .hit.is-active { background: var(--primary-soft); text-decoration: none; }
.hit-ico { width: 22px; text-align: center; color: var(--text-3); flex-shrink: 0; padding-top: 2px; }
.hit-body { flex: 1; min-width: 0; }
.hit-title { display: block; font-weight: 600; overflow-wrap: anywhere; }
.hit-amt { font-weight: 600; color: var(--text-2); margin-left: 6px; font-size: 13px; font-variant-numeric: tabular-nums; }
.hit-sub { display: block; font-size: 13px; color: var(--text-2); overflow-wrap: anywhere; }
.hit-where { display: block; font-size: 12px; color: var(--text-3); }
.hit-kind { flex-shrink: 0; }
.gs-more {
    display: block; width: 100%; border: 0; background: var(--surface-2);
    padding: 9px 12px; font: inherit; font-size: 13px; font-weight: 600; color: var(--primary);
    text-align: left; border-top: 1px solid var(--border);
}
.gs-more:hover { background: var(--primary-soft); }
.gs-none { padding: 12px; color: var(--text-3); font-size: 13px; }
.search-screen .hits .hit { padding: 10px 14px; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
    border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-2);
    border-radius: 14px; padding: 4px 11px; font: inherit; font-size: 13px; cursor: pointer;
}
.chip b { color: var(--text); }
.chip.on { background: var(--primary); border-color: var(--primary); color: #fff; }
.chip.on b { color: #fff; }

/* The search button that stands in for the box on a narrow bar. */
.tb-search-btn {
    display: none; flex-shrink: 0;
    border: 1px solid rgba(255,255,255,.22); background: transparent; color: #fff;
    border-radius: var(--radius-sm); min-width: 42px; min-height: 42px;
    align-items: center; justify-content: center; font-size: 16px; cursor: pointer;
}
@media (max-width: 1120px) and (min-width: 981px) {
    .tb-search-btn { display: inline-flex; }
}
@media (max-width: 900px) {
    .tb-search-btn { display: inline-flex; }
}
/* Opened from the button: the box takes the full width under the bar. */
.topbar.search-open .global-search {
    display: block; position: absolute; left: 8px; right: 8px;
    top: calc(var(--topbar-h) - 6px); flex: none; min-width: 0; z-index: 85;
}
.topbar.search-open .global-search input {
    background: var(--surface); color: var(--text); border-color: var(--primary);
    min-height: 44px; font-size: 16px;
}
.topbar.search-open .gs-menu { min-width: 0; max-width: none; }

/* ---- The Labor grid: every chosen column on the row, no arrow ----
   Headings wrap word by word (width: 1% asks the browser for the least
   a column can be), so a column is only as wide as the widest figure or
   word in it and the whole sheet fits the page; Details takes the room
   that is left. */
.lb-task { font-weight: 700; }
.lb-amt { color: var(--primary-deep); font-weight: 700; }
.tbl.lb-inline th { width: 1%; white-space: normal; overflow-wrap: normal; word-break: normal; line-height: 1.15; padding-left: 5px; padding-right: 5px; }
.tbl.lb-inline th.lb-wide { width: auto; }
.tbl.lb-inline th.sel-cell { width: 34px; }
.tbl.lb-inline td { padding-left: 5px; padding-right: 5px; }
.tbl.lb-inline td.num, .tbl.lb-inline td.nowrap { white-space: nowrap; }
.tbl.lb-inline td.cell-edit input { width: 4.6em; min-height: 32px; padding: 3px 4px; }
.tbl.lb-inline td.cell-text .txt-cell { min-width: 110px; }
.tbl.lb-inline .avatar-sm { display: none; }
.tbl.lb-inline td.num { font-size: 13.5px; }
.tbl td.lb-expand, .tbl th.lb-expand { width: 34px; padding-left: 4px; padding-right: 4px; text-align: center; }
.lb-arrow {
    border: 0; background: none; padding: 4px; min-width: 28px; min-height: 28px;
    font-size: 15px; color: var(--text-2); cursor: pointer; border-radius: var(--radius-sm);
    transition: transform var(--speed), background var(--speed);
}
.lb-arrow:hover { background: var(--primary-soft); color: var(--primary-deep); }
tr.is-open .lb-arrow { transform: rotate(90deg); }
tr.lb-detail td { background: var(--surface-2); padding: 8px 14px 12px 44px; border-bottom: 1px solid var(--border-strong); }
tr.lb-detail.is-selected td { background: var(--primary-soft); }
.lb-kv { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px 18px; }
.lb-kv .k { display: block; font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-3); font-weight: 600; margin-bottom: 2px; }
.lb-kv .v { font-size: 14px; font-variant-numeric: tabular-nums; }
.lb-kv input { min-height: 32px; }
.lb-locked { font-size: var(--fs-sm); color: var(--amber); cursor: help; }
.lb-note { padding: 8px var(--pad); background: var(--amber-soft); color: var(--amber); font-size: var(--fs-sm); border-bottom: 1px solid var(--border); }

/* ---- Invoice lines: numbering, the tax tick, and the job's money ---- */
#ib-items td.ib-num { color: var(--text-3); font-size: 12px; text-align: right; width: 30px; padding-right: 4px; font-variant-numeric: tabular-nums; }
#ib-items td.ib-tax { text-align: center; width: 52px; }
#ib-items td.ib-tax input { width: 17px; height: 17px; min-height: 0; accent-color: var(--primary); }
#ib-items td.cell-text .txt-cell { min-width: 120px; max-width: none; }
#ib-items th.center { text-align: center; }
.inv-totals {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px 16px;
    padding: 10px var(--pad); border-top: 1px solid var(--border); background: var(--surface-2);
}
.inv-totals .k { font-size: 11.5px; text-transform: uppercase; color: var(--text-3); font-weight: 700; letter-spacing: .04em; }
.inv-totals .v { font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums; }
.inv-totals .s { display: block; font-size: 12px; color: var(--text-3); font-weight: 500; }

/* ---- Rental line: the sum, said as it is worked out ---- */
.mf-formula { font-size: var(--fs-sm); color: var(--text-2); font-variant-numeric: tabular-nums; margin-top: 4px; }
.mf-formula b { color: var(--text); }

/* ---- The phone ----
   Fields that were sized to their content take the whole width, the
   filter columns stack, and dialogs and toasts lose their margins. */
.tbl-wrap { -webkit-overflow-scrolling: touch; }
@media (max-width: 560px) {
    .content { padding: 10px 10px 40px; }
    h1 { font-size: 20px; }
    .screen-head { gap: 8px; }
    .screen-head .btn { flex: 1 1 auto; }
    .stat-row { gap: 8px; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
    .stat-card .val { font-size: 18px; }
    .frow { gap: 8px 10px; }
    .fcol { flex: 1 1 100%; min-width: 0; }
    .w-24ch, .w-20ch, .w-16ch, .w-12ch, .w-10ch { width: 100%; }
    .range-pair { flex-wrap: wrap; }
    .range-pair input { flex: 1 1 40%; }
    .ss { display: block; width: 100%; }
    .ss .ss-input { width: 100%; }
    .modal { width: calc(100vw - 16px); max-height: calc(100vh - 24px); }
    .modal.wide { width: calc(100vw - 16px); }
    .modal-body { padding: 14px; }
    .modal-foot { flex-wrap: wrap; }
    .modal-foot .btn { flex: 1 1 auto; }
    .toast-root { left: 10px; right: 10px; bottom: 10px; }
    .toast { max-width: none; }
    .doc-paper { padding: 18px 14px; }
    .tbl th, .tbl td { padding: 7px 8px; }
    .tbl-chrome input[type="search"] { width: 100%; }
    .tabs .tab { padding: 10px 12px; }
    .txt-cell { min-width: 120px; }
    .inv-totals { grid-template-columns: 1fr 1fr; }
    .opt-grid { grid-template-columns: 1fr; }
    .chips { gap: 5px; }
}
/* A text cell on a voided invoice: readable, not editable. */
.txt-cell-ro { white-space: pre-wrap; overflow-wrap: anywhere; padding: 6px 8px; line-height: 1.4; font-size: 14px; color: var(--text-2); }

/* ---- Payroll Management: the week grid ----
   Seven day columns that stay seven (regular and overtime share the
   cells through a switch), the first column pinned while the rest
   scroll, today's column marked, and group rows for the job or the
   worker with their subtotal. On a phone held sideways the cost code
   and the pay columns fold away and the day cells narrow. */
.pw-grid table.tbl { min-width: 860px; }
.pw-grid th.pw-day, .pw-grid td.pw-day { text-align: center; width: 64px; padding-left: 3px; padding-right: 3px; }
.pw-grid th.pw-day { line-height: 1.2; }
.pw-grid .pw-sub { display: block; font-size: 11.5px; color: var(--text-3); font-weight: 500; text-transform: none; letter-spacing: 0; }
.pw-grid td .pw-sub { font-size: 12px; margin-top: 1px; }
.pw-grid td.pw-day input {
    width: 58px; min-height: 34px; padding: 4px 5px; text-align: center;
    font-variant-numeric: tabular-nums; -moz-appearance: textfield;
}
.pw-grid td.pw-day input::-webkit-outer-spin-button, .pw-grid td.pw-day input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pw-grid td.pw-day input.is-ot { background: var(--red-soft); border-color: #eac6c4; color: var(--red); font-weight: 600; }
.pw-grid td.pw-day input.is-ot:focus { border-color: var(--red); box-shadow: 0 0 0 3px rgba(194,57,52,.16); }
.pw-grid th.pw-today, .pw-grid td.pw-today { background: var(--primary-soft); }
.pw-grid th.pw-sticky, .pw-grid td.pw-sticky {
    position: sticky; left: 0; z-index: 3; background: var(--surface);
    min-width: 170px; box-shadow: 1px 0 0 var(--border);
}
.pw-grid thead th.pw-sticky { z-index: 4; background: var(--surface-2); }
.pw-grid tr.pw-group td { background: var(--surface-2); border-top: 2px solid var(--border-strong); font-weight: 700; }
.pw-grid tr.pw-group td.pw-sticky { background: var(--surface-2); }
.pw-grid tr.pw-group td.pw-day { color: var(--text-2); font-weight: 600; font-variant-numeric: tabular-nums; }
.pw-grid tr.pw-locked td { color: var(--text-3); }
.pw-grid td .pw-ro { display: inline-block; min-width: 34px; font-variant-numeric: tabular-nums; }
.pw-grid td .pw-ro small { display: block; font-size: 10.5px; color: var(--red); font-weight: 700; }
.pw-grid td.pw-num, .pw-grid th.pw-num { text-align: right; font-variant-numeric: tabular-nums; }
.pw-grid td.pw-tot { font-weight: 700; }
.pw-grid tfoot td { font-variant-numeric: tabular-nums; }
.pw-grid tfoot td.pw-sticky { background: var(--surface-2); }
.pw-grid td.pw-x { width: 34px; text-align: center; padding-left: 2px; padding-right: 2px; }
.pw-grid a.no-rowclick b { color: var(--primary); }

.pw-mode { display: inline-flex; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); overflow: hidden; }
.pw-mode button {
    border: 0; border-right: 1px solid var(--border-strong); background: var(--surface);
    font: inherit; font-size: 13px; font-weight: 600; padding: 6px 12px; min-height: 34px; cursor: pointer; color: var(--text-2);
}
.pw-mode button:last-child { border-right: 0; }
.pw-mode button.active { background: var(--primary); color: #fff; }
.pw-mode button.ot.active { background: var(--red); }
.pw-state { font-size: 13px; color: var(--text-3); white-space: nowrap; }
.pw-state.dirty { color: var(--amber); }
.pw-state.saving { color: var(--primary); }
.pw-state.err { color: var(--red); font-weight: 600; }
.pw-rotate { display: none; }

.pw-steps .step-title { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--text-3); font-weight: 700; margin: 14px 0 6px; }
.pw-steps .step-title:first-child { margin-top: 0; }
.pw-pick { max-height: 240px; overflow: auto; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.pw-pick .pw-opt { display: flex; gap: 10px; align-items: center; padding: 9px 12px; border-bottom: 1px solid var(--border); cursor: pointer; min-height: 44px; }
.pw-pick .pw-opt:last-child { border-bottom: 0; }
.pw-pick .pw-opt:hover { background: var(--surface-2); }
.pw-pick .pw-opt.active { background: var(--primary-soft); }
.pw-pick .pw-opt .spacer { flex: 1; }
.pw-steps .opt-grid { max-height: 260px; overflow: auto; }

@media (max-width: 900px) {
    .pw-grid table.tbl { min-width: 0; }
    .pw-grid .pw-hide-sm { display: none; }
    .pw-grid th, .pw-grid td { padding: 5px 4px; font-size: 13px; }
    .pw-grid th.pw-day, .pw-grid td.pw-day { width: 48px; }
    .pw-grid td.pw-day input { width: 44px; min-height: 32px; padding: 3px; font-size: 14px; }
    .pw-grid th.pw-sticky, .pw-grid td.pw-sticky { min-width: 120px; max-width: 150px; }
    .pw-grid td.pw-sticky b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .pw-grid td .pw-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    #pw-mode-hint { display: none; }
}
@media (max-width: 560px) and (orientation: portrait) {
    .pw-rotate { display: block; padding: 10px 14px; margin-bottom: 12px; border-radius: var(--radius); background: var(--amber-soft); color: var(--amber); font-size: 14px; font-weight: 600; }
}
