/*
 * Shared status colors for the Wayman app suite — danger/warn/success.
 * Every app previously copy-pasted its own :root block with these same
 * three values; --danger and --warn already matched everywhere by
 * convention alone, and --success is new (there was no shared "it worked"
 * color at all — apps either hardcoded one of several unrelated greens or
 * reused their own brand --accent color for confirmation text instead).
 *
 * Import this once, after your app's own :root block (so these three
 * declarations win if an app's own block still defines them during
 * migration), e.g. from your app's index.css:
 *   @import '@sumnerboy12/wrs-core/client/tokens.css';
 *
 * Brand/layout tokens (--accent, --bg, --panel, --text, --border, …) stay
 * per-app — only these three are meant to be identical everywhere.
 */
:root {
  --danger: #e5484d;
  --warn: #f59e0b;
  --success: #2e9b5f;
}
/* Deliberately does NOT redeclare --bg/--panel/--accent/etc: those are
   already defined on every consuming app's own :root (tendr, rostr, ...),
   each with its own real theme (e.g. tendr's teal --accent vs rostr's
   orange), and .estimating-workspace always renders inside that app's own
   document. An earlier version of this rule hardcoded tendr's original
   :root values here — copied verbatim when this was extracted from tendr
   into a shared module — which meant every consumer got tendr's colors
   instead of its own regardless of its actual theme. Just inherit. */
.estimating-workspace {
  font-family: -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  color-scheme: dark;
  background: var(--bg);
  color: var(--text);
}

:where(.estimating-workspace) * {
  box-sizing: border-box;
}

:where(.estimating-workspace) .table-scroll,
:where(.estimating-workspace) .schedule-table-scroll {
  overflow-x: auto;
}

:where(.estimating-workspace) .clickable-row {
  cursor: pointer;
}

:where(.estimating-workspace) .number-heading,
:where(.estimating-workspace) .number-cell {
  text-align: right;
}

:where(.estimating-workspace) .code-cell {
  color: var(--text-dim);
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 13px;
}

:where(.estimating-workspace) .toolbar-group .btn.is-selected {
  background: color-mix(in srgb, var(--accent) 32%, transparent);
  border-color: var(--accent);
}

:where(.estimating-workspace) .header-actions,
:where(.estimating-workspace) .form-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

:where(.estimating-workspace) .success-notice {
  padding: 9px 12px;
  margin: 0 0 12px;
  border-left: 3px solid #35b67a;
  background: color-mix(in srgb, #35b67a 12%, transparent);
  color: #a7e2c5;
  font-size: 13px;
}

/* Same success color as .success-notice, but text-only and inline — sits
   right next to the button that triggered it instead of a block banner,
   for confirmations that would otherwise land off-screen at the page top. */
:where(.estimating-workspace) .inline-success {
  color: #7fd1a8;
  font-size: 13px;
}

:where(.estimating-workspace) .checkbox-label {
  display: flex;
  align-items: center;
  gap: 7px;
  color: var(--text-dim);
  font-size: 13px;
}

:where(.estimating-workspace) .checkbox-label input {
  margin: 0;
}

/* .badge.state-* rather than .state-* — these share the .badge base rule's
   specificity (0-1-0) further down the file, so plain .state-* here would
   just lose that cascade tie and render as the same flat, uncoloured
   .badge look regardless of state. */
:where(.estimating-workspace) .badge.state-pending {
  border-color: var(--warn);
  background: color-mix(in srgb, var(--warn) 15%, transparent);
  color: var(--warn);
}

:where(.estimating-workspace) .badge.state-tendering {
  border-color: #5b8dc7;
  background: color-mix(in srgb, #5b8dc7 7%, transparent);
  color: #a8c5e8;
}

:where(.estimating-workspace) .badge.state-awarded,
:where(.estimating-workspace) .outcome-winner {
  border-color: #4f9d6f;
  background: color-mix(in srgb, #4f9d6f 7%, transparent);
  color: #8fcaa8;
}

:where(.estimating-workspace) .badge.state-lost,
:where(.estimating-workspace) .outcome-unsuccessful {
  border-color: var(--text-dim);
  background: color-mix(in srgb, var(--text-dim) 15%, transparent);
  opacity: 0.72;
}

/* Product library and global estimating settings */
:where(.estimating-workspace) .settings-card {
  padding: 18px;
  margin-bottom: 16px;
}

:where(.estimating-workspace) .settings-columns > div > .card:not(.settings-card) {
  margin-bottom: 16px;
}

:where(.estimating-workspace) .settings-card h2,
:where(.estimating-workspace) .estimate-section h2 {
  margin: 0 0 12px;
  font-size: 16px;
}

:where(.estimating-workspace) .settings-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 12px;
}

:where(.estimating-workspace) .settings-grid-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

:where(.estimating-workspace) .settings-card > h2:not(:first-child) {
  padding-top: 16px;
  margin-top: 4px;
  border-top: 1px solid var(--border);
}

:where(.estimating-workspace) .form-help {
  margin: -4px 0 14px;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.45;
}

:where(.estimating-workspace) .overhead-settings {
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto auto auto auto;
  row-gap: 4px;
  column-gap: 16px;
  align-items: stretch;
  margin-bottom: 12px;
}

:where(.estimating-workspace) .money-input {
  position: relative;
}

:where(.estimating-workspace) .money-input::before {
  content: '$';
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-dim);
  font-size: 13px;
  pointer-events: none;
}

:where(.estimating-workspace) .money-input input {
  padding-left: 20px;
}

:where(.estimating-workspace) .calculated-setting {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 60px;
  padding: 8px 14px;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 12%, var(--panel-alt));
}

:where(.estimating-workspace) .calculated-setting span,
:where(.estimating-workspace) .calculated-setting small {
  color: var(--text-dim);
  font-size: 11px;
}

:where(.estimating-workspace) .calculated-setting strong {
  margin: 2px 0;
  font-size: 22px;
}

:where(.estimating-workspace) .settings-card .form-actions {
  justify-content: flex-start;
  padding-top: 8px;
}

:where(.estimating-workspace) .settings-card .form-actions.settings-form-actions {
  padding-top: 0;
}

:where(.estimating-workspace) .settings-columns {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}

:where(.estimating-workspace) .merge-field-reference-card {
  padding-bottom: 10px;
}

:where(.estimating-workspace) .merge-field-reference {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 18px 22px;
}

:where(.estimating-workspace) .merge-field-group h3 {
  margin: 0 0 8px;
  color: var(--text-dim);
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

:where(.estimating-workspace) .merge-field-group-note {
  margin: -2px 0 8px;
  color: var(--text-dim);
  font-size: 11px;
  font-style: italic;
  line-height: 1.35;
}

:where(.estimating-workspace) .merge-field-group dl {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

:where(.estimating-workspace) .merge-field-row dt code {
  display: inline-block;
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel-alt);
  font-size: 11px;
}

:where(.estimating-workspace) .merge-field-row dd {
  margin: 1px 0 0;
  color: var(--text-dim);
  font-size: 12px;
  line-height: 1.35;
}

:where(.estimating-workspace) .schedule-summary-table {
  font-size: 12px;
}

:where(.estimating-workspace) .schedule-summary-dim {
  color: var(--text-dim);
}

/* One tbody per schedule group: a name to read the block by, then its own
   subtotal, with the grand total still in the table's foot. */
:where(.estimating-workspace) .schedule-summary-group-heading th {
  padding-top: 14px;
  color: var(--accent);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-align: left;
  text-transform: uppercase;
}

:where(.estimating-workspace) .schedule-summary-group:first-of-type .schedule-summary-group-heading th {
  padding-top: 0;
}

:where(.estimating-workspace) .schedule-summary-group-total td {
  border-top: 1px solid var(--border);
  font-weight: 600;
}

:where(.estimating-workspace) .compact-list {
  max-height: 360px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 6px;
}

:where(.estimating-workspace) .compact-list-row {
  display: grid;
  grid-template-columns: minmax(80px, auto) 1fr auto;
  align-items: center;
  gap: 10px;
  min-height: 37px;
  padding: 5px 9px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}

:where(.estimating-workspace) .compact-list-row:last-child {
  border-bottom: 0;
}

/* "Nothing here yet" inside the list's own box. Laid out like a row rather
   than as a loose paragraph, which is what left it jammed against the border
   with its own margin pushing it off-centre. */
:where(.estimating-workspace) .compact-list-empty {
  display: flex;
  align-items: center;
  min-height: 37px;
  margin: 0;
  padding: 5px 9px;
  color: var(--text-dim);
  font-size: 13px;
}

/* A list under its own heading, within a card or a form. Spaced here rather
   than inline per section, so appendices and email attachments sit the same
   distance from their headings as every other card does — and so .form-help's
   own negative top margin lands against a known value. */
:where(.estimating-workspace) .compact-list-section {
  margin-top: 18px;
}

:where(.estimating-workspace) .compact-list-section > h2,
:where(.estimating-workspace) .compact-list-section > h3 {
  margin: 0 0 12px;
}

:where(.estimating-workspace) .compact-list-section > h3 {
  font-size: 14px;
}

:where(.estimating-workspace) .compact-list-row-gl {
  grid-template-columns: minmax(70px, auto) 1fr minmax(90px, auto) auto;
}

/* A schedule's cost codes add an Overhead tick before Delete. Each row is its
   own grid, so every track is sized alike in all of them — fixed, or content
   that reads the same on every row — for the columns to line up; the name
   takes what's left. */
:where(.estimating-workspace) .compact-list-row-cost-code {
  grid-template-columns: 80px minmax(0, 1fr) 100px max-content max-content;
}

/* Text boxes fill their column rather than their own default width, which
   would push the row past its tracks. */
:where(.estimating-workspace) .compact-list-row-cost-code input:not([type='checkbox']) {
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
}

:where(.estimating-workspace) .cost-code-overhead {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text-dim);
  white-space: nowrap;
  cursor: pointer;
}

:where(.estimating-workspace) .inline-add .cost-code-overhead input {
  flex: none;
}

/* A file name in one of these rows is the row's own label, which happens to
   open the file — a column of underlines reads as noise rather than as
   emphasis, so it only underlines under the pointer. */
:where(.estimating-workspace) .compact-list-row > a {
  text-decoration: none;
}

:where(.estimating-workspace) .compact-list-row > a:hover {
  text-decoration: underline;
}

:where(.estimating-workspace) .compact-list-row span {
  color: var(--text-dim);
}

:where(.estimating-workspace) .inline-add {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
}

:where(.estimating-workspace) .inline-add input,
:where(.estimating-workspace) .inline-add select {
  min-width: 0;
  flex: 1;
}

/* Estimate workspace */
:where(.estimating-workspace) .estimate-workspace {
  min-width: 1080px;
  min-height: 100%;
  padding: 22px 26px 40px;
  background:
    radial-gradient(circle at 75% -20%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 32%), var(--bg);
}

:where(.estimating-workspace) .estimate-workspace-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  max-width: 1800px;
  margin: 0 auto 18px;
}

:where(.estimating-workspace) .estimate-title-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

:where(.estimating-workspace) .estimate-title-row h1 {
  margin: 0;
  font-size: 23px;
}

:where(.estimating-workspace) .estimate-subline {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 7px 0 0;
  color: var(--text-dim);
  font-size: 13px;
}

:where(.estimating-workspace) .estimate-subline .badge {
  position: relative;
  top: 1px;
}

:where(.estimating-workspace) .estimate-subline-address {
  color: inherit;
  text-decoration: none;
}

:where(.estimating-workspace) .estimate-subline-dot {
  color: var(--text-dim);
}

:where(.estimating-workspace) .estimate-header-summary {
  display: flex;
  gap: 18px;
  color: var(--text-dim);
  font-size: 12px;
}

:where(.estimating-workspace) .workspace-tabs {
  display: flex;
  max-width: 1800px;
  margin: 0 auto;
  border-bottom: 1px solid var(--border);
}

:where(.estimating-workspace) .workspace-tabs button {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 15px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--text-dim);
  font: inherit;
  font-size: 13px;
  text-align: left;
}

:where(.estimating-workspace) .workspace-tabs button.active {
  border-bottom-color: var(--accent);
  color: var(--text);
  font-weight: 600;
}

:where(.estimating-workspace) .workspace-tabs small {
  font-size: 10px;
  font-weight: 400;
}

:where(.estimating-workspace) .workspace-tabs .add-schedule-tab {
  color: var(--accent);
}

:where(.estimating-workspace) .schedule-tab-awarded {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  border: 1px solid #4f9d6f;
  border-radius: 50%;
  color: #4f9d6f;
}

:where(.estimating-workspace) .schedule-tab-sent {
  display: inline-flex;
  align-items: center;
  color: var(--accent);
}

:where(.estimating-workspace) .workspace-content {
  max-width: 1800px;
  margin: 16px auto 0;
}

:where(.estimating-workspace) .estimate-section {
  padding: 18px;
}

:where(.estimating-workspace) .section-heading {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 20px;
  margin-bottom: 16px;
}

:where(.estimating-workspace) .section-heading h2 {
  margin-bottom: 4px;
}

:where(.estimating-workspace) .section-heading p {
  margin: 0;
  color: var(--text-dim);
  font-size: 13px;
}

:where(.estimating-workspace) .outcome-submissions {
  margin-top: 14px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
}

:where(.estimating-workspace) .submission-row-awarded td {
  background: color-mix(in srgb, #35b67a 10%, transparent);
  box-shadow:
    inset 0 1px 0 #35b67a,
    inset 0 -1px 0 #35b67a;
}

:where(.estimating-workspace) .submission-row-awarded td:first-child {
  border-top-left-radius: 6px;
  border-bottom-left-radius: 6px;
  box-shadow:
    inset 0 1px 0 #35b67a,
    inset 0 -1px 0 #35b67a,
    inset 1px 0 0 #35b67a;
}

:where(.estimating-workspace) .submission-row-awarded td:last-child {
  border-top-right-radius: 6px;
  border-bottom-right-radius: 6px;
  box-shadow:
    inset 0 1px 0 #35b67a,
    inset 0 -1px 0 #35b67a,
    inset -1px 0 0 #35b67a;
}

:where(.estimating-workspace) .outcome-submissions .btn {
  font-size: 13px;
}

:where(.estimating-workspace) .table-cell-note {
  color: var(--warn);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

:where(.estimating-workspace) .table-cell-sub {
  color: var(--text-dim);
  font-size: 11px;
  white-space: nowrap;
}

:where(.estimating-workspace) .client-card-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(250px, 1fr));
  gap: 12px;
}

:where(.estimating-workspace) .client-card {
  padding: 13px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--panel-alt);
}

:where(.estimating-workspace) .client-card-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}

:where(.estimating-workspace) .client-card-title .badge {
  margin-left: auto;
  text-transform: capitalize;
}

:where(.estimating-workspace) .client-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
}

:where(.estimating-workspace) .client-card .field {
  margin-bottom: 4px;
}

:where(.estimating-workspace) .client-add {
  max-width: 680px;
}

:where(.estimating-workspace) .empty-panel {
  padding: 20px;
  color: var(--text-dim);
  font-size: 13px;
}

/* Schedule editor */
:where(.estimating-workspace) .autosave-status {
  min-width: 58px;
  color: var(--text-dim);
  font-size: 11px;
  text-align: right;
}

:where(.estimating-workspace) .save-status-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 12px;
  border-radius: 6px;
  font-size: 12.5px;
}

:where(.estimating-workspace) .save-status-banner-error {
  border: 1px solid var(--danger);
  background: color-mix(in srgb, var(--danger) 14%, transparent);
  color: var(--danger);
}

:where(.estimating-workspace) .save-status-banner-error button {
  color: var(--danger);
}

:where(.estimating-workspace) .command-menu {
  position: relative;
}

:where(.estimating-workspace) .command-menu > summary {
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--panel-alt);
  color: var(--text);
  cursor: pointer;
  font-size: 13px;
  list-style: none;
  white-space: nowrap;
}

:where(.estimating-workspace) .command-menu > summary::-webkit-details-marker {
  display: none;
}

:where(.estimating-workspace) .command-menu[open] > summary {
  border-color: var(--accent);
}

:where(.estimating-workspace) .command-menu-content {
  position: absolute;
  z-index: 30;
  top: calc(100% + 5px);
  left: 0;
  min-width: 125px;
  padding: 4px;
  border: 1px solid var(--accent);
  border-radius: 7px;
  background: var(--panel-alt);
  box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
  display: flex;
  flex-direction: column;
}

:where(.estimating-workspace) .command-menu-item {
  display: block;
  padding: 7px 10px;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: var(--text);
  font-size: 13px;
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

:where(.estimating-workspace) .command-menu-item:hover {
  background: color-mix(in srgb, var(--accent) 20%, transparent);
}

:where(.estimating-workspace) .command-menu-item-danger {
  color: var(--danger);
}

:where(.estimating-workspace) .command-menu-separator {
  height: 1px;
  margin: 4px 6px;
  background: var(--border);
}

/* The picked-out rows' right-click menu: the Actions menu's look, placed at
   the pointer (ScheduleEditor sets left/top and keeps it on screen). */
:where(.estimating-workspace) .schedule-row-menu {
  position: fixed;
  z-index: 60;
  min-width: 190px;
}

:where(.estimating-workspace) .schedule-row-menu-heading {
  padding: 5px 10px 4px;
  color: var(--text-dim);
  font-size: 12px;
}

:where(.estimating-workspace) .schedule-row-menu .command-menu-item {
  display: flex;
  justify-content: space-between;
  gap: 24px;
}

:where(.estimating-workspace) .command-menu-shortcut {
  color: var(--text-dim);
  font-size: 12px;
}

/* A step above the 13px help text around them. */
:where(.estimating-workspace) .send-schedule-modal .field > label {
  font-size: 14px;
}

/* The template modal's sections (Name, Cover page, Email subject…) read as
   headings, the same as its Email Attachments and Appendices sections below
   them (.compact-list-section > h3). */
:where(.estimating-workspace) .document-template-modal .field > label {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
}

/* And spaced like them too. A section's heading and help text collapse to an
   8px gap, with 14px down to its list and 18px between sections; a field is
   a flex column (4px gap, no margin collapsing), where .form-help's own -4px
   top margin would leave the help text touching its label. */
:where(.estimating-workspace) .document-template-modal .field {
  margin-bottom: 18px;
}
:where(.estimating-workspace) .document-template-modal .field > .form-help {
  margin: 4px 0 10px;
}

/* 10px each side: 6px + the field's 4px gap above; -10px off the action row's 20px below. */
:where(.estimating-workspace) .form-help.send-attachments-hint {
  margin: 6px 0 -10px;
}

/* Opens upward, for a menu at the foot of a scrolling modal. */
:where(.estimating-workspace) .command-menu-up > .command-menu-content {
  top: auto;
  bottom: calc(100% + 5px);
}

:where(.estimating-workspace) .command-menu-align-right > .command-menu-content {
  left: auto;
  right: 0;
}

:where(.estimating-workspace) .command-submenu {
  position: relative;
}

:where(.estimating-workspace) .command-submenu > summary {
  list-style: none;
}

:where(.estimating-workspace) .command-submenu > summary::-webkit-details-marker {
  display: none;
}

:where(.estimating-workspace) .command-submenu-content {
  position: absolute;
  z-index: 31;
  top: -5px;
  right: calc(100% + 5px);
  min-width: 125px;
  padding: 4px;
  border: 1px solid var(--accent);
  border-radius: 7px;
  background: var(--panel-alt);
  box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
  display: flex;
  flex-direction: column;
}

:where(.estimating-workspace) .schedule-pricing-card {
  margin-bottom: 12px;
}

:where(.estimating-workspace) .pricing-summary-row {
  display: grid;
  grid-template-columns: auto repeat(6, minmax(100px, 1fr)) 1px auto;
  align-items: stretch;
  min-height: 48px;
}

:where(.estimating-workspace) .pricing-summary-title {
  display: flex;
  align-items: center;
  padding: 0 12px;
  font-size: 13px;
}

:where(.estimating-workspace) .pricing-summary-metric {
  display: grid;
  grid-template-columns: 1fr auto;
  align-content: center;
  column-gap: 5px;
  padding: 5px 10px;
  border-left: 1px solid var(--border);
  font-variant-numeric: tabular-nums;
}

:where(.estimating-workspace) .pricing-summary-metric span {
  grid-column: 1 / -1;
  color: var(--text-dim);
  font-size: 9px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

:where(.estimating-workspace) .pricing-summary-metric strong,
:where(.estimating-workspace) .pricing-summary-metric small {
  color: var(--text);
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
}

:where(.estimating-workspace) .pricing-summary-primary {
  background: color-mix(in srgb, var(--accent) 15%, transparent);
}

:where(.estimating-workspace) .pricing-summary-primary strong {
  color: white;
  font-size: 15px;
}

:where(.estimating-workspace) .pricing-summary-profit {
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}

:where(.estimating-workspace) .pricing-summary-metric .pricing-summary-discount {
  grid-column: 1 / -1;
  color: var(--warn);
  font-size: 10px;
  font-weight: 600;
}

/* How far a locked schedule's figure has moved from the tender it was
   awarded on (see EstimateDetail.awarded_totals) — a cost up or a profit
   down reads as a warning, the rest as information. */
:where(.estimating-workspace) .pricing-summary-metric .pricing-summary-delta {
  grid-column: 1 / -1;
  color: var(--text-dim);
  font-size: 10px;
  font-weight: 600;
}

:where(.estimating-workspace) .pricing-summary-metric .pricing-summary-worse {
  color: var(--warn);
}

:where(.estimating-workspace) .pricing-summary-separator {
  align-self: stretch;
  background: var(--border);
}

:where(.estimating-workspace) .pricing-summary-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 12px;
}

:where(.estimating-workspace) .pricing-rate-editor-wrapper {
  position: relative;
}

:where(.estimating-workspace) .pricing-rate-editor-close {
  position: absolute;
  top: 4px;
  right: 6px;
  font-size: 16px;
  line-height: 1;
}

:where(.estimating-workspace) .pricing-rate-editor {
  display: grid;
  grid-template-columns: repeat(8, minmax(85px, 1fr)) minmax(260px, 1.4fr);
  gap: 10px;
  padding: 10px 12px;
  border-top: 1px solid var(--border);
  background: var(--panel-alt);
  border-bottom-left-radius: var(--radius);
  border-bottom-right-radius: var(--radius);
}

:where(.estimating-workspace) .pricing-rate-label {
  display: block;
  color: var(--text-dim);
  font-size: 9px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

:where(.estimating-workspace) .pricing-rate-unit {
  color: var(--text-dim);
  font-size: 9px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

:where(.estimating-workspace) .input-suffix {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 4px;
  color: var(--text-dim);
  font-size: 11px;
}

:where(.estimating-workspace) .input-suffix input {
  width: 100%;
  min-width: 0;
  text-align: right;
}

:where(.estimating-workspace) .pricing-overhead-context {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  padding: 4px 12px;
  margin-right: 18px;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 12%, var(--panel-alt));
}

:where(.estimating-workspace) .pricing-overhead-context small {
  color: var(--text-dim);
  font-size: 10px;
  white-space: nowrap;
}

:where(.estimating-workspace) .pricing-overhead-context strong {
  font-size: 14px;
}

:where(.estimating-workspace) .schedule-items-card {
  margin-bottom: 12px;
}

:where(.estimating-workspace) .schedule-items-card-fullscreen {
  position: fixed;
  z-index: 90;
  inset: 0;
  display: flex;
  flex-direction: column;
  margin: 0;
  border: 0;
  border-radius: 0;
}

:where(.estimating-workspace) .schedule-items-card-fullscreen .schedule-items-toolbar,
:where(.estimating-workspace) .schedule-items-card-fullscreen .shortcut-strip {
  flex: 0 0 auto;
}

:where(.estimating-workspace) .schedule-items-card-fullscreen .schedule-table-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}

:where(.estimating-workspace) .schedule-items-card-fullscreen .estimate-grid thead th {
  position: sticky;
  z-index: 2;
  top: 0;
  background: var(--panel-alt);
}

:where(.estimating-workspace) .schedule-editor-item-fullscreen .sticky-feedback {
  z-index: 95;
}

:where(.estimating-workspace) .schedule-items-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
}

:where(.estimating-workspace) .schedule-items-toolbar strong {
  font-size: 13px;
}

:where(.estimating-workspace) .schedule-key-notes-card {
  margin-bottom: 12px;
}

/* Kept tight: the notes sit between the pricing card and the schedule, and
   a handful of one-line notes should not push the rows off the screen. */
:where(.estimating-workspace) .schedule-key-notes-card .schedule-items-toolbar {
  min-height: 0;
  padding: 6px 12px;
}

:where(.estimating-workspace) .key-note-row {
  display: grid;
  grid-template-columns: 220px 1fr auto;
  gap: 6px;
  align-items: center;
  padding: 3px 12px;
}

/* The first row sits under the card's header rather than under another row,
   so it needs the full 6px the rows give each other — and the last row the
   same beneath it. An adjacent-sibling selector, not :first-of-type: the
   header is a div like the rows, so it is itself the first of that type and
   the rule never reached a row. */
:where(.estimating-workspace) .schedule-items-toolbar + .key-note-row {
  padding-top: 6px;
}

:where(.estimating-workspace) .key-note-row:last-child {
  padding-bottom: 6px;
}

/* Sized like the schedule grid's own inputs, so the two read as one. */
:where(.estimating-workspace) .key-note-row input {
  height: 25px;
  padding: 2px 8px;
  font-size: 12px;
  line-height: 1.2;
}

:where(.estimating-workspace) .key-note-row .btn {
  height: 25px;
  padding: 2px 8px;
  font-size: 12px;
  line-height: 1.2;
}

:where(.estimating-workspace) .schedule-item-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

:where(.estimating-workspace) .estimate-grid {
  /* Explicit widths per column via <colgroup> — width:auto (not the
     app-wide table{width:100%} reset) keeps the table sized to exactly
     those widths instead of the browser stretching every column to fill
     the container, which distorts narrow columns far more than wide ones. */
  width: auto;
  table-layout: fixed;
}

:where(.estimating-workspace) .estimate-grid th,
:where(.estimating-workspace) .estimate-grid td {
  padding: 2px 4px;
  overflow: hidden;
}

:where(.estimating-workspace) .estimate-grid th {
  position: relative;
  padding: 5px 12px 5px 4px;
  font-size: 10px;
}

:where(.estimating-workspace) .estimate-grid input,
:where(.estimating-workspace) .estimate-grid select {
  width: 100%;
  min-width: 0;
  height: 25px;
  padding: 2px 5px;
  border-color: transparent;
  background: transparent;
  font-size: 12px;
  line-height: 1.2;
}

:where(.estimating-workspace) .estimate-grid input[type='number'] {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

:where(.estimating-workspace) .estimate-grid .money-input input {
  padding-left: 18px;
}

:where(.estimating-workspace) .estimate-grid .money-input::before {
  left: 5px;
  font-size: 12px;
}

:where(.estimating-workspace) .estimate-grid input:focus,
:where(.estimating-workspace) .estimate-grid select:focus {
  border-color: var(--accent);
  background: var(--panel-alt);
}

:where(.estimating-workspace) .estimate-grid td.schedule-computed-cell {
  padding: 2px 9px;
  color: var(--text-dim);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  text-overflow: ellipsis;
}

:where(.estimating-workspace) .column-resize-handle {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 8px;
  cursor: col-resize;
  touch-action: none;
  z-index: 1;
}

:where(.estimating-workspace) .column-resize-handle:hover,
:where(.estimating-workspace) .column-resize-handle:active {
  background: var(--accent);
  opacity: 0.5;
}

:where(.estimating-workspace) .estimate-grid .drag-column {
  width: 52px;
  min-width: 52px;
  color: var(--text-dim);
  text-align: center;
  cursor: grab;
  white-space: nowrap;
}

:where(.estimating-workspace) .schedule-row-id {
  display: inline-block;
  min-width: 20px;
  margin-left: 3px;
  color: var(--text);
  text-align: right;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

:where(.estimating-workspace) .drag-handle {
  color: var(--text-dim);
}

:where(.estimating-workspace) .schedule-label-row td:nth-child(5) input {
  font-weight: 650;
  color: var(--text);
}

:where(.estimating-workspace) .schedule-label-row td:nth-child(n + 6):nth-child(-n + 11),
:where(.estimating-workspace) .has-quote-column .schedule-label-row td:nth-child(12),
:where(.estimating-workspace) .schedule-label-row td.schedule-computed-cell {
  background: color-mix(in srgb, var(--panel-alt) 65%, transparent);
}

:where(.estimating-workspace) .schedule-label-row td:nth-child(n + 6):nth-child(-n + 11) input,
:where(.estimating-workspace) .schedule-label-row td:nth-child(n + 6):nth-child(-n + 11) select {
  opacity: 0.4;
}

:where(.estimating-workspace) .dragging-row {
  opacity: 0.45;
}

:where(.estimating-workspace) .schedule-row-hidden {
  display: none;
}

/* A credit line: the row prices below zero and so comes off the schedule
   total. Red by the usual accounting convention, but lighter than the error
   row below and with no left bar, since a credit is a legitimate state and a
   save error is not. Declared before the error and highlight rules so that
   either of those wins on a row that is both — same specificity, later wins. */
:where(.estimating-workspace) .schedule-row-negative td {
  background: color-mix(in srgb, var(--danger) 7%, transparent);
}

:where(.estimating-workspace) .schedule-row-error td {
  background: color-mix(in srgb, var(--danger) 14%, transparent);
}

:where(.estimating-workspace) .schedule-row-error td:first-child {
  box-shadow: inset 3px 0 0 var(--danger);
}

:where(.estimating-workspace) .schedule-row-highlighted td {
  background: color-mix(in srgb, var(--warn) 14%, transparent);
}

:where(.estimating-workspace) .schedule-row-highlighted td:first-child {
  box-shadow: inset 3px 0 0 var(--warn);
}

/* Rows picked out for a whole-row copy. A different colour from the
   highlight flag above on purpose: that one is the estimator's own mark on
   a row and outlives the page, this one lasts as long as the selection. */
:where(.estimating-workspace) .schedule-row-selected td {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
}

:where(.estimating-workspace) .schedule-row-selected td:first-child {
  box-shadow: inset 3px 0 0 var(--accent);
}

:where(.estimating-workspace) .schedule-label-row.schedule-row-highlighted td:nth-child(n + 6):nth-child(-n + 11),
:where(.estimating-workspace) .has-quote-column .schedule-label-row.schedule-row-highlighted td:nth-child(12),
:where(.estimating-workspace) .schedule-label-row.schedule-row-highlighted td.schedule-computed-cell {
  background: color-mix(in srgb, var(--warn) 14%, transparent);
}

:where(.estimating-workspace) .schedule-label-row.schedule-row-highlighted td:nth-child(n + 6):nth-child(-n + 11) input,
:where(.estimating-workspace)
  .schedule-label-row.schedule-row-highlighted
  td:nth-child(n + 6):nth-child(-n + 11)
  select {
  opacity: 1;
}

:where(.estimating-workspace) .schedule-label-row.schedule-row-selected td:nth-child(n + 6):nth-child(-n + 11),
:where(.estimating-workspace) .has-quote-column .schedule-label-row.schedule-row-selected td:nth-child(12),
:where(.estimating-workspace) .schedule-label-row.schedule-row-selected td.schedule-computed-cell {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
}

:where(.estimating-workspace) .row-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  white-space: nowrap;
}

:where(.estimating-workspace) .row-diary-count {
  margin-right: 6px;
  padding: 0;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: 12px;
  color: var(--text-dim);
  cursor: pointer;
}

:where(.estimating-workspace) .row-diary-count:hover {
  color: var(--text);
}

:where(.estimating-workspace) .icon-button {
  width: 22px;
  height: 25px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text-dim);
}

:where(.estimating-workspace) .icon-button:hover {
  color: var(--text);
}

:where(.estimating-workspace) .icon-button.danger:hover {
  color: var(--danger);
}

:where(.estimating-workspace) .icon-button.highlighted {
  color: var(--warn);
}

:where(.estimating-workspace) .outcome-message {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
  color: var(--text-dim);
  font-size: 13px;
}

:where(.estimating-workspace) .audit-award-note,
:where(.estimating-workspace) .audit-lost-note {
  /* Negative top margin cancels most of the heading's own margin-bottom
     (16px, both in .section-heading and .modal h2) so the gap above and
     below this box end up equal instead of the heading's spacing stacking
     on top of ours. */
  margin: -8px 0 8px;
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 13px;
}

:where(.estimating-workspace) .audit-award-note {
  border: 1px solid #35b67a;
  background: color-mix(in srgb, #35b67a 10%, transparent);
  color: #8fcaa8;
}

:where(.estimating-workspace) .audit-lost-note {
  border: 1px solid var(--danger);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  color: var(--danger);
}

/* A lost schedule (EstimateScheduleSummary.lost_at), or the one that won, above its editor. */
:where(.estimating-workspace) .schedule-lost-note,
:where(.estimating-workspace) .schedule-awarded-note {
  margin-bottom: 12px;
  padding: 8px 12px;
  border: 1px solid var(--danger);
  border-radius: 6px;
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  color: var(--danger);
  font-size: 13px;
}

:where(.estimating-workspace) .schedule-awarded-note {
  border-color: #35b67a;
  background: color-mix(in srgb, #35b67a 10%, transparent);
  color: #8fcaa8;
}

:where(.estimating-workspace) .sticky-feedback {
  position: fixed;
  right: 24px;
  bottom: 20px;
  z-index: 20;
  min-width: 280px;
  margin: 0;
  padding: 10px 14px;
  border: 1px solid #35b67a;
  border-left-width: 3px;
  border-radius: 6px;
  background: color-mix(in srgb, #35b67a 12%, var(--panel));
  color: #a7e2c5;
  font-size: 13px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
}

:where(.estimating-workspace) .error-feedback {
  border-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 12%, var(--panel));
  color: var(--danger);
}

@media (max-width: 900px) {
  :where(.estimating-workspace) .settings-grid,
  :where(.estimating-workspace) .settings-columns,
  :where(.estimating-workspace) .client-card-grid {
    grid-template-columns: 1fr;
  }
}

:where(.estimating-workspace) button {
  font-family: inherit;
  cursor: pointer;
}

:where(.estimating-workspace) input,
:where(.estimating-workspace) select,
:where(.estimating-workspace) textarea {
  font-family: inherit;
  background: var(--panel-alt);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
}

:where(.estimating-workspace) input[type='number'] {
  appearance: textfield;
  -moz-appearance: textfield;
}

:where(.estimating-workspace) input[type='number']::-webkit-inner-spin-button,
:where(.estimating-workspace) input[type='number']::-webkit-outer-spin-button {
  margin: 0;
  -webkit-appearance: none;
}

:where(.estimating-workspace) textarea {
  resize: vertical;
}

:where(.estimating-workspace) input:focus,
:where(.estimating-workspace) select:focus,
:where(.estimating-workspace) textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}

:where(.estimating-workspace) input:disabled,
:where(.estimating-workspace) select:disabled,
:where(.estimating-workspace) textarea:disabled {
  background: var(--bg);
  border-color: transparent;
  color: var(--text-dim);
  cursor: not-allowed;
}

:where(.estimating-workspace) a {
  color: var(--accent);
}

:where(.estimating-workspace) table {
  border-collapse: collapse;
  width: 100%;
}

:where(.estimating-workspace) th,
:where(.estimating-workspace) td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
}

:where(.estimating-workspace) th {
  color: var(--text-dim);
  font-weight: 600;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

:where(.estimating-workspace) tbody tr:last-child td {
  border-bottom: 0;
}

:where(.estimating-workspace) .checklist-item-row:hover {
  background: var(--panel-alt);
}

:where(.estimating-workspace) .btn {
  background: var(--panel-alt);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 7px 14px;
  font-size: 14px;
  text-decoration: none;
}

:where(.estimating-workspace) .btn:hover:not(:disabled) {
  border-color: var(--accent);
}

:where(.estimating-workspace) .btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: white;
  font-weight: 600;
}

:where(.estimating-workspace) .btn-primary:hover:not(:disabled) {
  filter: brightness(1.1);
}

:where(.estimating-workspace) .btn-danger {
  color: var(--danger);
}

:where(.estimating-workspace) .btn-danger:hover:not(:disabled) {
  border-color: var(--danger);
}

/* .btn.btn-borderless, so an app's own later .btn rule (rostr's) cannot override it. */
:where(.estimating-workspace) .btn.btn-borderless {
  background: transparent;
  border-color: transparent;
  padding: 3px 8px;
  font-size: 12px;
}

:where(.estimating-workspace) .btn.btn-borderless:hover:not(:disabled) {
  border-color: transparent;
  text-decoration: underline;
}

/* Attachment lists show a faint border on hover, like toolbar buttons, not an underline. */
:where(.estimating-workspace) .attachment-list .btn.btn-borderless:hover:not(:disabled) {
  border-color: var(--border);
  text-decoration: none;
}

:where(.estimating-workspace) .link-button {
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

:where(.estimating-workspace) .btn:disabled,
:where(.estimating-workspace) button:disabled {
  cursor: default;
  opacity: 0.6;
}

:where(.estimating-workspace) .badge {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  background: var(--panel-alt);
  border: 1px solid var(--border);
  color: var(--text-dim);
}

:where(.estimating-workspace) .toolbar-group {
  display: flex;
  gap: 2px;
  padding: 3px;
  background: var(--panel-alt);
  border: 1px solid var(--border);
  border-radius: 8px;
}

:where(.estimating-workspace) .toolbar-group .btn {
  background: transparent;
  border: 1px solid transparent;
}

:where(.estimating-workspace) .toolbar-group .btn:hover:not(:disabled) {
  border-color: var(--border);
}

:where(.estimating-workspace) .card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

:where(.estimating-workspace) .page-container {
  padding: 20px;
  max-width: 1200px;
  margin: 0 auto;
}

:where(.estimating-workspace) .page-container-narrow {
  max-width: 1000px;
}

:where(.estimating-workspace) .page-container-health {
  max-width: 900px;
}

:where(.estimating-workspace) .page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  margin-bottom: 16px;
}

:where(.estimating-workspace) .page-header h1 {
  font-size: 20px;
  margin: 0;
}

:where(.estimating-workspace) .page-description {
  color: var(--text-dim);
  font-size: 13px;
  margin: 0 0 16px;
}

:where(.estimating-workspace) .page-toolbar {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

:where(.estimating-workspace) .page-message {
  padding: 20px;
}

:where(.estimating-workspace) .empty-row {
  text-align: center;
  color: var(--text-dim);
  padding: 24px;
  font-size: 12px;
}

:where(.estimating-workspace) .schedule-empty-filter-row {
  font-size: 13px;
}

:where(.estimating-workspace) .client-pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  color: white;
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

/* Addressable contacts above the Send modal's To/Cc fields — click the name
   to address it to them, Cc to copy them in, or drag the pill onto either
   field. The role subline is what tells two contacts on the same job apart. */
:where(.estimating-workspace) .contact-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* Smaller and tighter than .form-help: one line under the pills, where the
   pills themselves are the loud part and this only names the gestures. */
:where(.estimating-workspace) .contact-pills-help {
  margin: 0;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.45;
}

:where(.estimating-workspace) .contact-pill {
  display: flex;
  align-items: stretch;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--panel-alt);
}

:where(.estimating-workspace) .contact-pill.is-to {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 18%, var(--panel-alt));
}

:where(.estimating-workspace) .contact-pill.is-cc {
  border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
  background: color-mix(in srgb, var(--accent) 8%, var(--panel-alt));
}

:where(.estimating-workspace) .contact-pill-main {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 5px 12px;
  border: 0;
  background: none;
  color: inherit;
  line-height: 1.25;
  text-align: left;
  cursor: pointer;
}

:where(.estimating-workspace) .contact-pill-main strong {
  font-size: 12px;
  font-weight: 600;
}

:where(.estimating-workspace) .contact-pill-main span {
  color: var(--text-dim);
  font-size: 10px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

:where(.estimating-workspace) .contact-pill-copy {
  padding: 0 10px;
  border: 0;
  border-left: 1px solid var(--border);
  background: none;
  color: var(--text-dim);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  cursor: pointer;
}

/* To and Cc each carry a round + that opens the address book — the
   schedule's client's contacts or anyone at WRS — for whoever isn't one of
   the pills above. The apps' standard add button (rostr's .btn-icon-add): an
   accent circle with the plus drawn, since a "+" glyph never sits dead centre.
   Keyed on .btn.address-field-add, not the class alone: :where() adds nothing,
   so the class alone only ties an app's own global .btn (rostr's), and that
   stylesheet loads after this one, so its corners and padding won. */
:where(.estimating-workspace) .address-field {
  display: flex;
  gap: 6px;
}

:where(.estimating-workspace) .address-field input {
  flex: 1;
  min-width: 0;
}

:where(.estimating-workspace) .btn.address-field-add {
  position: relative;
  align-self: center;
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  padding: 0;
  border-radius: 50%;
}

:where(.estimating-workspace) .btn.address-field-add::before,
:where(.estimating-workspace) .btn.address-field-add::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  background: currentColor;
  transform: translate(-50%, -50%);
}

:where(.estimating-workspace) .btn.address-field-add::before {
  width: 14px;
  height: 2px;
}

:where(.estimating-workspace) .btn.address-field-add::after {
  width: 2px;
  height: 14px;
}

:where(.estimating-workspace) .address-book-tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 12px;
}

:where(.estimating-workspace) .contact-pill.is-cc .contact-pill-copy,
:where(.estimating-workspace) .contact-pill-copy:hover,
:where(.estimating-workspace) .contact-pill-main:hover strong {
  color: var(--accent);
}

:where(.estimating-workspace) .modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}

:where(.estimating-workspace) .modal {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  width: 460px;
  max-width: 92vw;
  max-height: 88vh;
  overflow-y: auto;
}

:where(.estimating-workspace) .modal.modal-wide {
  width: 650px;
}

/* Between wide and xl: a form that has outgrown 650px but would look
   stranded at the grid-sized 1180px, e.g. the send email modal. */
:where(.estimating-workspace) .modal.modal-wider {
  width: 880px;
}

:where(.estimating-workspace) .modal.modal-xl {
  width: 1180px;
}

:where(.estimating-workspace) .modal h2 {
  margin: 0 0 16px;
  font-size: 20px;
}

:where(.estimating-workspace) .field {
  margin-bottom: 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

:where(.estimating-workspace) .field label,
:where(.estimating-workspace) label.field {
  font-size: 13px;
  color: var(--text-dim);
}

:where(.estimating-workspace) .field input,
:where(.estimating-workspace) .field select,
:where(.estimating-workspace) .field textarea {
  width: 100%;
}

:where(.estimating-workspace) .row {
  display: flex;
  gap: 10px;
}

:where(.estimating-workspace) .row > .field {
  flex: 1;
  min-width: 0;
}

:where(.estimating-workspace) .modal-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-top: 20px;
}

:where(.estimating-workspace) .modal-actions .right {
  display: flex;
  gap: 8px;
  margin-left: auto;
}

:where(.estimating-workspace) .modal-actions .left {
  display: flex;
  gap: 8px;
}

:where(.estimating-workspace) .notice {
  padding: 10px 12px;
  margin-bottom: 14px;
  border-left: 3px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--text-dim);
  font-size: 13px;
}

:where(.estimating-workspace) .notice-warning {
  border-left-color: var(--warn);
  background: color-mix(in srgb, var(--warn) 14%, transparent);
  color: var(--warn);
}

:where(.estimating-workspace) .error-text {
  color: var(--danger);
}

:where(.estimating-workspace) .warning-text {
  color: var(--warn);
}

:where(.estimating-workspace) .email-subject-button {
  display: block;
  max-width: 420px;
  padding: 0;
  overflow: hidden;
  border: 0;
  background: transparent;
  color: var(--text);
  font-size: 14px;
  font-weight: 600;
  text-align: left;
  text-overflow: ellipsis;
  white-space: nowrap;
}

:where(.estimating-workspace) .email-subject-button:hover {
  color: var(--accent);
  text-decoration: underline;
}

:where(.estimating-workspace) .email-meta {
  color: var(--text-dim);
  font-size: 12px;
  margin-top: 2px;
}

:where(.estimating-workspace) .email-body {
  max-height: 340px;
  overflow: auto;
  padding: 12px;
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font:
    13px/1.5 ui-monospace,
    SFMono-Regular,
    Consolas,
    monospace;
  white-space: pre-wrap;
}

:where(.estimating-workspace) .linked-email-list {
  border-top: 1px solid var(--border);
  margin-top: 20px;
  padding-top: 16px;
}

:where(.estimating-workspace) .linked-email-list h3 {
  font-size: 15px;
  margin: 0 0 8px;
}

/* Estimate schedule workspace */
:where(.estimating-workspace) .schedule-page {
  min-width: 1050px;
  min-height: 100%;
  padding: 24px 28px 36px;
  background:
    radial-gradient(circle at 75% -20%, color-mix(in srgb, var(--accent) 12%, transparent), transparent 34%), var(--bg);
}

:where(.estimating-workspace) .schedule-loading {
  padding: 28px;
  color: var(--text-dim);
}

:where(.estimating-workspace) .schedule-heading {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  max-width: 1800px;
  margin: 0 auto 20px;
}

:where(.estimating-workspace) .schedule-title-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

:where(.estimating-workspace) .schedule-title-row h1 {
  margin: 0;
  font-size: 26px;
  font-weight: 680;
  letter-spacing: -0.02em;
}

:where(.estimating-workspace) .schedule-status {
  padding: 3px 8px;
  border: 1px solid color-mix(in srgb, var(--warn) 48%, var(--border));
  border-radius: 999px;
  background: color-mix(in srgb, var(--warn) 11%, transparent);
  color: #f9c968;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

:where(.estimating-workspace) .schedule-heading p {
  margin: 6px 0 0;
  color: var(--text-dim);
  font-size: 13px;
}

:where(.estimating-workspace) .schedule-heading-actions {
  display: flex;
  align-items: center;
  gap: 14px;
}

:where(.estimating-workspace) .save-state {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text-dim);
  font-size: 12px;
}

:where(.estimating-workspace) .save-state svg {
  color: #62b6a9;
}

:where(.estimating-workspace) .schedule-summary {
  display: flex;
  align-items: stretch;
  max-width: 1800px;
  min-height: 72px;
  margin: 0 auto 12px;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: linear-gradient(100deg, color-mix(in srgb, var(--panel-alt) 45%, var(--panel)), var(--panel));
}

:where(.estimating-workspace) .schedule-summary-item,
:where(.estimating-workspace) .schedule-summary-total {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 12px 22px;
}

:where(.estimating-workspace) .schedule-summary-item span,
:where(.estimating-workspace) .schedule-summary-total span {
  margin-bottom: 4px;
  color: var(--text-dim);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

:where(.estimating-workspace) .schedule-summary-item strong {
  font-size: 18px;
}

:where(.estimating-workspace) .schedule-summary-divider {
  width: 1px;
  margin: 14px 0;
  background: var(--border);
}

:where(.estimating-workspace) .schedule-summary-total {
  align-items: flex-end;
  min-width: 210px;
  margin-left: auto;
  border-left: 1px solid var(--border);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}

:where(.estimating-workspace) .schedule-summary-total strong {
  color: #7fc8bd;
  font-size: 20px;
  font-variant-numeric: tabular-nums;
}

:where(.estimating-workspace) .schedule-summary-total small {
  margin-top: 2px;
  color: var(--text-dim);
  font-size: 10px;
}

:where(.estimating-workspace) .schedule-workspace {
  max-width: 1800px;
  margin: 0 auto;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--panel);
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.14);
}

:where(.estimating-workspace) .schedule-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 51px;
  padding: 7px 9px;
  border-bottom: 1px solid var(--border);
}

:where(.estimating-workspace) .schedule-toolbar-group {
  display: flex;
  align-items: center;
  gap: 3px;
}

:where(.estimating-workspace) .schedule-tool {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 9px;
  border-color: transparent;
  background: transparent;
  color: var(--text-dim);
  font-size: 12px;
}

:where(.estimating-workspace) .schedule-tool:hover:not(:disabled) {
  border-color: var(--border);
  color: var(--text);
}

:where(.estimating-workspace) .schedule-tool-danger:hover:not(:disabled) {
  border-color: color-mix(in srgb, var(--danger) 60%, var(--border));
  color: #ff777b;
}

:where(.estimating-workspace) .schedule-tool-divider {
  width: 1px;
  height: 22px;
  margin: 0 5px;
  background: var(--border);
}

:where(.estimating-workspace) .shortcut-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  padding: 6px 14px;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--accent) 8%, var(--panel));
  color: var(--text-dim);
  font-size: 11px;
}

:where(.estimating-workspace) .shortcut-strip kbd {
  padding: 1px 5px;
  border: 1px solid var(--border);
  border-bottom-width: 2px;
  border-radius: 4px;
  background: var(--panel-alt);
  color: var(--text);
  font-family: inherit;
  font-size: 10px;
}

:where(.estimating-workspace) .schedule-grid-scroll {
  overflow-x: auto;
}

:where(.estimating-workspace) .schedule-grid {
  min-width: 1530px;
  table-layout: fixed;
}

:where(.estimating-workspace) .schedule-grid .col-select {
  width: 56px;
}

:where(.estimating-workspace) .schedule-grid .col-detail {
  width: 88px;
}

:where(.estimating-workspace) .schedule-grid .col-group {
  width: 138px;
}

:where(.estimating-workspace) .schedule-grid .col-code {
  width: 108px;
}

:where(.estimating-workspace) .schedule-grid .col-item {
  width: 232px;
}

:where(.estimating-workspace) .schedule-grid .col-product {
  width: 260px;
}

:where(.estimating-workspace) .schedule-grid .col-uom {
  width: 82px;
}

:where(.estimating-workspace) .schedule-grid .col-quantity {
  width: 95px;
}

:where(.estimating-workspace) .schedule-grid .col-price {
  width: 108px;
}

:where(.estimating-workspace) .schedule-grid .col-cost {
  width: 126px;
}

:where(.estimating-workspace) .schedule-grid th,
:where(.estimating-workspace) .schedule-grid td {
  height: 43px;
  padding: 0;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

:where(.estimating-workspace) .schedule-grid th:last-child,
:where(.estimating-workspace) .schedule-grid td:last-child {
  border-right: 0;
}

:where(.estimating-workspace) .schedule-grid thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  height: 39px;
  padding: 0 9px;
  background: color-mix(in srgb, var(--panel-alt) 75%, var(--panel));
  color: #b2bbcf;
  font-size: 10px;
  letter-spacing: 0.055em;
  white-space: nowrap;
}

:where(.estimating-workspace) .schedule-grid th span {
  display: block;
  margin-top: 1px;
  color: #6f7a94;
  font-size: 8px;
  font-weight: 500;
  letter-spacing: 0.04em;
}

:where(.estimating-workspace) .schedule-grid .number-heading {
  text-align: right;
}

:where(.estimating-workspace) .schedule-grid tbody tr {
  background: var(--panel);
}

:where(.estimating-workspace) .schedule-grid tbody tr:hover,
:where(.estimating-workspace) .schedule-grid tbody tr:focus-within {
  background: color-mix(in srgb, var(--panel-alt) 62%, var(--panel));
}

:where(.estimating-workspace) .schedule-grid tbody tr.schedule-row-selected {
  background: color-mix(in srgb, var(--accent) 13%, var(--panel));
}

:where(.estimating-workspace) .schedule-grid input:not([type='checkbox']),
:where(.estimating-workspace) .schedule-grid select {
  width: 100%;
  height: 42px;
  padding: 0 9px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--text);
  font-size: 12px;
}

:where(.estimating-workspace) .schedule-grid input::placeholder {
  color: #69738a;
}

:where(.estimating-workspace) .schedule-grid input:not([type='checkbox']):focus,
:where(.estimating-workspace) .schedule-grid select:focus {
  position: relative;
  z-index: 1;
  outline: 2px solid #19a99d;
  outline-offset: -2px;
  background: color-mix(in srgb, var(--accent) 7%, var(--panel));
}

:where(.estimating-workspace) .schedule-grid select.uom-locked {
  padding-right: 24px;
  background-color: color-mix(in srgb, var(--bg) 55%, transparent);
  color: #8994ab;
}

:where(.estimating-workspace) .number-input {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

:where(.estimating-workspace) .product-cell {
  position: relative;
}

:where(.estimating-workspace) .product-cell input {
  padding-right: 30px !important;
}

:where(.estimating-workspace) .product-linked {
  position: absolute;
  top: 50%;
  right: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  transform: translateY(-50%);
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 35%, var(--panel));
  color: #8ee2d5;
  pointer-events: none;
}

:where(.estimating-workspace) .product-linked svg {
  width: 11px;
  height: 11px;
  stroke-width: 2.3;
}

:where(.estimating-workspace) .schedule-select-cell {
  position: relative;
  padding: 0 8px !important;
  text-align: center !important;
}

:where(.estimating-workspace) .schedule-select-cell input[type='checkbox'] {
  width: 14px;
  height: 14px;
  margin: 0;
  accent-color: var(--accent);
}

:where(.estimating-workspace) .schedule-row-number {
  position: absolute;
  top: 50%;
  left: 6px;
  transform: translateY(-50%);
  color: #68738b;
  font-size: 9px;
  font-variant-numeric: tabular-nums;
}

:where(.estimating-workspace) .schedule-cost,
:where(.estimating-workspace) .schedule-cost-empty {
  padding: 0 10px !important;
  color: #dce3ee;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

:where(.estimating-workspace) .schedule-cost-empty {
  color: #68738b;
}

:where(.estimating-workspace) .schedule-grid tfoot td {
  height: 47px;
  border-bottom: 0;
  background: color-mix(in srgb, var(--panel-alt) 52%, var(--panel));
}

:where(.estimating-workspace) .schedule-add-line {
  margin-left: 7px;
  border: 0;
  background: transparent;
  color: #71c8bb;
  font-size: 12px;
}

:where(.estimating-workspace) .schedule-add-line:hover:not(:disabled) {
  color: #99e3d8;
}

:where(.estimating-workspace) .schedule-total-label {
  padding-right: 10px !important;
  color: var(--text-dim);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-align: right;
  text-transform: uppercase;
}

:where(.estimating-workspace) .schedule-total-value {
  padding-right: 10px !important;
  color: #86d4c8;
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

:where(.estimating-workspace) .schedule-footer-note {
  padding: 9px 12px;
  border-top: 1px solid var(--border);
  color: #707b93;
  font-size: 10px;
  text-align: right;
}

@media (max-width: 720px) {
  :where(.estimating-workspace) .page-container {
    padding: 14px;
  }

  :where(.estimating-workspace) .page-header,
  :where(.estimating-workspace) .row {
    align-items: stretch;
    flex-direction: column;
  }

  :where(.estimating-workspace) .page-toolbar > input {
    width: 100% !important;
  }

  :where(.estimating-workspace) .modal-backdrop {
    align-items: flex-start;
  }

  :where(.estimating-workspace) .modal,
  :where(.estimating-workspace) .modal.modal-wide,
  :where(.estimating-workspace) .modal.modal-wider,
  :where(.estimating-workspace) .modal.modal-xl {
    width: 100%;
    max-width: none;
    max-height: 100vh;
    min-height: 100vh;
    border-radius: 0;
  }
}

/* Compare schedules ------------------------------------------------- */

/* A row each, the select taking the full width: these labels carry the
   schedule, its client and which revision, and two of them sharing a line
   left each one too narrow to read to the end. */
:where(.estimating-workspace) .compare-picker {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 8px 10px;
  margin: -6px 0 16px;
}

:where(.estimating-workspace) .compare-picker select {
  width: 100%;
  min-width: 0;
}

:where(.estimating-workspace) .compare-picker span {
  color: var(--text-dim);
  font-size: 13px;
}

/* Names the side each picker fills in, so the counts and the column
   headings below have something to refer to. */
:where(.estimating-workspace) .compare-side {
  flex: none;
  width: 22px;
  padding: 2px 0;
  border-radius: 6px;
  background: color-mix(in srgb, var(--text-dim) 16%, transparent);
  color: var(--text);
  font-size: 12px;
  font-weight: 650;
  text-align: center;
}

:where(.estimating-workspace) .compare-counts {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 12px;
  color: var(--text-dim);
  font-size: 13px;
}

/* Separated rather than just spaced, so four counts in a row read as four
   things and not as one sentence. Matches how the PDF joins them. */
:where(.estimating-workspace) .compare-counts span:not(:last-child)::after {
  content: '·';
  margin-left: 16px;
  color: var(--border);
}

:where(.estimating-workspace) .compare-table {
  width: 100%;
  margin-bottom: 18px;
  border-collapse: collapse;
  font-size: 13px;
}

:where(.estimating-workspace) .compare-table th,
:where(.estimating-workspace) .compare-table td {
  padding: 6px 8px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: top;
}

:where(.estimating-workspace) .compare-table tfoot td {
  border-bottom: 0;
  font-weight: 650;
}

/* A fixed width, so the figures table above and the lines table below put
   their A, B and Difference columns at the same place on the page — the two
   are separate tables and would otherwise each size to their own content.
   The label and line columns are the flexible ones that take up the slack,
   which is how the PDF lays the same report out. Wide enough for a
   nine-figure tender; nowrap and tabular numerals keep the digits from
   reflowing under it. */
:where(.estimating-workspace) .compare-table .number-cell,
:where(.estimating-workspace) .compare-table .number-heading {
  width: 140px;
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

:where(.estimating-workspace) .compare-setting-row td {
  color: var(--text-dim);
}

/* The margin a profit figure represents, under the money rather than in
   brackets beside it — these cells don't wrap, so the two together ran on
   into the next column. */
:where(.estimating-workspace) .compare-figure-note {
  margin-top: 1px;
  color: var(--text-dim);
  font-size: 11px;
  font-weight: 400;
}

/* Group and cost code: narrow and unwrapped, so each takes only the width
   its own text needs and the description beside them keeps the rest. */
:where(.estimating-workspace) .compare-table .compare-tight-heading,
:where(.estimating-workspace) .compare-table .compare-tight-cell {
  width: 1%;
  white-space: nowrap;
}

:where(.estimating-workspace) .compare-up {
  color: var(--success);
}

:where(.estimating-workspace) .compare-down {
  color: var(--danger);
}

:where(.estimating-workspace) .compare-lines-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 6px;
}

:where(.estimating-workspace) .compare-lines-heading h3 {
  margin: 0;
  font-size: 14px;
}

:where(.estimating-workspace) .compare-lines-heading label {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text-dim);
  font-size: 12px;
}

:where(.estimating-workspace) .compare-pill {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 650;
  white-space: nowrap;
}

:where(.estimating-workspace) .compare-pill-added {
  background: color-mix(in srgb, var(--success) 18%, transparent);
  color: var(--success);
}

:where(.estimating-workspace) .compare-pill-removed {
  background: color-mix(in srgb, var(--danger) 18%, transparent);
  color: var(--danger);
}

:where(.estimating-workspace) .compare-pill-changed {
  background: color-mix(in srgb, var(--warn) 20%, transparent);
  color: var(--warn);
}

:where(.estimating-workspace) .compare-pill-unchanged {
  background: color-mix(in srgb, var(--text-dim) 14%, transparent);
  color: var(--text-dim);
}

:where(.estimating-workspace) .compare-line-change {
  margin-top: 2px;
  color: var(--text);
  font-size: 12px;
}

:where(.estimating-workspace) .compare-note {
  margin: -6px 0 0;
  color: var(--text-dim);
  font-size: 12px;
}

/* The padlocks beside Discount and Final price (see PriceLockButton): the
   closed one is in the accent colour, the open one dim until hovered. */
:where(.estimating-workspace) .price-lock-button {
  display: inline-flex;
  align-items: center;
  margin-left: 5px;
  padding: 1px;
  border: 0;
  border-radius: 3px;
  background: none;
  color: var(--text-dim);
  vertical-align: -1px;
  cursor: pointer;
}

:where(.estimating-workspace) .price-lock-button[aria-pressed='true'] {
  color: var(--accent);
  cursor: default;
}

:where(.estimating-workspace) .price-lock-button:not([aria-pressed='true']):not(:disabled):hover {
  color: var(--text);
}

:where(.estimating-workspace) .price-lock-button:disabled {
  cursor: default;
  opacity: 0.6;
}

:root {
  --bg: #0f1420;
  --panel: #161d2e;
  --panel-alt: #1d263b;
  --border: #2a3550;
  --text: #e6e9f2;
  --text-dim: #9aa4bf;
  /* A slightly muted version of favicon.svg's terracotta — used everywhere
     (main nav, buttons, links) for one consistent theme colour. */
  --accent: #da5a2f;
  /* --danger / --warn / --success come from wrs-core's tokens.css */
  --radius: 8px;
  font-family: -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  color-scheme: dark;
}

* {
  box-sizing: border-box;
}

html,
body,
#root {
  height: 100%;
  margin: 0;
}

body {
  background: var(--bg);
  color: var(--text);
}

button {
  font-family: inherit;
  cursor: pointer;
}

input,
select,
textarea {
  font-family: inherit;
  background: var(--panel-alt);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
}

input:focus,
select:focus,
textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}

a {
  color: var(--accent);
}

table {
  border-collapse: collapse;
  width: 100%;
}

th,
td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
}

th {
  color: var(--text-dim);
  font-weight: 600;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.btn {
  background: var(--panel-alt);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 7px 14px;
  font-size: 14px;
}

.btn:hover {
  border-color: var(--accent);
}

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: white;
  font-weight: 600;
}

.btn-primary:hover {
  filter: brightness(1.1);
}

.btn-icon-add {
  position: relative;
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: 50%;
  flex-shrink: 0;
}

.btn-icon-add:disabled {
  opacity: 0.5;
}

/* Drawn rather than a "+" glyph — font metrics never sit dead-center on a
   circle, this does. */
.btn-icon-add::before,
.btn-icon-add::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  background: currentColor;
  transform: translate(-50%, -50%);
}

.btn-icon-add::before {
  width: 18px;
  height: 2.5px;
}

.btn-icon-add::after {
  width: 2.5px;
  height: 18px;
}

.btn-icon-close {
  position: relative;
  width: 24px;
  height: 24px;
  padding: 0;
  border: none;
  background: none;
  border-radius: 50%;
  flex-shrink: 0;
  color: var(--text-dim);
}

.btn-icon-close:disabled {
  opacity: 0.5;
}

.btn-icon-close::before,
.btn-icon-close::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 14px;
  height: 2px;
  background: currentColor;
}

.btn-icon-close::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

.btn-icon-close::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

.btn-icon-contact {
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.btn-danger {
  color: var(--danger);
}

.btn-danger:hover {
  border-color: var(--danger);
}

.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  background: var(--panel-alt);
  border: 1px solid var(--border);
  color: var(--text-dim);
}

.toolbar-group {
  display: flex;
  gap: 2px;
  padding: 3px;
  background: var(--panel-alt);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.toolbar-group .btn {
  background: transparent;
  border: 1px solid transparent;
}

.toolbar-group .btn:hover {
  border-color: var(--border);
}

.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.checklist-item-row:hover {
  background: var(--panel-alt);
}

/* A collapsed multi-item JobDiary row (see JobDiary.tsx's renderGroupRow) —
   otherwise identical to a normal row; same hover feedback as any other
   clickable row (.checklist-item-row) rather than a permanent tint. */
.diary-group-row {
  cursor: pointer;
}

.diary-group-row:hover {
  background: var(--panel-alt);
}

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}

.modal {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  width: 460px;
  max-width: 92vw;
  max-height: 88vh;
  overflow-y: auto;
}

.modal.modal-wide {
  width: 650px;
}

.modal.modal-variation {
  width: 740px;
}

.modal.modal-booking {
  width: 700px;
}

.modal-booking .row > .field {
  min-width: 0;
}

.modal-booking .booking-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}

.booking-pricing {
  padding: 0;
  margin: 0;
  border: 0;
  min-width: 0;
}

.booking-field-hint {
  color: var(--text-dim);
  font-size: 12px;
  margin: -4px 0 12px;
  line-height: 1.5;
}

.booking-pricing-mode .booking-weekends {
  grid-column: span 2;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
  margin: 0;
}

.booking-pricing-mode .booking-row {
  align-items: center;
}

.booking-pricing input[readonly] {
  color: var(--text-dim);
}

@media (max-width: 560px) {
  .modal-booking .row {
    flex-direction: column;
    gap: 0;
  }

  .modal-booking .booking-row {
    grid-template-columns: 1fr;
    gap: 0;
  }

  .booking-pricing-mode .booking-weekends {
    grid-column: auto;
    margin-top: 8px;
  }
}

.modal h2 {
  margin-top: 0;
}

.field {
  margin-bottom: 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.field label {
  font-size: 13px;
  color: var(--text-dim);
}

.field input,
.field select,
.field textarea {
  width: 100%;
}

.full-width-field textarea {
  width: 100%;
}

.comment-composer {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}

.comment-composer input,
.comment-composer textarea {
  flex: 1;
  min-width: 0;
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 14px;
}

.btn-icon-send {
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.btn-icon-send svg {
  display: block;
  width: 19px;
  height: 19px;
  transform: translate(-1px, 1px);
}

.btn-icon-send:disabled {
  opacity: 0.5;
}

/* A job named on another job's page — a remedial job's parent, or a
   parent's remedial jobs. */
.job-link {
  color: var(--accent);
  text-decoration: none;
}

.job-link:hover {
  text-decoration: underline;
}

.row {
  display: flex;
  gap: 10px;
}

.row > .field {
  flex: 1;
}

.modal-actions {
  display: flex;
  justify-content: space-between;
  margin-top: 20px;
}

.modal-actions .right {
  display: flex;
  gap: 8px;
}

/* --- vis-timeline theming --- */

.vis-timeline {
  border: none !important;
  font-family: inherit;
}

.vis-labelset .vis-label {
  border-color: var(--border) !important;
  color: var(--text) !important;
}

.vis-labelset .vis-label.vis-nesting-group {
  background: var(--panel-alt) !important;
}

.vis-labelset .vis-label.vis-nested-group {
  background: var(--panel) !important;
}

.vis-labelset .vis-label.vis-nesting-group:hover {
  background: var(--border) !important;
}

/* vis-timeline recycles label DOM nodes on collapse/expand without always
   resetting alignment, and internally flips .vis-panel.vis-left to RTL (to
   put its scrollbar on the left) — pin ltr/text-align at every level so
   nothing leaks a stray right-aligned or RTL state onto reused nodes. */
.vis-labelset {
  direction: ltr !important;
}

.vis-labelset .vis-label {
  text-align: left !important;
  direction: ltr !important;
}

.vis-labelset .vis-label .vis-inner {
  text-align: left !important;
  direction: ltr !important;
}

.vis-labelset .vis-label.tl-job-group {
  /* Thicker and full-opacity vs. a phase row's border (see .tl-phase-group)
     so job rows read as visually distinct from their phase rows. */
  border-left: 5px solid var(--job-color, var(--border));
  /* Same job-type tint as the Jobs list (see JobsPage.tsx's jobTypeRowTint)
     — --job-type-color is set per-group in SchedulePage.tsx, separate from
     --job-color (the client's colour, used for the border/bars above). */
  background: color-mix(in srgb, var(--job-type-color, transparent) 12%, transparent);
}

.vis-labelset .vis-label.tl-job-group .vis-inner {
  padding-top: 6px;
  padding-bottom: 6px;
  line-height: 1.5;
}

/* Meta line is already hidden when collapsed (see .tl-job-meta below);
   tighten the remaining line's padding too so more jobs fit on screen. */
.vis-label.vis-nesting-group.tl-job-group:not(.expanded) .vis-inner {
  padding-top: 3px;
  padding-bottom: 3px;
}

.vis-labelset .vis-label.tl-phase-group {
  /* vis-timeline can drop the vis-group-level-0 class on collapse/expand,
     falling back to its own indent defaults — pin our own fixed values. */
  padding-left: 0 !important;
  /* Thinner and fainter than a job row's border (see .tl-job-group) — the
     quieter of the two. */
  border-left: 2px solid color-mix(in srgb, var(--job-color, var(--border)) 30%, transparent);
}

/* vis-timeline's own stylesheet applies padding-left straight onto
   `.vis-inner` keyed by `.vis-group-level-N`, at higher specificity than
   our single .tl-phase-group. Chaining the class twice bumps our
   specificity above it regardless of which level vis-timeline lands on. */
.vis-labelset .vis-label.tl-phase-group.tl-phase-group .vis-inner {
  padding-left: 0 !important;
  /* display:block, not inline-block — an inline-block's position follows
     its parent's text-align, which recycled DOM can leave right-aligned. */
  display: block !important;
  width: auto !important;
  line-height: 1.5;
}

/* Indented 18px to line up with the job header's text (10px dot + 8px gap). */
.tl-phase-title-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-left: 18px;
}

.tl-phase-index {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  /* Smaller/fainter than a job row's colour dot — shouldn't out-weigh it. */
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--job-color, var(--accent)) 20%, var(--panel));
  color: var(--text-dim);
  font-size: 9px;
  font-weight: 600;
}

.tl-phase-name {
  /* Smaller and dimmer than a job row's name — keeps phase rows reading
     as subordinate rather than a peer. */
  font-size: 12px;
  font-weight: 400;
  color: var(--text-dim);
}

.tl-phase-meta {
  padding-left: 18px;
  margin-top: 2px;
  font-size: 11px;
  color: var(--text-dim);
}

/* Job Detail's standalone phase Gantt (JobDetailPage.tsx) has no parent job
   row to line its text up under, so the 18px indent (see .tl-phase-title-row
   above) has nothing to align with — just wasted space here. */
.tl-phase-group--standalone .tl-phase-title-row {
  padding-left: 4px;
}

/* Job Detail's standalone phase Gantt (JobDetailPage.tsx) has no parent job
   row, so the phase name is the primary label rather than a subordinate
   one — full-brightness instead of .tl-phase-name's dim default. */
.tl-phase-group--standalone .tl-phase-name {
  color: var(--text);
}

/* A single glyph that rotates, rather than the default swapped triangles. */
.vis-label.vis-nesting-group:before {
  content: '\25B6' !important;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  width: 16px !important;
  height: 16px;
  margin-right: 3px;
  border-radius: 4px;
  color: var(--text-dim);
  font-size: 9px;
  vertical-align: middle;
  transition:
    transform 0.15s ease,
    color 0.15s ease,
    background-color 0.15s ease;
}

.vis-label.vis-nesting-group.expanded:before {
  transform: rotate(90deg);
}

.vis-label.vis-nesting-group:hover:before {
  color: var(--text);
  background-color: rgba(255, 255, 255, 0.08);
}

/* Drop the meta line so a collapsed job shrinks back to a single line. */
.vis-label.vis-nesting-group:not(.expanded) .tl-job-meta {
  display: none;
}

.vis-foreground .vis-group.vis-nested-group {
  background: var(--panel) !important;
}

/* Extend the label sidebar's panel-alt tint into the bars area too, so a
   job's row reads as one continuous band. */
.vis-foreground .vis-group.vis-nesting-group {
  background: var(--panel-alt) !important;
}

.vis-foreground .vis-group {
  border-color: var(--border) !important;
}

.vis-panel.vis-top,
.vis-panel.vis-bottom,
.vis-panel.vis-left,
.vis-panel.vis-right,
.vis-panel.vis-center {
  border-color: var(--border) !important;
}

.vis-time-axis .vis-text.vis-major {
  color: var(--text) !important;
  font-weight: 600;
  font-size: 12.5px;
  letter-spacing: 0.02em;
  padding: 6px 10px 4px !important;
}

.vis-time-axis .vis-text.vis-minor {
  color: var(--text-dim) !important;
  font-size: 12px;
  padding: 4px 8px !important;
}

.vis-time-axis .vis-grid.vis-minor {
  border-color: rgba(255, 255, 255, 0.045) !important;
}

.vis-time-axis .vis-grid.vis-major {
  border-color: #3c4a70 !important;
}

.vis-current-time {
  background-color: var(--accent) !important;
  width: 2px !important;
}

/* Our own tooltipRef div (TimelineView.tsx) replaces this entirely. */
.vis-tooltip {
  display: none !important;
}

.vis-item {
  border-radius: 5px;
  border-width: 1px;
  color: white;
  font-size: 12px;
}

/* vis-timeline appends TimeAxis before ItemSet, so without explicit z-index
   the itemset's background (weekend/holiday) paints over the grid lines.
   Pin the stack: grid lines, then bars, then weekend/holiday, then row-band
   stripes. `.vis-group` and `.vis-item` are siblings in `.vis-foreground` —
   z-index them individually (not the shared container) so weekend/holiday
   shading can sit between them without their translucent tints compounding. */
.vis-itemset .vis-background {
  z-index: 1;
}

.vis-item:not(.vis-background) {
  z-index: 2;
}

.vis-time-axis.vis-background {
  z-index: 3 !important;
  /* Without this, sitting on top intercepts pointer/wheel events that
     vis-timeline's pan/zoom/select handlers need below — silently killed
     all timeline interaction. */
  pointer-events: none;
}

/* Weekend/holiday shading — full-height background items, rendered
   behind every row and every assignment bar. */
.vis-item.vis-background.tl-weekend {
  background-color: rgba(255, 255, 255, 0.07) !important;
  border: none !important;
}

/* Blue, not red — red now means over-allocated/overcapacity (see
   .conflict and .tl-overcapacity below), and a holiday isn't a problem. */
.vis-item.vis-background.tl-holiday {
  background-color: rgba(79, 124, 255, 0.18) !important;
  border: none !important;
}

/* Days where pipeline/quoted plus real assignments exceed active headcount —
   an over-allocation, so red like .conflict; painted last so it wins over
   other shading. */
.vis-item.vis-background.tl-overcapacity {
  background-color: rgba(229, 72, 77, 0.22) !important;
  border: none !important;
}

.vis-item.tl-item {
  background-color: var(--job-color, var(--accent));
  border-color: var(--job-color, var(--accent));
}

/* Every tl-item bar opens something on double-click — its own modal, or the
   job page for job-summary (see SchedulePage.tsx's handleItemDoubleClick) —
   so they all get a pointer. Background bars (tl-weekend/tl-holiday/
   tl-overcapacity) carry no tl-item and stay as they are. The drag-centre
   overlay covers an editable bar edge to edge and would otherwise keep
   vis-timeline's own `move`; the left/right handles keep their resize
   cursors, since that edge really does resize rather than open anything. */
.vis-item.tl-item,
.vis-item.tl-item .vis-drag-center {
  cursor: pointer;
}

/* Selecting a movable bar makes dragging the live gesture, so the `move`
   cursor comes back — vis-timeline says as much itself in
   .vis-editable.vis-selected, but the drag-centre overlay sits above the bar
   and needs telling too. A bar that can't be moved (vis-readonly, e.g. the
   Schedule's job-summary rollup) keeps the pointer either way. */
.vis-item.tl-item.vis-editable.vis-selected,
.vis-item.tl-item.vis-editable.vis-selected .vis-drag-center {
  cursor: move;
}

.vis-item.tl-item.tentative {
  background-image: repeating-linear-gradient(
    45deg,
    var(--job-color, var(--accent)),
    var(--job-color, var(--accent)) 6px,
    rgba(255, 255, 255, 0.18) 6px,
    rgba(255, 255, 255, 0.18) 12px
  );
  border-style: dashed;
}

.vis-item.tl-item.status-closed,
.vis-item.tl-item.status-on_hold,
.vis-item.tl-item.status-lost {
  opacity: 0.55;
}

.vis-item.tl-item.job-summary {
  background-color: color-mix(in srgb, var(--job-color, var(--accent)) 30%, var(--panel));
  border-width: 1px;
  border-radius: 7px;
  font-weight: 400;
  font-size: 12px;
  color: var(--text);
}

.vis-item.tl-item.job-summary .vis-item-content {
  color: var(--text);
  /* Matches assignment bars' actual rendered padding (vis-timeline's 5px
     default — our .vis-item-content override below never applies, losing
     to it on specificity), not the unapplied 3px below. */
  padding: 5px 8px;
}

/* Keeps the tinted fill/dashed border from .tentative, minus the stripes —
   the dashed outline alone already reads as "not confirmed yet". */
.vis-item.tl-item.job-summary.tentative {
  background-image: none;
}

/* Outline-only (no fill) so person bars read as a lighter tier than the
   filled job-summary rollup, while still carrying the job colour. */
.vis-item.tl-item.person-bar {
  background-color: transparent;
  border-width: 1px;
  border-radius: 6px;
  color: var(--text);
}

.vis-item.tl-item.person-bar .vis-item-content {
  color: var(--text);
}

/* .person-bar already has no fill, so .tentative's stripes would paint solid
   colour into what's meant to be an empty outline — dashed border alone
   (still inherited) carries the "not confirmed" meaning here. */
.vis-item.tl-item.person-bar.tentative {
  background-image: none;
}

/* Shown for every phase, even unassigned ones, so the row always reads as
   "this is when it runs". Outline (not filled) so it never reads as an
   actual commitment. Dotted, not dashed, since dashed already means
   pipeline/quoted (.tentative) and a phase can sit on a confirmed job too. */
.vis-item.tl-item.phase-segment-bar {
  background-color: transparent;
  border-width: 1px;
  border-style: dotted;
  border-color: var(--job-color, var(--accent));
  border-radius: 6px;
  color: var(--text-dim);
}

.vis-item.tl-item.phase-segment-bar .vis-item-content {
  color: var(--text-dim);
}

/* Fewer real people booked than the phase's own estimate — amber like the
   overcapacity shading, solid instead of dotted so it stands out. */
.vis-item.tl-item.phase-segment-bar.understaffed {
  border-style: solid;
  border-color: #fab005;
  background-color: rgba(250, 176, 5, 0.12);
}

.vis-item.tl-item.phase-segment-bar.understaffed .vis-item-content {
  color: #fab005;
}

/* Distinct slate colour so leave never reads as job work, which is always
   coloured via --job-color. */
.vis-item.tl-item.leave-bar {
  background-color: #4a5468;
  border-color: #5b6680;
  border-width: 1px;
  border-radius: 6px;
  color: #fff;
}

.vis-item.tl-item.leave-bar .vis-item-content {
  color: #fff;
}

/* Same colour language as leave (also not job work), but distinct teal:
   leave means "not here", this means "here, just not on a job". */
.vis-item.tl-item.non-billable-bar {
  background-color: #2f6f68;
  border-color: #3f8a82;
  border-width: 1px;
  border-radius: 6px;
  color: #fff;
}

.vis-item.tl-item.non-billable-bar .vis-item-content {
  color: #fff;
}

/* Same outline-coloured-by-job treatment as .person-bar, so a plant booking
   reads as job work rather than "not available" (contrast .plant-service-bar). */
.vis-item.tl-item.plant-bar {
  background-color: transparent;
  border-width: 1px;
  border-radius: 6px;
  color: var(--text);
}

.vis-item.tl-item.plant-bar .vis-item-content {
  color: var(--text);
}

.vis-item.tl-item.plant-bar.tentative {
  background-image: none;
}

/* Same colour language as leave/non-billable, a distinct violet — not amber,
   since that already means understaffed. */
.vis-item.tl-item.plant-service-bar {
  background-color: #5c4a8a;
  border-color: #7a63ad;
  border-width: 1px;
  border-radius: 6px;
  color: #fff;
}

.vis-item.tl-item.plant-service-bar .vis-item-content {
  color: #fff;
}

/* Distinct gold — meetings aren't job work, leave, or non-billable time,
   and don't participate in the allocation conflict colours below. */
.vis-item.tl-item.meeting-bar {
  background-color: #8a6d1a;
  border-color: #c9a227;
  border-width: 1px;
  border-radius: 6px;
  color: #fff;
}

.vis-item.tl-item.meeting-bar .vis-item-content {
  color: #fff;
}

/* One occurrence of a recurring MeetingSeries (materialized or still
   virtual) — same fill as a one-off meeting, dashed border as the only
   visual cue it belongs to a series rather than being a single meeting. */
.vis-item.tl-item.meeting-series-bar {
  border-style: dashed;
}

/* Mirrors .understaffed (solid red border, lighter red fill) — same
   specificity as the bar-type rules above, so it must come after all of
   them to win on any bar (leave, plant, etc.) flagged conflict. */
.vis-item.tl-item.conflict {
  border-style: solid;
  border-color: var(--danger);
  background-color: rgba(229, 72, 77, 0.12);
}

.vis-item.tl-item.conflict .vis-item-content {
  color: var(--danger);
}

.vis-item.vis-selected {
  box-shadow: 0 0 0 2px white;
}

.vis-item .vis-item-content {
  padding: 3px 8px;
}

.color-swatch-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.color-swatch {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.15);
  padding: 0;
  cursor: pointer;
}

.color-swatch:hover {
  transform: scale(1.1);
}

.color-swatch:disabled {
  cursor: default;
  opacity: 0.6;
}

.color-swatch:disabled:hover {
  transform: none;
}

.color-swatch.selected {
  box-shadow:
    0 0 0 2px var(--panel),
    0 0 0 4px white;
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
  font-size: 12px;
  color: var(--text-dim);
}

.legend-swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 3px;
  margin-right: 5px;
  vertical-align: middle;
}

/* LentuneContractItemsModal.tsx (the job schedule's contract items export). */
.modal.lentune-contract-modal {
  width: 940px;
}

.contract-item-builder {
  margin: 20px 0;
}

.contract-item-builder-label {
  color: var(--text-dim);
  font-size: 13px;
  margin: 0 0 10px;
}

.cost-code-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.cost-code-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 8px 12px;
  background: var(--panel-alt);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  text-align: left;
}

button.cost-code-pill {
  cursor: pointer;
}

.cost-code-pill span {
  overflow-wrap: anywhere;
}

.cost-code-pill em {
  color: var(--text-dim);
  font-style: normal;
  white-space: nowrap;
}

.cost-code-pill.is-selected {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 25%, var(--panel));
  box-shadow: inset 0 0 0 1px var(--accent);
}

.cost-code-pill:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 2px;
}

.cost-code-pill.is-static {
  padding: 3px 8px;
}

.contract-item-compose {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
}

.contract-item-compose input {
  flex: 1 1 220px;
  min-width: 0;
}

.contract-items-scroll {
  overflow-x: auto;
  margin: 16px 0;
}

.contract-items-table {
  width: 100%;
  min-width: 540px;
  border-collapse: collapse;
}

.contract-items-table th,
.contract-items-table td {
  padding: 10px 8px;
  border-bottom: 1px solid var(--border);
  text-align: left;
}

.contract-items-table th {
  color: var(--text-dim);
  font-size: 13px;
}

.contract-items-table input {
  width: 100%;
  min-width: 160px;
}

.contract-items-table .num {
  text-align: right;
  white-space: nowrap;
}

.contract-items-table tfoot {
  font-weight: 600;
}
