/* ===================================================================
   SaberTask Design System — reusable tokens + form/control primitives.
   Source of truth for buttons, inputs, dropdowns, toggles, etc. so components
   don't re-declare control styling. Imported globally from index.html.

   Two ways to consume:
   1. Native HTML  → use the .st-* primitive classes (.st-input, .st-btn-*, …).
   2. MudBlazor    → wrap a region in .st-form; the adapter at the bottom
                     reskins Mud outlined inputs/selects/pickers to match.
   ========================================================================== */

:root {
  /* ---------- Color · Primary (product) ---------- */
  --st-primary-50:  #EEF1FE;
  --st-primary-100: #DCE2FD;
  --st-primary-light: #EEF3FE;   /* product tint bg / active row */
  --st-primary-border: #C7D8FD;
  --st-primary:        #4A76F9;   /* product brand (admin + app) */
  --st-primary-hover:  #3561E0;   /* == MudTheme PrimaryDarken (single hover blue) */
  --st-primary-focus-ring: rgba(74, 118, 249, 0.15);

  /* ---------- Color · Neutrals (slate) ---------- */
  --st-white:        #FFFFFF;
  --st-bg:           #F8FAFC;
  --st-bg-alt:       #F1F5F9;
  --st-surface-alt:  #FAFBFD;   /* second column / total strips */
  --st-border:       #E8EDF5;
  --st-border-hover: #CBD5E1;
  --st-border-light: #F1F5F9;
  --st-subtle:       #94A3B8;   /* muted/placeholder + section meta */
  --st-muted:        #64748B;   /* secondary text */
  --st-text:         #1E293B;   /* primary text */
  --st-text-strong:  #0A0F18;   /* headings / input text */

  /* ---------- Color · Semantic (== MudTheme palette: one value per semantic) ---------- */
  --st-success:        #22C55E;
  --st-success-dark:   #047857;
  --st-success-light:  #F0FDF4;
  --st-warning:        #F97316;
  --st-warning-light:  #FFF7ED;
  --st-error:          #EF4444;
  --st-error-dark:     #B91C1C;
  --st-error-light:    #FEF2F2;
  --st-caution:        #EAB308;   /* traffic-light yellow (distinct from the orange warning) */
  --st-caution-light:  #FEFCE8;

  /* ---------- Color · Route paint (feature constants) ----------
     The OSM road-group identity colours and the eraser treatment used by the Planning
     route paintbrush. The same three group values are the GROUP_COLORS constant in
     wwwroot/js/route-paint.js (the map layers are painted from JS, the legend from CSS),
     so they live in exactly these two places and are never re-typed inline. */
  --st-paint-one-lane:   var(--st-error);   /* single-lane road   */
  --st-paint-multi-lane: #16A34A;           /* two or more lanes  */
  --st-paint-walkway:    #707070;           /* footway / cycleway */
  --st-paint-erase:      var(--st-error);   /* eraser tool        */

  /* ---------- Type ---------- */
  --st-font-heading: 'Plus Jakarta Sans', 'Inter', system-ui, -apple-system, sans-serif;
  --st-font-body:    'Inter', system-ui, -apple-system, sans-serif;

  /* ---------- Radii ---------- */
  --st-radius-sm:   6px;
  --st-radius:      8px;    /* button / input / chip */
  --st-radius-md:   12px;   /* card / dropdown / popover */
  --st-radius-lg:   16px;   /* modal */
  --st-radius-full: 9999px;

  /* ---------- Spacing (8-pt) ---------- */
  --st-space-1: 4px;  --st-space-2: 8px;  --st-space-3: 12px;
  --st-space-4: 16px; --st-space-5: 20px; --st-space-6: 24px; --st-space-8: 32px;

  /* ---------- Shadows ---------- */
  --st-shadow-sm: 0 1px 2px rgba(10, 15, 24, 0.06);
  --st-shadow:    0 4px 12px rgba(15, 23, 42, 0.06);
  --st-shadow-md: 0 8px 20px rgba(15, 23, 42, 0.08);
  --st-shadow-popover: 0 18px 40px -10px rgba(10,15,24,0.25), 0 0 0 1px rgba(10,15,24,0.04);
  --st-shadow-modal:   0 24px 80px -16px rgba(10,15,24,0.35), 0 0 0 1px rgba(10,15,24,0.04);

  /* ---------- Motion ---------- */
  --st-ease: cubic-bezier(0.4, 0, 0.2, 1);
  --st-duration-fast: 150ms;
}

/* ===================================================================
   Page header — title row used by the PageHeader component
   ========================================================================== */
.st-page-header { margin-bottom: var(--st-space-4); }
.st-page-header__inner {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--st-space-4); flex-wrap: wrap;
}
.st-page-header__titles { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.st-page-header__actions { display: flex; align-items: center; gap: var(--st-space-2); flex-shrink: 0; }
/* At the top of the main content column (replacing the old full-width topbar) the header
   is a full-bleed sticky bar — background + divider run edge to edge — while the inner row
   is constrained to .st-content's max-width so the title lines up with the content below. */
.st-main > .st-page-header {
  margin-bottom: 0;
  position: sticky; top: 0; z-index: 20;
  background: var(--st-white);
  border-bottom: 1px solid var(--st-border);
}
.st-main > .st-page-header > .st-page-header__inner {
  max-width: 1600px; width: 100%; box-sizing: border-box;
  margin: 0 auto; padding: var(--st-space-4) var(--st-space-6);
}
@media (max-width: 768px) {
  .st-main > .st-page-header { position: static; }
  .st-main > .st-page-header > .st-page-header__inner { padding: var(--st-space-4); }
}

/* ===================================================================
   Connectivity banner (offline / server unreachable)
   ========================================================================== */
.st-conn-banner {
  position: sticky; top: 0; z-index: 1400;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 7px 16px;
  background: var(--st-warning); color: var(--st-white);
  font-size: 13px; font-weight: 600;
  box-shadow: var(--st-shadow-sm);
}
/* Newer bundle deployed (stUpdate in index.html) — same strip, primary-coloured, with a reload action. */
.st-update-banner {
  position: sticky; top: 0; z-index: 1400;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 7px 16px;
  background: var(--st-primary); color: var(--st-white);
  font-size: 13px; font-weight: 600;
  box-shadow: var(--st-shadow-sm);
}
.st-update-banner-btn {
  background: var(--st-white); color: var(--st-primary);
  border: none; border-radius: var(--st-radius-sm);
  padding: 3px 12px; font: inherit; cursor: pointer;
}

/* ===================================================================
   Error / load-failure state (ErrorState component)
   ========================================================================== */
.st-error-state {
  padding: 48px 24px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.st-error-state__icon { font-size: 40px !important; color: var(--st-subtle); margin-bottom: 8px; }
.st-error-state__title { font-weight: 600; color: var(--st-text); }
.st-error-state__detail { color: var(--st-subtle); max-width: 460px; word-break: break-word; }
.st-error-state__action { margin-top: 12px; }

/* Empty ("nothing here yet") state */
.st-empty-state {
  padding: 48px 24px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
}
/* Legacy bare icon, still used by hand-written empty states (KnowledgeServiceTypesView). */
.st-empty-state__icon { font-size: 44px !important; color: var(--st-border-hover); margin-bottom: 8px; }
/* EmptyState component: a 44px primary-tinted tile holding the icon. */
.st-empty-state__tile {
  width: 44px; height: 44px; border-radius: var(--st-radius-md);
  background: var(--st-primary-light); color: var(--st-primary);
  display: inline-flex; align-items: center; justify-content: center;
  margin-bottom: 10px; flex-shrink: 0;
}
.st-empty-state__tile .mud-icon-root { font-size: 22px; }
.st-empty-state__title { font-size: 15px; font-weight: 600; color: var(--st-text); }
.st-empty-state__hint { color: var(--st-muted); max-width: 420px; }
.st-empty-state__action { margin-top: 16px; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--st-space-2); }
/* "No results for these filters": a shorter block than the "nothing here yet" state. */
.st-empty-state.st-empty-state--compact { padding: 32px 24px; }
.st-empty-state--compact .st-empty-state__action { margin-top: 12px; }

/* ===================================================================
   Section header — uppercase 11px label with optional leading icon
   ========================================================================== */
/* A titled block of fields: the section's gap is the only thing that spaces its rows, so
   every field lines up regardless of control type (see the .st-form adapter at the bottom,
   which strips MudBlazor's per-field margins and growth). */
.st-section { display: flex; flex-direction: column; gap: 10px; }
/* A section's rows are intrinsically sized: the gap above is the only thing between them.
   Without this, MudBlazor's own `flex: 1 1 auto` on .mud-input-control (and `flex-grow: 1`
   on .mud-select) makes every field absorb the leftover height whenever the section sits in
   a height-constrained column (a side panel whose body scrolls), so a 38px input box
   renders 100px tall and the form reads as huge gaps. Deliberately not !important, so an
   explicit .flex-grow-1 on a row that really should stretch still wins. */
.st-section > * { flex-grow: 0; }
.st-section-title {
  margin: 0 0 12px;
  font-family: var(--st-font-body);
  font-size: 11px; font-weight: 700;
  color: var(--st-muted);
  text-transform: uppercase; letter-spacing: 0.06em;
  display: flex; align-items: center; gap: 6px;
}
.st-section-title svg,
.st-section-title .mud-icon-root { width: 14px; height: 14px; font-size: 14px; color: var(--st-subtle); }

/* ===================================================================
   Field + label (top-label style)
   ========================================================================== */
.st-field { display: flex; flex-direction: column; gap: 6px; }
.st-field > label {
  font-size: 12px; font-weight: 600; color: var(--st-text);
  display: flex; align-items: center; gap: 4px;
}
.st-field > label .req { color: var(--st-primary); }
.st-field .st-hint { font-size: 11px; color: var(--st-subtle); margin-top: 2px; }

/* ===================================================================
   Inputs / selects / textareas (native)
   ========================================================================== */
.st-input, .st-select, .st-textarea {
  width: 100%;
  background: var(--st-white);
  border: 1px solid var(--st-border);
  border-radius: var(--st-radius);
  padding: 10px 12px;
  font-family: var(--st-font-body);
  font-size: 14px; color: var(--st-text-strong);
  outline: none;
  transition: border-color var(--st-duration-fast), box-shadow var(--st-duration-fast), background var(--st-duration-fast);
}
.st-input::placeholder, .st-textarea::placeholder { color: var(--st-subtle); }
.st-input:hover, .st-select:hover, .st-textarea:hover { border-color: var(--st-border-hover); }
.st-input:focus, .st-select:focus, .st-textarea:focus {
  border-color: var(--st-primary);
  box-shadow: 0 0 0 3px var(--st-primary-focus-ring);
}
.st-input:disabled, .st-select:disabled, .st-textarea:disabled {
  background: var(--st-bg); color: var(--st-subtle); cursor: not-allowed; border-color: var(--st-border-light);
}
.st-textarea { resize: vertical; min-height: 90px; line-height: 1.5; }

/* Custom select with caret */
.st-select-wrap { position: relative; }
.st-select { appearance: none; -webkit-appearance: none; padding-right: 36px; cursor: pointer; }
.st-select-wrap > .st-caret {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  width: 14px; height: 14px; color: var(--st-subtle); pointer-events: none;
}

/* Field + trailing action button (the "+" add-new) */
.st-with-action { display: flex; align-items: stretch; gap: 8px; }
.st-with-action > .st-select-wrap, .st-with-action > .st-input, .st-with-action > div { flex: 1; min-width: 0; }
/* Strip MudBlazor's field margins so the field wrapper height == the input box height;
   the stretched action button then matches the input box exactly (square, same height). */
.st-with-action .mud-input-control { margin-top: 0 !important; margin-bottom: 0 !important; }
.st-action-btn {
  width: 40px; flex-shrink: 0; align-self: stretch;
  border: 1px solid var(--st-border); background: var(--st-white); border-radius: var(--st-radius);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--st-muted); cursor: pointer;
  transition: border-color var(--st-duration-fast), background var(--st-duration-fast), color var(--st-duration-fast);
}
.st-action-btn:hover { border-color: var(--st-primary); color: var(--st-primary); background: #F5F8FF; }
.st-action-btn svg, .st-action-btn .mud-icon-root { width: 16px; height: 16px; font-size: 16px; }
/* Compact square hairline icon button for card actions (same visual language as .st-action-btn). */
.st-icon-btn {
  width: 32px; height: 32px; flex-shrink: 0; padding: 0;
  border: 1px solid var(--st-border); background: var(--st-white); border-radius: var(--st-radius);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--st-muted); cursor: pointer;
  transition: border-color var(--st-duration-fast), background var(--st-duration-fast), color var(--st-duration-fast);
}
.st-icon-btn:hover:not(:disabled) { border-color: var(--st-primary); color: var(--st-primary); background: #F5F8FF; }
.st-icon-btn:disabled { opacity: 0.45; cursor: default; }
.st-icon-btn svg, .st-icon-btn .mud-icon-root { width: 18px; height: 18px; font-size: 18px; }
/* A MudTooltip-wrapped "?" help icon inside .st-with-action: bare icon (no button box),
   only as wide as the icon, vertically centered next to the input. */
.st-with-action > .mud-tooltip-root { flex: 0 0 auto; align-self: center; display: inline-flex; }
.st-help-btn {
  width: auto; min-width: 0; padding: 0; border: none; background: transparent;
  color: var(--st-subtle); cursor: help;
}
.st-help-btn:hover { border: none; background: transparent; color: var(--st-primary); }
.st-help-btn .mud-icon-root, .st-help-btn svg { width: 18px; height: 18px; font-size: 18px; }

/* Currency / unit suffix */
.st-input-suffix { position: relative; }
.st-input-suffix .st-suffix {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  font-size: 12px; font-weight: 600; color: var(--st-subtle); pointer-events: none;
}
.st-input-suffix input { padding-right: 48px; }

/* Validation */
.st-input.invalid, .st-select.invalid, .st-textarea.invalid {
  border-color: #FCA5A5; background: #FFFBFB;
}
.st-error { font-size: 11px; color: var(--st-error-dark); display: flex; align-items: center; gap: 4px; }

/* ===================================================================
   Buttons
   ========================================================================== */
.st-btn {
  font-family: var(--st-font-body);
  border-radius: var(--st-radius); padding: 9px 18px;
  font-size: 13px; font-weight: 600; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border: 1px solid transparent; white-space: nowrap;
  transition: background var(--st-duration-fast), border-color var(--st-duration-fast), color var(--st-duration-fast), box-shadow var(--st-duration-fast);
}
.st-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--st-primary-focus-ring); }
.st-btn-primary {
  background: var(--st-primary); color: var(--st-white); border-color: var(--st-primary);
  box-shadow: 0 1px 2px rgba(74,118,249,0.25);
}
.st-btn-primary:hover { background: var(--st-primary-hover); border-color: var(--st-primary-hover); }
.st-btn-primary:disabled, .st-btn-primary[aria-disabled="true"] {
  background: #C7D2FE; border-color: #C7D2FE; cursor: not-allowed; box-shadow: none;
}
.st-btn-ghost { background: var(--st-white); color: var(--st-muted); border-color: var(--st-border); }
.st-btn-ghost:hover { background: var(--st-bg-alt); color: var(--st-text-strong); border-color: var(--st-border-hover); }
.st-btn-danger { background: var(--st-white); color: var(--st-error); border-color: #FCA5A5; }
.st-btn-danger:hover { background: var(--st-error-light); border-color: var(--st-error); }
.st-btn svg, .st-btn .mud-icon-root { width: 14px; height: 14px; font-size: 14px; }

/* StButton (Components/StButton.razor): the MudButton wrapper adds .st-button plus one kind
   class. Approved look: 34px tall, 8px radius, 13px semibold, the same as the CreateTaskDialog
   footer. The selectors carry the extra :not(.mud-icon-button) so they outrank the global
   `.mud-button-root:not(.mud-icon-button)` !important border/padding reset in app.css, which
   loads after this file. min-height (not height) so a long label can still wrap, and so an
   explicit inline height on a login-style button keeps working. */
.st-button.mud-button-root:not(.mud-icon-button) {
  min-height: 34px !important; padding: 0 14px !important;
  border-radius: var(--st-radius);
  font-family: var(--st-font-body); font-size: 13px; font-weight: 600;
  line-height: 1.2; letter-spacing: 0; text-transform: none;
  box-shadow: none;
}
.st-button.mud-button-root:not(.mud-icon-button):focus-visible { box-shadow: 0 0 0 3px var(--st-primary-focus-ring); }
.st-button.st-button--primary:not(.mud-icon-button),
.st-button.st-button--primary:not(.mud-icon-button):hover { box-shadow: 0 1px 2px rgba(74,118,249,0.25); }
.st-button.st-button--primary.mud-disabled:not(.mud-icon-button) { box-shadow: none; }
.st-button.st-button--ghost.mud-button-root:not(.mud-icon-button) {
  border-color: var(--st-border) !important; background: var(--st-white); color: var(--st-text);
}
.st-button.st-button--ghost.mud-button-root:not(.mud-icon-button):hover {
  border-color: var(--st-border-hover) !important; background: var(--st-bg-alt);
}
.st-button.st-button--ghost.mud-disabled:not(.mud-icon-button) { color: var(--st-subtle); background: var(--st-bg); }
.st-button.st-button--secondary.mud-button-root:not(.mud-icon-button) { border-color: transparent !important; }
.st-button.st-button--danger.mud-button-root:not(.mud-icon-button),
.st-button.st-button--danger.mud-button-root:not(.mud-icon-button):hover { box-shadow: none; }
/* Dense toolbars: 28px tall, 12px label. */
.st-button.st-button--compact.mud-button-root:not(.mud-icon-button) {
  min-height: 28px !important; padding: 0 10px !important; font-size: 12px;
}
.st-button.st-button--lg.mud-button-root:not(.mud-icon-button) {
  min-height: 40px !important; padding: 0 18px !important; font-size: 14px;
}
/* Icon-only StButton (no label): stays square. */
.st-button.st-button--icon.mud-button-root:not(.mud-icon-button) { min-width: 34px; width: 34px; padding: 0 !important; }
.st-button.st-button--icon.st-button--compact.mud-button-root:not(.mud-icon-button) { min-width: 28px; width: 28px; }
.st-button.st-button--icon .mud-button-icon-start,
.st-button.st-button--icon .mud-button-icon-end { margin: 0; }

/* ===================================================================
   Segmented control
   ========================================================================== */
.st-segmented { display: inline-flex; padding: 3px; background: var(--st-bg-alt); border-radius: 9px; width: 100%; }
.st-segmented button {
  flex: 1; border: none; background: transparent; padding: 8px 14px;
  font-family: var(--st-font-body); font-size: 13px; font-weight: 600;
  color: var(--st-muted); cursor: pointer; border-radius: 7px;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  transition: background var(--st-duration-fast), color var(--st-duration-fast), box-shadow var(--st-duration-fast);
}
.st-segmented button.active {
  background: var(--st-white); color: var(--st-primary);
  box-shadow: 0 1px 2px rgba(10,15,24,0.06), 0 0 0 1px rgba(10,15,24,0.04);
}
.st-segmented button:disabled {
  opacity: 0.4; cursor: not-allowed; color: var(--st-muted);
  background: transparent; box-shadow: none;
}
/* Sized to its buttons, for a toolbar next to a search field. */
.st-segmented--inline { width: auto; flex-shrink: 0; align-self: center; }
.st-segmented--inline button { flex: 0 0 auto; padding: 5px 12px; white-space: nowrap; }

/* ===================================================================
   Toggle (switch) row
   ========================================================================== */
.st-toggle-row {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  background: var(--st-white); border: 1px solid var(--st-border); border-radius: 10px;
  cursor: pointer; transition: border-color var(--st-duration-fast), background var(--st-duration-fast);
}
.st-toggle-row:hover { border-color: var(--st-border-hover); }
.st-toggle-row.on { border-color: var(--st-primary); background: #F5F8FF; }
.st-toggle-row .info { flex: 1; min-width: 0; }
.st-toggle-row .info .t { font-size: 13px; font-weight: 600; color: var(--st-text-strong); line-height: 1.25; }
.st-toggle-row .info .d { font-size: 11px; color: var(--st-muted); margin-top: 2px; }
.st-toggle {
  position: relative; width: 36px; height: 20px; flex-shrink: 0;
  background: var(--st-border-hover); border-radius: 99px; transition: background .2s;
}
.st-toggle::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
  background: #fff; border-radius: 50%; box-shadow: 0 1px 2px rgba(10,15,24,0.18); transition: transform .2s var(--st-ease);
}
.st-toggle.on { background: var(--st-primary); }
.st-toggle.on::after { transform: translateX(16px); }

/* ===================================================================
   Radio group (inline cards)
   ========================================================================== */
.st-radio-group { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.st-radio {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  background: var(--st-white); border: 1px solid var(--st-border); border-radius: var(--st-radius);
  cursor: pointer; font-size: 13px; font-weight: 600; color: #475569;
  transition: border-color var(--st-duration-fast), background var(--st-duration-fast), color var(--st-duration-fast);
}
.st-radio:hover { border-color: var(--st-border-hover); }
.st-radio.on { border-color: var(--st-primary); background: #F5F8FF; color: var(--st-text-strong); }
.st-radio .dot {
  width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--st-border-hover);
  background: #fff; flex-shrink: 0; position: relative; transition: border-color var(--st-duration-fast);
}
.st-radio.on .dot { border-color: var(--st-primary); }
.st-radio.on .dot::after { content: ""; position: absolute; inset: 2px; background: var(--st-primary); border-radius: 50%; }

/* ===================================================================
   Attachments dropzone + chips
   ========================================================================== */
.st-attach {
  border: 1.5px dashed var(--st-border-hover); border-radius: 10px; padding: 14px 16px;
  display: flex; align-items: center; gap: 12px; background: var(--st-white);
  transition: border-color var(--st-duration-fast), background var(--st-duration-fast);
}
.st-attach:hover { border-color: var(--st-primary); background: #F5F8FF; }
.st-attach .icn {
  width: 32px; height: 32px; border-radius: var(--st-radius); background: var(--st-bg-alt); color: var(--st-primary);
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.st-attach .body { flex: 1; min-width: 0; }
.st-attach .body .ttl { font-size: 13px; font-weight: 600; color: var(--st-text-strong); }
.st-attach .body .meta { font-size: 11px; color: var(--st-muted); margin-top: 1px; }
.st-attach-list { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.st-attach-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 8px 5px 10px;
  background: var(--st-bg-alt); border-radius: var(--st-radius-sm);
  font-size: 12px; color: var(--st-text); font-weight: 500;
}
.st-attach-chip .x {
  width: 16px; height: 16px; border-radius: 4px; display: inline-flex; align-items: center; justify-content: center;
  color: var(--st-subtle); cursor: pointer;
}
.st-attach-chip .x:hover { background: #fff; color: var(--st-error); }

/* Uploaded-attachment tiles. Photos need to be readable at a glance and open
   full-screen on click, so images render as a real thumbnail rather than the
   filename chip above; non-image files keep an icon in the same tile shape. */
.st-attach-tiles { display: flex; flex-wrap: wrap; gap: var(--st-space-3); margin-top: var(--st-space-2); }
.st-attach-tile { position: relative; width: 104px; }
.st-attach-tile .thumb {
  width: 104px; height: 104px; border-radius: var(--st-radius);
  border: 1px solid var(--st-border); background: var(--st-bg-alt);
  overflow: hidden; display: flex; align-items: center; justify-content: center;
  color: var(--st-subtle);
}
.st-attach-tile img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  cursor: zoom-in; transition: transform var(--st-duration-fast) var(--st-ease);
}
.st-attach-tile img:hover { transform: scale(1.04); }
.st-attach-tile .name {
  margin-top: var(--st-space-1); font-size: 11px; line-height: 1.35; color: var(--st-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.st-attach-tile .x {
  position: absolute; top: -6px; right: -6px; width: 20px; height: 20px;
  border-radius: var(--st-radius-full); background: var(--st-white);
  border: 1px solid var(--st-border); box-shadow: var(--st-shadow-sm);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--st-muted); cursor: pointer;
}
.st-attach-tile .x:hover { color: var(--st-error); border-color: var(--st-error); }

/* ===================================================================
   Inline create popover (anchored under a field)
   ========================================================================== */
.st-field-anchor { position: relative; }
.st-popover {
  position: absolute; left: 0; right: 0; top: calc(100% + 6px);
  background: #fff; border: 1px solid var(--st-border); border-radius: var(--st-radius-md);
  box-shadow: var(--st-shadow-popover); padding: 16px; z-index: 10;
}
.st-popover h4 {
  margin: 0 0 12px; font-family: var(--st-font-heading);
  font-size: 14px; font-weight: 800; color: var(--st-text-strong); letter-spacing: -0.01em;
}

/* ===================================================================
   MudBlazor adapter — wrap a region in .st-form to reskin Mud outlined
   inputs / selects / numeric / date pickers to the design tokens. Keeps the
   Mud component behaviour; only restyles border, radius, focus, colors.
   ========================================================================== */
/* Neutralize MudBlazor's per-field margins (e.g. .mud-input-control-margin-dense = 4px 0) so
   vertical spacing in a .st-form layout is driven ONLY by the container's gap — guaranteeing
   every field is evenly spaced regardless of control type (TextField vs Select vs Autocomplete). */
.st-form .mud-input-control { margin: 0 !important; }

.st-form .mud-input.mud-input-outlined .mud-input-outlined-border {
  border-color: var(--st-border);
  border-radius: var(--st-radius);
  transition: border-color var(--st-duration-fast), box-shadow var(--st-duration-fast);
}
.st-form .mud-input.mud-input-outlined:hover:not(.mud-disabled):not(.mud-error) .mud-input-outlined-border {
  border-color: var(--st-border-hover);
}
.st-form .mud-input.mud-input-outlined.mud-focused:not(.mud-error) .mud-input-outlined-border {
  border-color: var(--st-primary) !important;
  border-width: 1px;
  box-shadow: 0 0 0 3px var(--st-primary-focus-ring);
}
.st-form .mud-input-control-input-container { background: var(--st-white); border-radius: var(--st-radius); }
.st-form .mud-input-root { font-family: var(--st-font-body); font-size: 14px; color: var(--st-text-strong); }
.st-form .mud-input-label { font-family: var(--st-font-body); color: var(--st-muted); }
.st-form .mud-input.mud-input-outlined.mud-focused:not(.mud-error) .mud-input-label { color: var(--st-primary); }
.st-form .mud-input.mud-input-outlined .mud-input-slot { color: var(--st-text-strong); }
.st-form .mud-input.mud-disabled .mud-input-outlined-border { border-color: var(--st-border-light); }

/* Mud buttons inside .st-form → align to .st-btn look */
.st-form .mud-button-root.mud-button-filled-primary {
  background-color: var(--st-primary); border-radius: var(--st-radius);
  box-shadow: 0 1px 2px rgba(74,118,249,0.25); text-transform: none; font-weight: 600;
}
.st-form .mud-button-root.mud-button-filled-primary:hover { background-color: var(--st-primary-hover); }
.st-form .mud-button-root.mud-button-text { text-transform: none; font-weight: 600; color: #475569; }

/* Mud switches inside .st-form → product blue */
.st-form .mud-switch .mud-switch-track { border-radius: 99px; }
.st-form .mud-switch.mud-checked .mud-switch-track { background-color: var(--st-primary); }

/* Mud autocomplete inside .st-form → make it read like a native .st-select:
   white fill, hairline border, 8px radius, 14px text, subtle placeholder + caret. */
.st-form .mud-autocomplete .mud-input.mud-input-outlined { background: var(--st-white); }
.st-form .mud-autocomplete .mud-input-outlined-border { border-color: var(--st-border); border-radius: var(--st-radius); }
.st-form .mud-autocomplete .mud-input-control-input-container { min-height: 40px; }
.st-form .mud-autocomplete .mud-input-slot,
.st-form .mud-autocomplete input { font-size: 14px; color: var(--st-text-strong); }
.st-form .mud-autocomplete input::placeholder { color: var(--st-subtle); opacity: 1; }
.st-form .mud-autocomplete .mud-input-adornment-end .mud-icon-root { color: var(--st-subtle); font-size: 20px; }

/* ===================================================================
   Suffix alias + date inputs (used by .st-input-suffix .suffix)
   ========================================================================== */
.st-input-suffix .suffix {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  font-size: 12px; font-weight: 600; color: var(--st-subtle); pointer-events: none;
}
.st-date-wrap { position: relative; }
.st-date-range { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }

/* ===================================================================
   .st-date-picker: a MudDatePicker (Variant.Outlined, Margin.Dense) standing in for a native
   <input type="date">, which the browser draws in the OS region's format instead of the
   tenant's. Reads like the plain .st-input it replaces: hairline token border, white fill, no
   Mud field margins, full width of its column. Size modifiers match the native fields:
     (none)          .st-input           14px, 10px 12px
     --sm            compact form field  13px, 7px 10px, 6px radius
     --xs            filter-bar chip     12px, 6px 8px
   --inline stops it stretching in a flex row (filter bars), at a width that fits a date.
   Global on purpose: MudBlazor renders the input tree, so scoped CSS can't reach it.
   ========================================================================== */
.st-date-picker { width: 100%; }
.st-date-picker .mud-input-control { margin: 0 !important; }
.st-date-picker .mud-input.mud-input-outlined .mud-input-outlined-border {
  border-color: var(--st-border);
  border-radius: var(--st-radius);
}
.st-date-picker .mud-input.mud-input-outlined:hover:not(.mud-disabled) .mud-input-outlined-border {
  border-color: var(--st-border-hover);
}
.st-date-picker .mud-input.mud-input-outlined.mud-focused .mud-input-outlined-border {
  border-color: var(--st-primary) !important;
  border-width: 1px;
  box-shadow: 0 0 0 3px var(--st-primary-focus-ring);
}
.st-date-picker .mud-input-control-input-container { background: var(--st-white); border-radius: var(--st-radius); }
.st-date-picker .mud-input.mud-disabled .mud-input-control-input-container,
.st-date-picker .mud-input-control.mud-disabled .mud-input-control-input-container { background: var(--st-bg); }
.st-date-picker .mud-input.mud-disabled .mud-input-outlined-border { border-color: var(--st-border-light); }
.st-date-picker .mud-input { font-family: var(--st-font-body); font-size: 14px; color: var(--st-text-strong); }
.st-date-picker .mud-input > input.mud-input-root-outlined.mud-input-root-margin-dense {
  padding: 10px 0 10px 12px; font-size: inherit; color: inherit; height: auto; line-height: normal;
  /* Shield the inner input from a page's generic `input { border; background }` rules. */
  border: 0; background: transparent; border-radius: 0; box-shadow: none;
}
.st-date-picker .mud-input.mud-input-outlined.mud-input-adorned-end { padding-right: 8px; }
.st-date-picker .mud-input-adornment-end { margin-left: 4px; }
.st-date-picker .mud-input-adornment-end .mud-icon-button { padding: 4px; }
.st-date-picker .mud-input-adornment-end .mud-icon-root { font-size: 18px; width: 18px; height: 18px; color: var(--st-subtle); }

.st-date-picker--sm .mud-input { font-size: 13px; color: var(--st-text); }
.st-date-picker--sm .mud-input > input.mud-input-root-outlined.mud-input-root-margin-dense { padding: 7px 0 7px 10px; }
.st-date-picker--sm .mud-input.mud-input-outlined .mud-input-outlined-border,
.st-date-picker--sm .mud-input-control-input-container { border-radius: var(--st-radius-sm); }
.st-date-picker--sm .mud-input-adornment-end .mud-icon-button { padding: 2px; }
.st-date-picker--sm .mud-input-adornment-end .mud-icon-root { font-size: 16px; width: 16px; height: 16px; }

.st-date-picker--xs .mud-input { font-size: 12px; color: var(--st-text); }
.st-date-picker--xs .mud-input > input.mud-input-root-outlined.mud-input-root-margin-dense { padding: 6px 0 6px 8px; }
.st-date-picker--xs .mud-input.mud-input-outlined.mud-input-adorned-end { padding-right: 4px; }
.st-date-picker--xs .mud-input-adornment-end .mud-icon-button { padding: 2px; }
.st-date-picker--xs .mud-input-adornment-end .mud-icon-root { font-size: 15px; width: 15px; height: 15px; }

.st-date-picker--inline { flex: 0 0 auto; width: 150px; }
.st-date-picker--inline.st-date-picker--xs { width: 128px; }

/* ===================================================================
   Help icon + tooltip (e.g. next to a field label)
   ========================================================================== */
.st-help {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border-radius: 50%;
  border: 1px solid var(--st-border-hover); color: var(--st-subtle);
  font-size: 10px; font-weight: 700; cursor: help; margin-left: 2px; outline: none;
  transition: color var(--st-duration-fast), border-color var(--st-duration-fast);
}
.st-help:hover, .st-help:focus-visible { color: var(--st-primary); border-color: var(--st-primary); }
.st-help-tip {
  position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%) translateY(4px);
  background: var(--st-text-strong); color: #fff;
  font-size: 12px; font-weight: 500; line-height: 1.45; text-transform: none; letter-spacing: 0;
  padding: 8px 10px; border-radius: var(--st-radius); width: max-content; max-width: 220px;
  box-shadow: var(--st-shadow-popover); opacity: 0; pointer-events: none;
  transition: opacity var(--st-duration-fast); z-index: 5; white-space: normal;
}
.st-help:hover .st-help-tip, .st-help:focus-visible .st-help-tip { opacity: 1; }

/* ===================================================================
   Workers list (team members + akkord split)
   ========================================================================== */
.st-workers { border: 1px solid var(--st-border); background: #fff; border-radius: 10px; overflow: hidden; }
.st-workers-head {
  display: flex; align-items: center; justify-content: space-between; padding: 9px 14px;
  background: var(--st-bg-alt); font-size: 11px; font-weight: 700; color: var(--st-muted);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.st-workers-head .cnt { font-size: 11px; font-weight: 600; color: var(--st-subtle); text-transform: none; letter-spacing: 0; }
.st-worker { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-top: 1px solid var(--st-border-light); }
.st-worker:first-of-type { border-top: none; }
.st-worker > .nm {
  flex: 1; min-width: 0; font-size: 13px; font-weight: 500; color: var(--st-text-strong);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.st-worker-pool { max-height: 230px; overflow-y: auto; }
.st-worker.pick { cursor: pointer; transition: background var(--st-duration-fast); }
.st-worker.pick:hover { background: var(--st-bg-alt); }
.st-worker-act {
  width: 24px; height: 24px; border-radius: 6px; border: 1px solid var(--st-border); background: #fff;
  color: var(--st-muted); display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; flex-shrink: 0; padding: 0;
  transition: background var(--st-duration-fast), border-color var(--st-duration-fast), color var(--st-duration-fast);
}
.st-worker.pick:hover .st-worker-act.add,
.st-worker-act.add:hover { color: var(--st-primary); border-color: var(--st-primary); background: var(--st-primary-light); }
.st-worker-act.rm:hover { color: var(--st-error-dark); border-color: var(--st-error-dark); background: var(--st-error-light); }
.st-workers-selected .st-worker { background: var(--st-primary-light); }
.st-workers-selected .st-worker + .st-worker { border-top-color: var(--st-border); }
.st-worker-split { display: inline-flex; align-items: center; gap: 8px; flex-shrink: 0; }
.st-worker-split .lockbtn {
  width: 26px; height: 26px; border-radius: 6px; border: none; background: transparent; color: var(--st-subtle);
  cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  transition: background var(--st-duration-fast), color var(--st-duration-fast);
}
.st-worker-split .lockbtn:hover { background: var(--st-bg-alt); color: var(--st-text); }
.st-worker-split .lockbtn.on { color: var(--st-primary); background: var(--st-primary-light); }
.st-worker-split .pct input {
  width: 58px; border: 1px solid var(--st-border); background: #fff; border-radius: 6px;
  padding: 5px 22px 5px 8px; font: 600 13px var(--st-font-body); color: var(--st-text-strong);
  outline: none; text-align: right; -moz-appearance: textfield;
}
.st-worker-split .pct { position: relative; }
.st-worker-split .pct input::-webkit-outer-spin-button,
.st-worker-split .pct input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.st-worker-split .pct input:focus { border-color: var(--st-primary); box-shadow: 0 0 0 3px var(--st-primary-focus-ring); }
.st-worker-split .pct .u { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); font-size: 11px; font-weight: 600; color: var(--st-subtle); pointer-events: none; }
.st-worker-split .dkk { font-size: 12px; color: var(--st-muted); font-weight: 500; min-width: 78px; text-align: right; font-variant-numeric: tabular-nums; }
.st-workers-total { display: flex; align-items: center; justify-content: space-between; padding: 9px 14px; background: var(--st-surface-alt); border-top: 1px solid var(--st-border-light); }
.st-workers-total .lbl { font-size: 11px; font-weight: 600; color: var(--st-muted); text-transform: uppercase; letter-spacing: 0.06em; }
.st-workers-total .v { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }
.st-workers-total.ok .v { color: var(--st-success-dark); }
.st-workers-total.warn .v { color: var(--st-error-dark); }

/* Footer urgent toggle (mock places "Mark as urgent" in the footer) */
.st-urgent {
  display: inline-flex; align-items: center; gap: 10px; font-size: 13px; font-weight: 600;
  color: var(--st-text); cursor: pointer; user-select: none; padding: 6px 10px 6px 4px; border-radius: var(--st-radius);
}
.st-urgent:hover { background: var(--st-bg); }
.st-urgent.on { color: #B91C1C; }
.st-urgent .ic { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 6px; background: var(--st-bg-alt); color: var(--st-subtle); }
.st-urgent.on .ic { background: #FEE2E2; color: #B91C1C; }

/* ===================================================================
   Task creation/edit popup (CreateTaskDialog) layout & chrome.
   Kept here (static CSS) rather than an in-component <style> so tweaks show on
   a hard refresh without a WASM rebuild.
   ========================================================================== */
.st-dialog .mud-dialog { border-radius: var(--st-radius-lg); max-width: 1040px; }
.st-dialog-title { display: flex; align-items: center; gap: 12px; }
.st-dialog-title .icon-tile {
  width: 36px; height: 36px; border-radius: 10px;
  background: var(--st-primary-light); color: var(--st-primary);
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.st-dialog-title .icon-tile .mud-icon-root { font-size: 20px; }
.st-dialog-title .ttl {
  font-family: var(--st-font-heading);
  font-size: 18px; font-weight: 800; color: var(--st-text-strong); letter-spacing: -0.01em;
}
/* Creation-draft autosave indicator (task + service agreement create dialogs, title right side) */
.st-draft-state {
  display: inline-flex; align-items: center; gap: 5px;
  margin-left: auto; padding: 3px 10px;
  font-size: 12px; font-weight: 600;
  border-radius: 999px;
}
.st-draft-state.saved  { color: var(--st-success-dark); background: rgba(16,185,129,0.10); }
.st-draft-state.saving { color: var(--st-muted); background: var(--st-bg-alt); }
.st-dialog .mud-dialog-title { border-bottom: 1px solid var(--st-border); padding-bottom: 16px; }
.st-dialog .mud-dialog-actions { border-top: 1px solid var(--st-border); padding: 14px 24px; gap: 10px; }
/* Full-bleed body so the two columns reach the dialog edges (right column is a tinted panel). */
.st-dialog .mud-dialog-content { padding: 0; }
.st-dialog-body { position: relative; padding: 0; }
.st-dialog-body > .st-error { margin: 16px 24px 0; }
/* minmax(0, 1fr) (not bare 1fr = minmax(auto, 1fr)) so a long selected value — e.g. a
   location "Name — Address" — can't inflate its column's min-content and steal width from
   the other. min-width:0 lets the column clip its content instead of spilling over. */
.st-dialog-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0; }
.st-dialog-grid .st-dialog-col { display: flex; flex-direction: column; gap: 24px; padding: 22px 24px; min-width: 0; }
.st-dialog-grid .st-dialog-col + .st-dialog-col { background: #FAFBFD; border-left: 1px solid var(--st-border-light); }
.st-dropzone-overlay {
  position: absolute; inset: 0; z-index: 100; pointer-events: none;
  background: rgba(74,118,249,0.06); border: 2px dashed var(--st-primary); border-radius: 12px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  color: var(--st-primary); font-weight: 600;
}
@media (max-width: 860px) {
  .st-dialog-grid { grid-template-columns: 1fr; }
  .st-dialog-grid .st-dialog-col + .st-dialog-col { border-left: none; border-top: 1px solid var(--st-border-light); }
}

/* ===================================================================
   Utility vocabulary — inline-style migration. See CONVENTION.
   ========================================================================== */
/* CONVENTION — prefer, in order:
   1. MudBlazor utilities for layout/flex/spacing on the 4px scale
      (d-flex, flex-column, flex-1, align-center, justify-*, gap-1..6, pa-/px-/py-/mt-/mb-/ml-* = n*4px);
   2. these token-backed st-* utilities for what MudBlazor lacks — the --st-* colors,
      the type scale, and the design's off-4px-grid spacing (2/6/10/14px, padding:10px 16px…);
   3. a scoped Pages/<Page>.razor.css class for page-specific structure (cards, tiles, grids).
   Only data-driven values stay inline (Style="@(...)"). Every hex/radius design-system.css
   already names resolves to its token. */
.st-text-muted { color: var(--st-muted); }
.st-text-subtle { color: var(--st-subtle); }
.st-text-body { color: var(--st-text); }
.st-text-primary { color: var(--st-primary); }
.st-text-slate { color: #475569; }
.st-text-red { color: var(--st-error); }
.st-text-amber { color: #92400E; }
.st-text-crimson { color: #991B1B; }
.st-text-blue { color: #1D4ED8; }
.st-bg-muted { background: var(--st-bg); }
.st-bg-white { background: var(--st-white); }
.st-min-w-0 { min-width: 0; }
.st-border-0 { border: none; }
.st-border-collapse { border-collapse: collapse; }
.st-nowrap { white-space: nowrap; }
.st-pre-wrap { white-space: pre-wrap; }
.st-mono { font-family: monospace; }
.st-ov-visible { overflow: visible; }
.st-col-full { grid-column: 1 / -1; }
.st-fs-11 { font-size: 11px; }
.st-fs-12 { font-size: 12px; }
.st-fs-13 { font-size: 13px; }
.st-fs-14 { font-size: 14px; }
.st-fs-15 { font-size: 15px; }
.st-fs-18 { font-size: 18px; }
.st-fs-24 { font-size: 24px; }
.st-fs-40 { font-size: 40px; }
.st-fs-48 { font-size: 48px; }
/* Icon sizes. A MudIcon renders a 1em box, and MudBlazor's Size enum only names
   20/24/36px, so these cover the design's in-between icon sizes without inline styles. */
.st-icon-12 { font-size: 12px; }
.st-icon-14 { font-size: 14px; }
.st-icon-15 { font-size: 15px; }
.st-icon-16 { font-size: 16px; }
.st-icon-18 { font-size: 18px; }
.st-icon-22 { font-size: 22px; }
.st-icon-28 { font-size: 28px; }
.st-icon-32 { font-size: 32px; }
.st-icon-34 { font-size: 34px; }
.st-fw-400 { font-weight: 400; }
.st-fw-500 { font-weight: 500; }
.st-fw-600 { font-weight: 600; }
.st-fw-700 { font-weight: 700; }
.st-ta-center { text-align: center; }
.st-ta-left { text-align: left; }
.st-ta-right { text-align: right; }
.st-ls { letter-spacing: 0.05em; }
.st-cursor-pointer { cursor: pointer; }
.st-py-2 { padding-top: 2px;padding-bottom: 2px; }
.st-py-6 { padding-top: 6px;padding-bottom: 6px; }
.st-py-10 { padding-top: 10px;padding-bottom: 10px; }
.st-py-1 { padding-top: 1px;padding-bottom: 1px; }
.st-px-6 { padding-left: 6px;padding-right: 6px; }
.st-px-10 { padding-left: 10px;padding-right: 10px; }
.st-gap-6 { gap: 6px; }
.st-gap-2 { gap: 2px; }
.st-gap-10 { gap: 10px; }
.st-gap-14 { gap: 14px; }
/* Visually hidden, still read by screen readers (e.g. an icon-only column header). */
.st-sr-only { position: absolute;width: 1px;height: 1px;padding: 0;margin: -1px;overflow: hidden;clip: rect(0, 0, 0, 0);white-space: nowrap;border: 0; }
/* Two equal columns (form rows in dialogs; global because dialog bodies are portaled). */
.st-grid-2 { display: grid;grid-template-columns: 1fr 1fr;gap: 12px; }
/* Coloured row-menu items (MudMenuItem popovers are portaled, so these are global). */
.mud-menu-item.st-menu-danger { color: var(--st-error); }
.mud-menu-item.st-menu-success { color: var(--st-success); }
.st-mb-2 { margin-bottom: 2px; }
.st-ml-6 { margin-left: 6px; }
.st-mt-2 { margin-top: 2px; }
.st-mt-6 { margin-top: 6px; }
.st-mb-6 { margin-bottom: 6px; }
.st-mt-10 { margin-top: 10px; }
.st-pt-8 { padding-top: 8px; }
.st-mb-14 { margin-bottom: 14px; }
.st-mb-10 { margin-bottom: 10px; }
.st-panel { border: 1px solid var(--st-border);border-radius: var(--st-radius-md); }
/* Small inline pill used next to a name (portal role, "managed by", …). */
.st-badge { display: inline-block;font-size: 11px;font-weight: 600;padding: 2px 8px;border-radius: 4px; }
.st-badge-muted { background: var(--st-bg-alt);color: var(--st-muted); }
.st-badge-primary { background: var(--st-primary-light);color: var(--st-primary); }
.st-badge-amber { background: #FEF3C7;color: #B45309; }
.st-badge-success { background: #DCFCE7;color: #16A34A; }
.st-badge-error { background: #FEE2E2;color: #DC2626; }
/* Customer-refusal marker (kravspec 1.23): CustomerRefusalChip, shown beside the .st-status pill in
   task lists and dialogs (global, since dialogs are portaled). Solid red while a head has to decide
   or when the refusal closed the task; a red outline when the task was only moved. The row class
   tints a list row and draws a red left edge (on the first cell for table rows). */
.st-status.st-refusal { background: var(--st-error);color: var(--st-white);font-weight: 600; }
.st-status.st-refusal-moved { background: var(--st-white);color: var(--st-error-dark);border: 1px solid #FCA5A5;padding: 2px 9px; }
.st-refusal-row { background: var(--st-error-light);box-shadow: inset 3px 0 0 var(--st-error); }
tr.st-refusal-row { box-shadow: none; }
tr.st-refusal-row > td:first-child { box-shadow: inset 3px 0 0 var(--st-error); }
/* A MudSelect option with a trailing action button (e.g. duplicate a checklist from the picker's
   list). Global because the select's list is portaled out of the component's scoped CSS. */
.st-select-option-row { display: flex; align-items: center; gap: 8px; width: 100%; }
.st-select-option-row__text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-select-option-row__action { margin: -6px 0; color: var(--st-subtle); }
.st-select-option-row__action:hover { color: var(--st-primary); }
/* The closed select echoes the chosen row; the action belongs to the open list only. */
.mud-select-input .st-select-option-row__action { display: none; }
/* Toggleable pill list, used to attach a knowledge item to service types. Lives here rather
   than in a .razor.css because the knowledge add-item dialog is a hand-rolled overlay whose body
   is reused from more than one component. */
.st-chip-select { display: flex;flex-wrap: wrap;gap: 6px; }
.st-chip-toggle {
  font-family: var(--st-font-body); font-size: 12px; font-weight: 600;
  padding: 5px 10px; border-radius: var(--st-radius-full);
  border: 1px solid var(--st-border); background: var(--st-white);
  color: var(--st-muted); cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
  transition: background var(--st-duration-fast), border-color var(--st-duration-fast), color var(--st-duration-fast);
}
.st-chip-toggle:hover { border-color: var(--st-border-hover);color: var(--st-text); }
.st-chip-toggle.is-on { background: var(--st-primary-light);border-color: var(--st-primary);color: var(--st-primary); }
.st-chip-toggle .mud-icon-root { width: 13px;height: 13px;font-size: 13px; }

/* Quality inspection outcome classes. One colour per class, shared by the chip on the reports
   overview and the count strip in the period export dialog. The dialog body is portaled out of
   scoped CSS, so these have to live here rather than in a .razor.css. */
.st-qr-count { font-size: 22px;font-weight: 700;line-height: 1.1; }
.st-qr-approved { color: #16A34A; }
.st-qr-remarks { color: #B45309; }
.st-qr-rejected { color: #DC2626; }
.st-qr-notset { color: var(--st-subtle); }
.st-qr-tile { border: 1px solid var(--st-border);border-radius: var(--st-radius);padding: 10px 12px;flex: 1;min-width: 92px; }
.st-qr-search-menu { border: 1px solid var(--st-border);border-radius: var(--st-radius);max-height: 200px;overflow-y: auto; }
.st-qr-search-item { padding: 6px 10px;cursor: pointer;font-size: 13px; }
.st-qr-search-item:hover { background: var(--st-bg); }
/* Verdict picker on the fill dialog: three large options, one chosen before a report can be
   filed. The dialog is portaled out of scoped CSS, so these live here. */
.st-qr-verdict { border-top: 1px solid var(--st-border);margin-top: 20px;padding-top: 16px; }
.st-qr-verdict-title { font-size: 14px;font-weight: 700;color: var(--st-text); }
.st-qr-verdict-hint { font-size: 12px;color: var(--st-muted);margin-top: 2px;margin-bottom: 10px; }
.st-qr-verdict-options { display: flex;gap: 10px;flex-wrap: wrap; }
.st-qr-verdict-option { flex: 1;min-width: 160px;display: flex;align-items: center;justify-content: center;gap: 8px;background: var(--st-white);border: 2px solid var(--st-border);border-radius: var(--st-radius);padding: 12px 14px;cursor: pointer;font-size: 13px;font-weight: 600;color: var(--st-muted);font-family: inherit; }
.st-qr-verdict-option:hover { border-color: var(--st-subtle); }
.st-qr-verdict-approved { background: #DCFCE7;border-color: #22C55E;color: #15803D; }
.st-qr-verdict-remarks  { background: #FEF3C7;border-color: #F59E0B;color: #B45309; }
.st-qr-verdict-rejected { background: #FEE2E2;border-color: #EF4444;color: #DC2626; }
.st-qr-verdict-required { font-size: 12px;color: var(--st-error);margin-top: 8px; }
.st-truncate { overflow: hidden;text-overflow: ellipsis;white-space: nowrap; }
.st-callout-warn { background: var(--st-warning-light);border: 1px solid #FED7AA;border-radius: var(--st-radius); }
.st-callout-error { background: var(--st-error-light);border: 1px solid #FECACA;border-radius: var(--st-radius); }
.st-callout-info { background: #EFF6FF;border: 1px solid #BFDBFE;border-radius: var(--st-radius); }
/* Bulleted summary list. Global because dialog bodies are portaled out of scoped CSS. */
.st-bullets { list-style: disc;padding-left: 20px;margin: 0; }
.st-bullets > li { margin: 0 0 2px; }
/* Settings dialog boxes (portal-rendered; scoped CSS cannot reach them). */
.st-set-flexbasis-06 { flex: 1; }
.st-set-x-28 { padding-top: 4px; }
.st-set-x-62 { padding-top: 8px; }
.st-set-mnw-63 { min-width: 140px; }
.st-set-mnw-64 { min-width: 150px; }
.st-set-mnw-65 { min-width: 120px; }
.st-set-x-66 { display: block; }
.st-set-x-67 { cursor: pointer; }
.st-set-x-68 { width: 1px;height: 1px;opacity: 0;position: absolute;pointer-events: none; }
.st-set-mw-69 { max-width: 120px; }

/* ─── Customer dashboards (tenant admin) — add/edit-user dialog. MudDialog content is
   portal-rendered, so scoped .razor.css can never reach it; these live global. ─── */
.st-cd-grid-2 { display: grid;grid-template-columns: 1fr 1fr;gap: 12px; }
/* Caption directly under a MudSwitch reads as that switch's helper text. */
.st-cd-hint { margin-top: -8px; }
.st-cd-locbox { border: 1px solid var(--st-border);border-radius: var(--st-radius);max-height: 280px;overflow-y: auto; }
.st-cd-locgroup + .st-cd-locgroup { border-top: 1px solid var(--st-border-light); }
.st-cd-locgroup-head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 6px 12px; background: var(--st-surface-alt); position: sticky; top: 0;
}
.st-cd-locgroup-name { font-size: 12px; font-weight: 600; color: var(--st-muted); }
.st-cd-locrow { display: flex; align-items: center; gap: 8px; padding: 6px 12px; cursor: pointer; }
.st-cd-locrow:hover { background: var(--st-bg); }
.st-cd-locrow-name { font-size: 13px; color: var(--st-text); }
/* Location sub-rows shown under a customer row in the picker while searching.
   36px left inset = the row's 12px padding + 16px checkbox + 8px gap, so the
   location names line up with the customer name above them. */
.st-cd-locsub { display: flex; align-items: center; gap: 6px; padding: 2px 12px 2px 36px; font-size: 12px; color: var(--st-muted); }
.st-cd-locsub .st-cd-locsub-icon { font-size: 14px; color: var(--st-subtle); }
.st-cd-locrow-count { margin-left: auto; font-size: 12px; color: var(--st-subtle); }
/* Customer number after a customer name ("#16420"): many customers share one name. */
.st-cd-custno { font-size: 12px; font-weight: 400; color: var(--st-subtle); }
.st-cd-linkbtn {
  background: none; border: none; padding: 0; font: inherit; font-size: 12px;
  font-weight: 600; color: var(--st-primary); cursor: pointer;
}
.st-cd-invitebox {
  display: flex; align-items: center; gap: 8px; padding: 8px 12px;
  background: var(--st-bg); border: 1px solid var(--st-border); border-radius: var(--st-radius);
}
/* Customer picker (search + checkbox list + selected chips), shared by the create-dashboard
   and add-customer dialogs; the chips are reused by the detail page's in-card customer row. */
.st-cd-pickbox-empty { padding: 8px 12px; font-size: 13px; color: var(--st-muted); }
.st-cd-chiprow { display: flex; flex-wrap: wrap; gap: 8px; }
.st-cd-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 4px 4px 12px;
  background: var(--st-bg); border: 1px solid var(--st-border);
  border-radius: var(--st-radius-full); font-size: 13px; color: var(--st-text);
}
.st-cd-chip .st-cd-chip-icon { font-size: 16px; color: var(--st-subtle); }
.st-cd-chip .st-cd-chip-remove { color: var(--st-subtle); padding: 2px; }

/* ─── Work-request conversation thread (shared by the staff triage dialog, the customer
   portal, and the public /r/{id} page; dialogs are portal-rendered, hence global). ─── */
.st-thread { display: flex; flex-direction: column; gap: 10px; max-height: 340px; overflow-y: auto; padding: 2px; }
.st-thread-msg { max-width: 82%; padding: 10px 14px; border-radius: var(--st-radius-md); font-size: 14px; line-height: 1.45; color: var(--st-text); white-space: pre-wrap; word-break: break-word; }
.st-thread-msg-own { align-self: flex-end; background: var(--st-primary-light); border: 1px solid var(--st-primary-border); }
.st-thread-msg-other { align-self: flex-start; background: var(--st-bg-alt); border: 1px solid var(--st-border); }
.st-thread-msg-system { align-self: center; background: transparent; border: none; color: var(--st-muted); font-size: 12.5px; padding: 2px 8px; }
.st-thread-meta { font-size: 11.5px; color: var(--st-subtle); margin-top: 4px; }
.st-thread-author { font-size: 12px; font-weight: 600; color: var(--st-muted); margin-bottom: 2px; }
.st-thread-photo { max-width: 140px; max-height: 140px; border-radius: var(--st-radius); border: 1px solid var(--st-border); object-fit: cover; cursor: pointer; }
.st-thread-unread-dot { display: inline-block; width: 8px; height: 8px; border-radius: var(--st-radius-full); background: var(--st-primary); flex-shrink: 0; }

/* ─── Route paint (Planning draw modal) ───────────────────────────────────────
   The road-group legend swatches and the two tool states. These carry the feature's
   own colours (--st-paint-*), which is why they live here rather than in
   Planning.razor.css: the values are declared once at the top of this file and the
   map layers read the identical constants from wwwroot/js/route-paint.js. */
.st-paint-swatch { height: 4px; min-width: 24px; border-radius: 2px; flex-shrink: 0; }
.st-paint-swatch-one-lane { background: var(--st-paint-one-lane); }
.st-paint-swatch-multi-lane { background: var(--st-paint-multi-lane); }
.st-paint-swatch-walkway { background: var(--st-paint-walkway); }

/* Armed tool. Brush takes the product tint, the eraser its own red one, so which tool
   is live is readable without reading the icon. */
.st-paint-tool-active {
  background: var(--st-primary-light);
  border-color: var(--st-primary);
  color: var(--st-primary);
}
.st-paint-tool-active-erase {
  background: var(--st-error-light);
  border-color: var(--st-paint-erase);
  color: var(--st-paint-erase);
}

/* Live-sync webhook panel (Settings > Integrations). Token-backed; the URL wraps
   rather than overflowing because it is long and meant to be read and copied. */
.st-webhook-panel {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 12px 14px;
    border: 1px solid var(--st-border);
    border-radius: var(--st-radius-md, 8px);
    background: var(--st-bg);
}

.st-webhook-url {
    flex: 1;
    min-width: 0;
    font-size: 12px;
    color: var(--st-text);
    background: var(--st-white);
    border: 1px solid var(--st-border);
    border-radius: 6px;
    padding: 6px 8px;
    overflow-wrap: anywhere;
}

/* Customer-number adoption preview (Settings > Integrations). */
.st-adopt-list { display: flex; flex-direction: column; gap: 2px; max-height: 260px; overflow-y: auto; }
.st-adopt-row { display: flex; align-items: center; gap: 10px; font-size: 12px; padding: 3px 0; border-bottom: 1px solid var(--st-border); }
.st-adopt-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--st-text); }
.st-adopt-nums { font-variant-numeric: tabular-nums; color: var(--st-text); white-space: nowrap; }
.st-adopt-reason { color: var(--st-subtle); white-space: nowrap; }

/* ==========================================================================
   GPS drawing coverage badge: "how much of the drawn area did the trail cover".
   Global (not scoped) on purpose: the badge renders inside MudDialog bodies, which
   a scoped .razor.css cannot reach. Bands mirror the GPS overview panel exactly:
   >= 90 % green, >= 60 % amber, below that red.
   ========================================================================== */
.st-coverage {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 999px;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.st-coverage[data-band="high"] { background: #ECFDF5; color: #047857; }
.st-coverage[data-band="mid"] { background: #FFFBEB; color: #B45309; }
.st-coverage[data-band="low"] { background: #FEF2F2; color: #B91C1C; }

.st-coverage-sm { font-size: 11px; font-weight: 600; padding: 1px 6px; }

/* ==========================================================================
   Shared map fullscreen. One vocabulary for every map in the app, applied to the
   element that should fill the viewport (.st-map-fs) plus the map itself
   (.st-map-fs-body). Global rather than scoped because several of these maps live
   inside MudDialog bodies, and the expanded layer must escape the dialog, hence a
   z-index above MudBlazor's dialog/popover stack rather than the 1300 the dashboard
   card can get away with as a page-level element.
   ========================================================================== */
.st-map-fs.st-map-fs-on {
    position: fixed;
    inset: 0;
    margin: 0;
    border: none;
    border-radius: 0;
    /* A small inset so a shell whose own header has no padding (the drawing editor) does not
       sit flush against the viewport edge; maps that fill the shell lose 12px, which reads as
       deliberate framing rather than a bug. */
    padding: 10px 12px 12px;
    box-sizing: border-box;
    /* The collapsed shells carry their own fixed height (a vh calc, 340px, 65vh…); the
       expanded layer must ignore all of it and take the viewport. */
    height: 100%;
    max-height: none;
    min-height: 0;
    width: auto;
    background: var(--st-white);
    z-index: 2500;
    display: flex;
    flex-direction: column;
}

/* The map element grows to fill the expanded shell; min-height:0 keeps the flex child from
   being pinned to its natural height inside a column flexbox. !important on the height is
   deliberate and scoped to the expanded state: several of these maps still declare their
   collapsed height inline (a data-driven-looking px value on the element), and a fullscreen
   utility that silently no-ops on those would be worse than the specificity escape hatch. */
.st-map-fs.st-map-fs-on .st-map-fs-body {
    flex: 1 1 auto;
    min-height: 0;
    height: auto !important;
    max-height: none !important;
}

/* The toggle itself, identical to the dashboard live map's live-expand button, so
   the control reads the same wherever a map is. */
.st-map-expand {
    background: var(--st-bg);
    border: 1px solid #E2E8F0;
    border-radius: 8px;
    cursor: pointer;
    padding: 5px 8px;
    color: #475569;
    display: inline-flex;
    align-items: center;
    transition: background .15s, color .15s;
    flex-shrink: 0;
}

.st-map-expand:hover {
    background: var(--st-primary-light);
    color: var(--st-primary);
    border-color: #C7D7FE;
}

/* Floating variant for maps with no header bar to host the button: pinned to the
   map's top-right corner, above the Mapbox canvas but under any style toggle group. */
.st-map-expand-float {
    position: absolute;
    top: 10px;
    right: 10px;
    /* Above the map's own controls (mapbox uses 2) and the style-toggle groups (5), so the
       toggle is never the thing a stray overlay swallows the click for. */
    z-index: 6;
    background: var(--st-white);
    box-shadow: 0 1px 4px rgba(15, 23, 42, 0.25);
}

/* The location drawing editor's canvas shell. Lifted out of an inline style so the shared
   fullscreen class can override its height; the values are unchanged. Global rather than
   scoped because the editor renders inside a MudDialog body. */
.st-drawing-canvas {
    position: relative;
    height: calc(88vh - 210px);
    min-height: 420px;
    border: 1px solid var(--st-border);
    border-radius: 12px;
    overflow: hidden;
}

/* A map dropped straight into a page/dialog with no header bar of its own (the employee day
   GPS map). Lifted out of an inline style so the shared fullscreen class can override the
   height; the values are unchanged. */
.st-map-inset {
    position: relative;
    width: 100%;
    height: 320px;
    border-radius: 8px;
    overflow: hidden;
    background: #F1F5F9;
}

/* A map filling a dialog body (subcontractor directory, subcontractor service area). Lifted
   out of an inline style so the shared fullscreen class can override the height; the values
   are unchanged. --st-border is the same #E8EDF5 the inline rule used. */
.st-map-dialog {
    height: 65vh;
    min-height: 420px;
    border-radius: 12px;
    border: 1px solid var(--st-border);
}

/* While a map is expanded, no ancestor may create a containing block for its position:fixed
   layer. MudBlazor's dialog carries `animation: mud-open-dialog-* .1s both`, and in Chrome an
   element with a filling transform animation is a containing block for fixed descendants even
   once the animation's final value is `none`, which pinned a "fullscreen" map to the dialog
   box. Killing the animation is safe here: it has long since finished, and its end state is the
   element's own declared state. map-fullscreen.js flags the body for exactly as long as a map is
   expanded, so none of this applies in any other situation. */
body.st-map-fs-active .mud-dialog-container,
body.st-map-fs-active .mud-dialog,
body.st-map-fs-active .mud-overlay {
    animation: none !important;
    transform: none !important;
    translate: none !important;
    scale: none !important;
    rotate: none !important;
    filter: none !important;
    backdrop-filter: none !important;
    will-change: auto !important;
}

/* Approval traffic light: the status dot shared by the shift-scheduler approval overview and the
   dashboard approvals block. Green / yellow / red with a soft halo so the colour reads at a glance. */
.st-light {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: var(--st-radius-full);
    flex-shrink: 0;
}
.st-light.st-light-lg { width: 16px; height: 16px; }
.st-light.green  { background: var(--st-success); box-shadow: 0 0 0 3px var(--st-success-light); }
.st-light.yellow { background: var(--st-caution); box-shadow: 0 0 0 3px var(--st-caution-light); }
.st-light.red    { background: var(--st-error);   box-shadow: 0 0 0 3px var(--st-error-light); }

/* ===================================================================
   List page building blocks (approved design, piloted on /customers).
   StStatusBadge, .st-table-card/.st-table, StTableSkeleton, StSearchField,
   StFilterButton, StFilterChips, StPager.
   ========================================================================== */

/* StStatusBadge tones. The pill itself (+ its 6px dot) is .st-status in app.css. */
.st-status.st-status--success { background: var(--st-success-light); color: var(--st-success); }
.st-status.st-status--warning { background: var(--st-warning-light); color: var(--st-warning); }
.st-status.st-status--neutral { background: var(--st-bg-alt); color: var(--st-muted); }
.st-status.st-status--error   { background: var(--st-error-light); color: var(--st-error); }
.st-status.st-status--info    { background: #EFF6FF; color: #3B82F6; }
.st-status.st-status--primary { background: var(--st-primary-light); color: var(--st-primary); }

/* Table card: a white bordered card holding a plain <table class="st-table">, plus (optionally)
   a StPager footer. Rows are ~52px so a second muted line (address, number) fits. Add
   .st-table--clickable when a row click navigates, for the pointer cursor. */
.st-table-card {
  background: var(--st-white);
  border: 1px solid var(--st-border);
  border-radius: var(--st-radius-md);
}
/* No overflow:hidden on the card (it would clip the Filters popover), so the scroll box
   rounds its own corners where it touches the card edge. */
.st-table-scroll { overflow-x: auto; }
.st-table-card > .st-table-scroll:first-child { border-radius: var(--st-radius-md) var(--st-radius-md) 0 0; }
.st-table-card > .st-table-scroll:last-child { border-radius: 0 0 var(--st-radius-md) var(--st-radius-md); }
.st-table-card > .st-table-scroll:only-child { border-radius: var(--st-radius-md); }

/* Toolbar band at the top of a table card: search stretches across, Filters and bulk actions
   sit on the right, and the active-filter chips wrap underneath inside the same band. */
.st-table-card__toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 12px 16px; border-bottom: 1px solid var(--st-border);
}
/* One row: search (fixed, shorter) on the left, then the active-filter chips right next to the
   Filters button on the right, then any bulk actions. The wrappers dissolve (display: contents)
   so their children line up in this single flex row; order puts the chips before the button. */
.st-table-card__toolbar > .st-list-toolbar,
.st-table-card__toolbar .st-list-toolbar__main { display: contents; }
.st-table-card__toolbar .st-list-toolbar__main > * { order: 1; }
.st-table-card__toolbar .st-search { flex: 0 1 320px; width: auto; min-width: 180px; }
.st-table-card__toolbar > .st-filter-chips {
  order: 2; margin: 0 0 0 auto; flex: 0 1 auto; min-width: 0; justify-content: flex-end;
}
.st-table-card__toolbar .st-list-toolbar__main > .st-filter { order: 3; }
.st-table-card__toolbar:not(:has(> .st-filter-chips)) .st-list-toolbar__main > .st-filter { margin-left: auto; }
.st-table-card__toolbar .st-list-toolbar__side { order: 4; }
.st-table-card__toolbar:not(:has(.st-filter)):not(:has(> .st-filter-chips)) .st-list-toolbar__side { margin-left: auto; }
@media (max-width: 640px) {
  .st-table-card__toolbar .st-search { flex: 1 1 100%; }
  .st-table-card__toolbar > .st-filter-chips { margin-left: 0; justify-content: flex-start; }
}
/* The Filters button sits at the card's right edge here, so its panel opens leftwards. */
.st-table-card__toolbar .st-filter__panel { left: auto; right: 0; }

/* Fill mode for list pages: put .st-content--fill on the page's .st-content and the table card
   always reaches the bottom of the window. The page itself stops scrolling; only the rows scroll,
   under a sticky column header, with the toolbar on top and the pager pinned at the bottom.
   An empty or no-results state is centred in the same full-height card. Phones keep normal
   page scrolling, where a nested scroll area is awkward. */
@media (min-width: 769px) {
  .st-main:has(> .st-content--fill) { height: 100vh; height: 100dvh; min-height: 0; }
  .st-content--fill { display: flex; flex-direction: column; min-height: 0; }
  .st-content--fill > .st-table-card { flex: 1; min-height: 320px; display: flex; flex-direction: column; }
  .st-content--fill > .st-table-card > .st-table-card__toolbar,
  .st-content--fill > .st-table-card > .st-pager { flex-shrink: 0; }
  .st-content--fill > .st-table-card > .st-table-scroll { flex: 1; min-height: 0; overflow: auto; }
  .st-content--fill .st-table thead th { position: sticky; top: 0; z-index: 1; }
  .st-content--fill > .st-table-card > .st-empty-state { flex: 1; justify-content: center; }
  /* The pinned pager sits under the global bug-report button (.bug-fab, 56px at 24px from the
     corner); keep its controls clear of it. */
  .st-content--fill > .st-table-card > .st-pager { padding-right: 72px; }
}

/* Generic fill surface (rule 14 widened: every page or tab whose main content is ONE work
   surface fills the window). Mark the chain from the page down to the surface:
     - the page root: .st-content.st-content--fill, or nothing at all: a .st-content whose
       direct child is a .st-fill switches to fill mode by itself, so a tab component can opt
       in per view (its list view fills, its builder view keeps normal page scroll). A page
       without .st-content puts the .st-fill directly under .st-main;
     - any wrapper element in between (a tab component's root div): .st-fill;
     - the surface card itself: .st-fill as well (a table card, a board, a calendar card), or
       .st-fill-scroll for a surface that should simply scroll in place (a card grid).
   A .st-fill takes the height left over by its siblings (a toolbar card above it keeps its
   natural height), lays its children out as a column, and its scroll region
   (.st-fill__body or .st-table-scroll) is the only thing that scrolls. Toolbars and pagers
   stay pinned; an EmptyState (or .st-fill__center) directly inside is centred in the full
   height. Phones keep normal page scrolling. */
@media (min-width: 769px) {
  .st-main:has(> .st-fill),
  .st-main:has(> .st-content > .st-fill),
  .st-main:has(> .st-content > .st-fill-scroll) { height: 100vh; height: 100dvh; min-height: 0; }
  .st-content:has(> .st-fill),
  .st-content:has(> .st-fill-scroll) { display: flex; flex-direction: column; min-height: 0; }
  /* A surface that is its own scroll region and keeps its own display (a card grid, a board):
     it takes the leftover height and scrolls; grid rows keep their natural height. */
  .st-fill-scroll { flex: 1 1 0; min-height: 0; overflow: auto; align-content: start; }
  .st-fill { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; }
  .st-fill > .st-fill__body,
  .st-fill > .st-table-scroll { flex: 1 1 0; min-height: 0; overflow: auto; }
  .st-fill > .st-table-card__toolbar,
  .st-fill > .st-pager,
  .st-fill > .st-fill__fixed { flex-shrink: 0; }
  .st-fill > .st-empty-state,
  .st-fill > .st-fill__center { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; }
  .st-fill .st-table thead th { position: sticky; top: 0; z-index: 1; }
  .st-fill > .st-pager { padding-right: 72px; }
  /* A StCard as the fill surface (<StCard Class="st-fill">): the title bar stays, the body is
     the scroll region. A body holding a table lets the table's own scroll box take the height
     (so the sticky header works) with a pager pinned under it; an EmptyState at the end of
     the body is centred in the space left. */
  .st-card.st-fill > .st-card__head { flex-shrink: 0; }
  .st-card.st-fill > .st-card__body { flex: 1 1 0; min-height: 0; overflow: auto; }
  .st-card.st-fill > .st-card__body:has(> .st-table-scroll),
  .st-card.st-fill > .st-card__body:has(> .st-empty-state:last-child) { display: flex; flex-direction: column; }
  .st-card.st-fill > .st-card__body > .st-table-scroll { flex: 1 1 0; min-height: 0; overflow: auto; }
  .st-card.st-fill > .st-card__body > .st-pager { flex-shrink: 0; padding-right: 72px; }
  .st-card.st-fill > .st-card__body > .st-empty-state:last-child { flex: 1 1 auto; justify-content: center; }
}
.st-table { width: 100%; border-collapse: collapse; }
.st-table th {
  height: 40px; padding: 0 16px;
  background: var(--st-bg);
  border-bottom: 1px solid var(--st-border);
  font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--st-muted); text-align: left; white-space: nowrap; user-select: none;
}
.st-table td {
  height: 52px; padding: 8px 16px;
  border-bottom: 1px solid var(--st-border-light);
  font-size: 13px; color: var(--st-text); vertical-align: middle;
}
.st-table tbody tr:last-child td { border-bottom: none; }
.st-table tbody tr { transition: background var(--st-duration-fast); }
.st-table tbody tr:hover td { background: var(--st-bg); }
.st-table tbody tr.is-selected td { background: #F5F8FF; }
.st-table.st-table--clickable tbody tr { cursor: pointer; }
.st-table th.st-table__sortable { cursor: pointer; }
.st-table th.st-table__sortable:hover { color: var(--st-text); }
.st-table .st-table__check { width: 44px; padding-right: 0; }
.st-table .st-table__actions { width: 52px; padding: 0 8px; text-align: right; }
.st-table .st-table__num { text-align: center; }
.st-table__primary { font-size: 14px; font-weight: 500; color: var(--st-text); line-height: 1.35; }
.st-table__secondary {
  font-size: 12px; color: var(--st-muted); line-height: 1.35; margin-top: 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 520px;
}
.st-table__empty { color: var(--st-border-hover); }
.st-table input[type="checkbox"] { width: 16px; height: 16px; cursor: pointer; accent-color: var(--st-primary); }
/* Row actions: the three-dot MudMenu trigger at the end of every row. */
.st-table .st-row-menu .mud-icon-button { color: var(--st-subtle); }
.st-table .st-row-menu .mud-icon-button:hover { color: var(--st-text); }

/* Skeleton shimmer (StTableSkeleton, and any other loading placeholder). */
.st-skeleton {
  display: block; height: 10px; border-radius: var(--st-radius-full);
  background: linear-gradient(90deg, var(--st-bg-alt) 0%, var(--st-border) 50%, var(--st-bg-alt) 100%);
  background-size: 200% 100%;
  animation: st-shimmer 1.4s ease-in-out infinite;
}
.st-skeleton--line2 { height: 8px; margin-top: 8px; width: 45%; }
@keyframes st-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) {
  .st-skeleton { animation: none; background: var(--st-bg-alt); }
}

/* List toolbar: search + Filters button on the left, secondary controls on the right. */
.st-list-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--st-space-3); flex-wrap: wrap; margin-bottom: var(--st-space-3);
}
.st-list-toolbar__main { display: flex; align-items: center; gap: var(--st-space-2); flex: 1; min-width: 0; flex-wrap: wrap; }
.st-list-toolbar__side { display: flex; align-items: center; gap: var(--st-space-2); flex-shrink: 0; }

/* StSearchField: a native input with a leading search icon, sized to the 34px buttons. */
.st-search { position: relative; width: 320px; max-width: 100%; }
.st-search__icon {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  color: var(--st-subtle); pointer-events: none; font-size: 18px;
}
.st-search__input {
  width: 100%; height: 34px; padding: 0 34px 0 34px;
  border: 1px solid var(--st-border); border-radius: var(--st-radius);
  background: var(--st-white); color: var(--st-text);
  font-family: var(--st-font-body); font-size: 13px; outline: none;
  transition: border-color var(--st-duration-fast), box-shadow var(--st-duration-fast);
}
.st-search__input::placeholder { color: var(--st-subtle); }
.st-search__input:hover { border-color: var(--st-border-hover); }
.st-search__input:focus { border-color: var(--st-primary); box-shadow: 0 0 0 3px var(--st-primary-focus-ring); }
.st-search__input::-webkit-search-cancel-button { display: none; }
.st-search__end {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center;
}
.st-search__end .mud-progress-circular { width: 16px; height: 16px; }
.st-search__clear {
  border: none; background: transparent; padding: 2px; border-radius: 4px;
  color: var(--st-subtle); cursor: pointer; display: inline-flex;
}
.st-search__clear:hover { color: var(--st-text); background: var(--st-bg-alt); }
.st-search__clear .mud-icon-root { font-size: 16px; }
@media (max-width: 768px) { .st-search { width: 100%; } }

/* StFilterButton: Ghost-style trigger with an active-count pill and an anchored panel.
   The panel is not portaled, so it lives next to the trigger (no MudPopover), and a
   transparent backdrop closes it on an outside click. */
.st-filter { position: relative; }
.st-filter__count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px; margin-left: 2px;
  border-radius: var(--st-radius-full);
  background: var(--st-primary); color: var(--st-white);
  font-size: 11px; font-weight: 700; line-height: 1;
}
.st-filter__backdrop { position: fixed; inset: 0; z-index: 30; }
.st-filter__panel {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 31;
  width: 320px; max-width: calc(100vw - 32px);
  background: var(--st-white); border: 1px solid var(--st-border);
  border-radius: var(--st-radius-md); box-shadow: var(--st-shadow-popover);
  display: flex; flex-direction: column;
}
.st-filter__body { padding: 16px; display: flex; flex-direction: column; gap: 16px; max-height: 60vh; overflow-y: auto; }
.st-filter__footer {
  display: flex; align-items: center; justify-content: space-between; gap: var(--st-space-2);
  padding: 10px 16px; border-top: 1px solid var(--st-border-light);
}
/* One filter group inside the panel: uppercase label + control. */
.st-filter-group { display: flex; flex-direction: column; gap: 8px; }
.st-filter-group__label {
  font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--st-muted);
}
.st-filter-options { display: flex; flex-direction: column; gap: 2px; max-height: 220px; overflow-y: auto; }
.st-filter-option {
  display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: var(--st-radius-sm);
  font-size: 13px; color: var(--st-text); cursor: pointer;
}
.st-filter-option:hover { background: var(--st-bg); }
.st-filter-option input { width: 16px; height: 16px; cursor: pointer; accent-color: var(--st-primary); margin: 0; }
.st-filter-option__meta { margin-left: auto; font-size: 12px; color: var(--st-subtle); }

/* Text-style link button ("Clear all", "Clear filters"). */
.st-link-btn {
  border: none; background: transparent; padding: 0; cursor: pointer;
  font-family: var(--st-font-body); font-size: 13px; font-weight: 600; color: var(--st-primary);
}
.st-link-btn:hover { text-decoration: underline; }
.st-link-btn:disabled { color: var(--st-subtle); cursor: default; text-decoration: none; }

/* StFilterChips: removable chips for the active filters, under the toolbar. */
.st-filter-chips { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-bottom: var(--st-space-3); }
.st-filter-chip {
  display: inline-flex; align-items: center; gap: 4px; height: 26px; padding: 0 4px 0 10px;
  border-radius: var(--st-radius-full); border: 1px solid var(--st-primary-border);
  background: var(--st-primary-light); color: var(--st-primary);
  font-size: 12px; font-weight: 500; white-space: nowrap;
}
.st-filter-chip__remove {
  width: 18px; height: 18px; border: none; border-radius: var(--st-radius-full); padding: 0;
  background: transparent; color: var(--st-primary); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.st-filter-chip__remove:hover { background: var(--st-primary-100); }
.st-filter-chip__remove .mud-icon-root { font-size: 14px; }
.st-filter-chips .st-link-btn { font-size: 12px; margin-left: 4px; }

/* StPager: "Showing 1-25 of 312" left; rows-per-page + prev/next right. Sits at the bottom of
   a .st-table-card. */
.st-pager {
  display: flex; align-items: center; justify-content: space-between; gap: var(--st-space-3);
  flex-wrap: wrap; padding: 10px 16px; border-top: 1px solid var(--st-border);
  font-size: 13px; color: var(--st-muted);
}
.st-pager__side { display: flex; align-items: center; gap: var(--st-space-2); }
.st-pager__size {
  height: 30px; padding: 0 26px 0 10px; border: 1px solid var(--st-border); border-radius: var(--st-radius);
  background: var(--st-white); color: var(--st-text); font-family: var(--st-font-body); font-size: 13px;
  appearance: none; -webkit-appearance: none; cursor: pointer; outline: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--st-subtle) 50%), linear-gradient(135deg, var(--st-subtle) 50%, transparent 50%);
  background-position: calc(100% - 13px) 13px, calc(100% - 9px) 13px;
  background-size: 4px 4px, 4px 4px; background-repeat: no-repeat;
}
.st-pager__size:focus { border-color: var(--st-primary); }
.st-pager .st-icon-btn { width: 30px; height: 30px; }

/* ===================================================================
   StConfirmDialog (Components/StConfirmDialog.razor): the shared confirm dialog.
   Global, because dialog bodies are portaled.
   ========================================================================== */
.st-dialog-title .icon-tile.icon-tile--danger { background: var(--st-error-light); color: var(--st-error); }
.st-confirm-dialog .st-confirm-body {
  padding: 20px 24px; font-size: 14px; line-height: 1.5; color: var(--st-text);
  white-space: pre-line;
}


/* ── Detail page header + page cards (design rollout) ─────────────────────────────────
   PageHeader with BackHref: a back arrow, the record name with its status badge, and one
   muted line of key facts. StCard: a white card with a title bar (title, optional icon,
   action top-right) over a divider, used for detail-page and settings content. */
.st-page-header--detail .st-page-header__inner { align-items: center; }
.st-page-header__back {
  flex-shrink: 0; width: 34px; height: 34px; border-radius: var(--st-radius-base);
  border: 1px solid var(--st-border); background: var(--st-white); color: var(--st-muted);
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  transition: border-color var(--st-duration-fast), color var(--st-duration-fast);
}
.st-page-header__back:hover { border-color: var(--st-border-hover); color: var(--st-text); }
.st-page-header__back:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--st-primary-focus-ring); }
.st-page-header__back .mud-icon-root { font-size: 18px; }
.st-page-header--detail .st-page-header__titles { flex: 1; }
.st-page-header__title-row { display: flex; align-items: center; gap: var(--st-space-2); flex-wrap: wrap; min-width: 0; }
.st-page-header__facts {
  font-size: 13px; color: var(--st-muted); line-height: 1.4;
  display: flex; flex-wrap: wrap; align-items: center; column-gap: 6px;
}

.st-card {
  background: var(--st-white); border: 1px solid var(--st-border);
  border-radius: var(--st-radius-md); min-width: 0;
}
.st-card__head {
  display: flex; align-items: center; gap: var(--st-space-2);
  min-height: 48px; padding: 8px 12px 8px 16px;
  border-bottom: 1px solid var(--st-border-light);
}
.st-card__icon.mud-icon-root { font-size: 18px; color: var(--st-subtle); }
.st-card__title { margin: 0; font-size: 14px; font-weight: 600; color: var(--st-text); line-height: 1.4; }
.st-card__subtitle { font-size: 12px; color: var(--st-muted); }
.st-card__actions { margin-left: auto; display: flex; align-items: center; gap: var(--st-space-1); }
.st-card__body { padding: 16px; }
.st-card--flush > .st-card__body { padding: 0; }
/* Two-column card grid for detail-page overviews; stacks on narrow screens. */
.st-card-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--st-space-4); align-items: start; }
.st-card-grid > .st-card--wide { grid-column: 1 / -1; }
@media (max-width: 1100px) { .st-card-grid { grid-template-columns: minmax(0, 1fr); } }
/* Label/value list inside a card. */
.st-kv { display: grid; grid-template-columns: minmax(120px, 34%) 1fr; gap: 10px 16px; margin: 0; font-size: 13px; }
.st-kv dt { color: var(--st-muted); }
.st-kv dd { margin: 0; color: var(--st-text); min-width: 0; overflow-wrap: anywhere; }

/* ===================================================================
   Rollout wave 2B (inventory, subcontractors, machinery, zones, messages).
   ========================================================================== */
/* Single-column st-dialog body: .st-dialog zeroes the content padding for the two-column
   task dialog, so plain form dialogs pad and space their own body. Global: dialogs portal. */
.st-dialog-body.st-dialog-body--padded { padding: 20px 24px; display: flex; flex-direction: column; gap: 14px; }
/* Segmented preset buttons in a toolbar (date range presets): Ghost-sized, the active one tinted. */
.st-segment { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.st-segment__btn {
  height: 34px; padding: 0 12px; border: 1px solid var(--st-border); border-radius: var(--st-radius);
  background: var(--st-white); color: var(--st-muted); font-family: var(--st-font-body);
  font-size: 13px; font-weight: 500; cursor: pointer; white-space: nowrap;
  transition: background var(--st-duration-fast), border-color var(--st-duration-fast), color var(--st-duration-fast);
}
.st-segment__btn:hover { border-color: var(--st-border-hover); color: var(--st-text); }
.st-segment__btn.is-active { border-color: var(--st-primary); background: var(--st-primary-light); color: var(--st-primary); }
/* Native <select> sized to the 34px toolbar controls (outlined, 8px radius, token colours). */
.st-native-select {
  height: 34px; padding: 0 30px 0 10px; border: 1px solid var(--st-border); border-radius: var(--st-radius);
  background-color: var(--st-white); color: var(--st-text); font-family: var(--st-font-body); font-size: 13px;
  appearance: none; -webkit-appearance: none; cursor: pointer; outline: none; max-width: 100%;
  background-image: linear-gradient(45deg, transparent 50%, var(--st-subtle) 50%), linear-gradient(135deg, var(--st-subtle) 50%, transparent 50%);
  background-position: calc(100% - 15px) 15px, calc(100% - 11px) 15px;
  background-size: 4px 4px, 4px 4px; background-repeat: no-repeat;
}
.st-native-select:hover { border-color: var(--st-border-hover); }
.st-native-select:focus { border-color: var(--st-primary); box-shadow: 0 0 0 3px var(--st-primary-focus-ring); }
.st-filter-group .st-native-select { width: 100%; }

/* ===================================================================
   Rollout wave 2A (tasks list).
   ========================================================================== */
.st-text-warning { color: var(--st-warning); }

/* ===================================================================
   Rollout wave 3A (customer + department detail pages).
   ========================================================================== */
/* Three equal columns (form rows in dialogs; global because dialog bodies are portaled). */
.st-grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
/* Small round avatar in dialog member lists: a photo (img) or initials on a muted tile. */
.st-mini-avatar {
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0; object-fit: cover;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--st-muted); color: var(--st-white); font-size: 11px; font-weight: 500;
}
/* Colour swatch picker (department colour). The swatch colour itself is inline (data). */
.st-color-swatches { display: flex; flex-wrap: wrap; gap: 8px; }
.st-color-swatch {
  width: 28px; height: 28px; border-radius: 50%; padding: 0; cursor: pointer;
  border: 3px solid transparent; transition: border-color var(--st-duration-fast);
}
.st-color-swatch.is-selected { border-color: var(--st-text); }
.st-color-swatch:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--st-primary-focus-ring); }
/* DepartmentEditDialog: underline section tabs over a scrolling pane, fixed dialog height. */
.st-dept-edit { height: min(70vh, 680px); display: flex; flex-direction: column; }
.st-dept-edit > .cust-tab-strip { flex-shrink: 0; }
.st-dept-edit__pane { flex: 1; min-height: 0; overflow-y: auto; padding: 20px 24px; display: flex; flex-direction: column; gap: 20px; }
.st-dept-edit__list { max-height: 280px; overflow-y: auto; }
.st-dept-edit__empty { padding: 14px; font-size: 13px; color: var(--st-subtle); text-align: center; }
.st-worker-act.st-dept-edit__star:hover,
.st-worker-act.st-dept-edit__star.is-on { color: var(--st-warning); border-color: var(--st-warning); background: var(--st-warning-light); }
.st-dept-edit__search { padding: 8px 10px; border-bottom: 1px solid var(--st-border-light); }
.st-dept-edit__search .st-search { width: 100%; }

/* ===================================================================
   Rollout wave 4A (settings page + its tab components).
   ========================================================================== */
/* Danger zone card: error-tinted border and title (StCard Class="st-card--danger"). */
.st-card.st-card--danger { border-color: color-mix(in srgb, var(--st-error) 35%, var(--st-white)); }
.st-card--danger > .st-card__head { border-bottom-color: color-mix(in srgb, var(--st-error) 15%, var(--st-white)); }
.st-card--danger > .st-card__head .st-card__title { color: var(--st-error-dark); }
.st-card--danger > .st-card__head .st-card__icon.mud-icon-root { color: var(--st-error); }
/* Toggle chip (pill) for multi-pick lists in dialogs: roles, departments. Global: dialogs portal. */
.st-choice-chip {
  padding: 6px 14px; border-radius: var(--st-radius-full); border: 1px solid var(--st-border);
  background: var(--st-white); color: var(--st-muted); font-family: var(--st-font-body);
  font-size: 13px; font-weight: 600; cursor: pointer;
  transition: background var(--st-duration-fast), border-color var(--st-duration-fast), color var(--st-duration-fast);
}
.st-choice-chip:hover { border-color: var(--st-border-hover); }
.st-choice-chip.is-active { border-color: var(--st-primary); background: var(--st-primary-light); color: var(--st-primary); }
/* Round colour dot (shift type colours in selects; the colour itself is inline data). */
.st-color-dot { display: inline-block; width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; }
/* Larger colour preview next to a colour input (shift type dialog). */
.st-color-preview { display: inline-block; width: 32px; height: 32px; border-radius: var(--st-radius-sm); border: 1px solid var(--st-border); cursor: pointer; }
/* StCard that fills its flex parent (a card beside a taller sibling). */
.st-card.st-card--fill { flex: 1; display: flex; flex-direction: column; }
.st-text-success { color: var(--st-success); }

/* ===================================================================
   Rollout wave 4B (location detail modal).
   ========================================================================== */
/* The AI accent (the corner mark on "Create from document"). */
:root { --st-ai: #7C3AED; }
/* Label/value lines inside a drawer card ("Company: ..."), and an inline error box. */
.st-fact-list { display: flex; flex-direction: column; gap: 4px; }
.st-fact { font-size: 13px; color: var(--st-text); }
.st-fact__label { color: var(--st-muted); }
.st-error-box {
  background: var(--st-error-light); border: 1px solid color-mix(in srgb, var(--st-error) 35%, var(--st-white));
  border-radius: var(--st-radius); padding: 10px 12px; font-size: 13px; color: var(--st-error-dark);
}
/* Section split inside a card body: a hairline and 16px above the next block. */
.st-divider-top { border-top: 1px solid var(--st-border); padding-top: 16px; }
/* Outlined expansion panel inside a card (invoice text templates). */
.st-expander.mud-expand-panel { border: 1px solid var(--st-border); border-radius: var(--st-radius); }

/* ===================================================================
   Rollout wave 5A (dashboard + customer portal).
   ========================================================================== */
/* Small underline tabs at the top of a card body: the PageTabs look at card scale. */
.st-card-tabs {
  display: flex; gap: 16px; padding: 0 16px; overflow-x: auto; scrollbar-width: none;
  box-shadow: inset 0 -1px 0 var(--st-border-light);
}
.st-card-tabs::-webkit-scrollbar { display: none; }
.st-card-tab {
  display: inline-flex; align-items: center; gap: 6px; padding: 10px 2px 8px;
  background: transparent; border: none; border-bottom: 2px solid transparent; border-radius: 0;
  font-family: inherit; font-size: 12px; font-weight: 500; color: var(--st-muted);
  cursor: pointer; white-space: nowrap;
  transition: color var(--st-duration-fast), border-color var(--st-duration-fast);
}
.st-card-tab:hover:not(.is-active) { color: var(--st-text); border-bottom-color: var(--st-border-hover); }
.st-card-tab.is-active { color: var(--st-primary); font-weight: 600; border-bottom-color: var(--st-primary); }
.st-card-tab__count {
  font-size: 11px; font-weight: 700; padding: 0 6px; border-radius: 10px; min-width: 18px; text-align: center;
  background: var(--st-bg-alt); color: var(--st-muted);
}
.st-card-tab.is-active .st-card-tab__count { background: var(--st-primary-light); color: var(--st-primary); }
/* Count pill beside a StCard title (Header slot). */
.st-card__count {
  font-size: 11px; font-weight: 700; padding: 1px 7px; border-radius: 10px; min-width: 20px; text-align: center;
  background: var(--st-bg-alt); color: var(--st-muted);
}
.st-card__count.st-card__count--error { background: var(--st-error-light); color: var(--st-error); }
/* Skeleton rows for a card list while it loads: two shimmer lines per row. */
.st-skel-row { padding: 12px 16px; border-bottom: 1px solid var(--st-border-light); }
.st-skel-row:last-child { border-bottom: none; }
.st-skel-row > .st-skeleton:first-child { width: 60%; }
/* Thin progress bar: a muted track; each fill's colour and width are data (inline). */
.st-progress { display: flex; height: 6px; border-radius: var(--st-radius-full); background: var(--st-bg-alt); overflow: hidden; }
.st-progress__fill { height: 100%; transition: width 0.4s; }
.st-progress__fill--partial { opacity: 0.5; }
/* Purple tag (subcontractor), on the AI accent. */
.st-badge-ai { background: color-mix(in srgb, var(--st-ai) 12%, var(--st-white)); color: var(--st-ai); }
/* A status pill whose dot pulses: live work (StStatusBadge Class="st-status--live"). */
.st-status.st-status--live::before { animation: st-status-pulse 1.2s ease-in-out infinite; }
@keyframes st-status-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.4; transform: scale(0.7); }
}
@media (prefers-reduced-motion: reduce) {
  .st-status.st-status--live::before { animation: none; }
}

/* ===================================================================
   Rollout wave 5B (planning week grid + route editor).
   ========================================================================== */
/* Drawn-route accent (route cards in the week grid, the route editor's view banner). An indigo
   family kept apart from --st-primary so a route never reads as a selected entry. */
:root {
  --st-route:        #6366F1;
  --st-route-dark:   #4F46E5;
  --st-route-soft:   #818CF8;
  --st-route-border: #A5B4FC;
  --st-route-hover:  #E0E7FF;
  --st-route-light:  #EEF2FF;
}

/* ===================================================================
   Rollout wave 5C (shift scheduler + service assets).
   ========================================================================== */
/* A dialog that draws its own chrome edge to edge (shift export modal). Global: dialogs portal. */
.mud-dialog.st-dialog-flush { padding: 0; }

/* ===================================================================
   Rollout wave 6A (dialog batch 1). Global: dialog bodies are portaled.
   ========================================================================== */
/* Plain explanatory text at the top of a padded dialog body. */
.st-dialog-message { font-size: 14px; line-height: 1.5; color: var(--st-text); white-space: pre-line; }
/* Muted hint line under a message or inside a section. */
.st-dialog-hint { font-size: 13px; line-height: 1.45; color: var(--st-muted); }
/* Title block with a muted second line (record name, date) under the dialog title. */
.st-dialog-title .st-dialog-title__text { display: flex; flex-direction: column; min-width: 0; }
.st-dialog-title .st-dialog-title__sub { font-size: 12px; color: var(--st-muted); font-weight: 500; }
/* Close X at the right of a viewer dialog's title (viewers without a Cancel). */
.st-dialog-title .st-dialog-close { margin-left: auto; flex-shrink: 0; }
/* Image viewer body. */
.st-image-preview { display: block; max-width: 100%; max-height: 80vh; margin: 0 auto; border-radius: var(--st-radius); }
.st-tabular { font-variant-numeric: tabular-nums; }
/* GpsNearbyDialog ("Who was here?"): date + radius row, then the worker list. */
.gnd-body { max-height: 70vh; overflow-y: auto; }
.gnd-controls { display: flex; gap: 12px; padding: 14px 24px; border-bottom: 1px solid var(--st-border-light); }
.gnd-ctl { flex: 1 1 0; min-width: 0; }
.gnd-msg { margin: 12px 24px 0; }
.gnd-list { display: flex; flex-direction: column; padding: 8px 16px 14px; }
.gnd-row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 10px 8px; border: 0; border-radius: 10px; background: transparent;
  text-align: left; cursor: pointer; font: inherit;
}
.gnd-row:hover { background: var(--st-bg); }
.gnd-avatar {
  width: 34px; height: 34px; min-width: 34px; border-radius: 50%; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--st-white); font-size: 12px; font-weight: 700;
}
.gnd-avatar img { width: 100%; height: 100%; object-fit: cover; }
.gnd-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.gnd-name { font-size: 13px; font-weight: 600; color: var(--st-text); }
.gnd-meta { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--st-muted); flex-wrap: wrap; }
.gnd-dot { color: var(--st-border); }
.gnd-none { color: var(--st-subtle); font-style: italic; }
.gnd-arrow { color: var(--st-muted); flex-shrink: 0; }
.gnd-chev.mud-icon-root { color: var(--st-subtle); font-size: 18px; }
/* GpsWorkerDayDialog: the day map, scrolling inside the dialog. */
.gwd-body { max-height: 78vh; overflow-y: auto; gap: 8px; }
/* Bordered pick list in a dialog: a tinted header, then scrolling checkbox rows. */
.st-pick-list { border: 1px solid var(--st-border); border-radius: var(--st-radius); overflow: hidden; }
.st-pick-list__head {
  padding: 10px 14px; background: var(--st-bg); border-bottom: 1px solid var(--st-border);
  font-size: 12px; font-weight: 600; color: var(--st-muted);
}
.st-pick-list__body { max-height: 250px; overflow-y: auto; }
.st-pick-list__row {
  padding: 10px 14px; border-bottom: 1px solid var(--st-border-light);
  display: flex; align-items: center; gap: 12px; font-size: 14px; color: var(--st-text);
}
.st-pick-list__row:last-child { border-bottom: none; }
/* Red text button for a secondary destructive action at the far left of a dialog footer
   ("Delete team", "End sick leave"): StButton Kind=Secondary Class="st-button--danger-text mr-auto". */
.st-button.st-button--secondary.st-button--danger-text.mud-button-root:not(.mud-icon-button) { color: var(--st-error); }
.st-button.st-button--secondary.st-button--danger-text.mud-button-root:not(.mud-icon-button):hover { background: var(--st-error-light); }
.st-button.st-button--secondary.st-button--danger-text.mud-disabled:not(.mud-icon-button) { color: var(--st-subtle); }
/* ELearningAttemptDialog: score summary, then one card per question with its answers. */
.ela-summary { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.ela-score { font-size: 18px; font-weight: 700; color: var(--st-text-strong); }
.ela-score__of { color: var(--st-subtle); font-weight: 500; font-size: 13px; }
.ela-score__count { color: var(--st-muted); font-weight: 500; font-size: 13px; margin-left: 8px; }
.ela-times { text-align: right; font-size: 12px; color: var(--st-muted); }
.ela-q { border: 1px solid var(--st-border); border-radius: 10px; padding: 12px; background: var(--st-white); }
.ela-q__head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.ela-q__mark {
  width: 22px; height: 22px; border-radius: 11px; display: inline-flex; align-items: center; justify-content: center;
}
.ela-q__mark.is-correct { background: color-mix(in srgb, var(--st-success) 18%, var(--st-white)); color: var(--st-success-dark); }
.ela-q__mark.is-wrong { background: color-mix(in srgb, var(--st-error) 15%, var(--st-white)); color: var(--st-error-dark); }
.ela-q__module { font-size: 11px; color: var(--st-muted); }
.ela-q__text { font-weight: 600; color: var(--st-text-strong); margin-bottom: 8px; }
.ela-q__answers { display: flex; flex-direction: column; gap: 6px; }
.ela-a {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--st-radius);
  background: var(--st-bg); border: 1px solid var(--st-border); font-size: 13px;
}
.ela-a.is-correct { background: var(--st-success-light); border-color: color-mix(in srgb, var(--st-success) 50%, var(--st-white)); }
.ela-a.is-wrong { background: var(--st-error-light); border-color: color-mix(in srgb, var(--st-error) 50%, var(--st-white)); }
.ela-a.is-correct .ela-a__icon { color: var(--st-success); }
.ela-a.is-wrong .ela-a__icon { color: var(--st-error); }
.ela-a__spacer { width: 18px; display: inline-block; flex-shrink: 0; }
.ela-a__yours { margin-left: auto; font-size: 11px; color: var(--st-muted); }
/* DayTasksDialog rows (the row itself is .day-tasks-row in app.css). */
.day-tasks-body { padding: 8px 8px 12px; max-height: 70vh; overflow-y: auto; }
.day-tasks-row__main { flex: 1; min-width: 0; }
.day-tasks-row__title { font-size: 13px; font-weight: 500; color: var(--st-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.day-tasks-row__sub { font-size: 12px; color: var(--st-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.day-tasks-row__side { text-align: right; flex-shrink: 0; margin-left: 8px; font-size: 11px; color: var(--st-subtle); }
/* DayDetailDialog: faded secondary bits in a task row (the rows themselves live in app.css). */
.day-detail-dim { opacity: 0.6; }
.day-detail-faint { opacity: 0.5; }
.day-detail-faint--italic { font-style: italic; }
/* AbsenceCoverageDialog: one bordered card per affected route, with a substitute picker. */
.acd-routes { max-height: 60vh; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }
.acd-route { border: 1px solid var(--st-border); border-radius: 10px; overflow: hidden; }
.acd-route__head { display: flex; align-items: center; gap: 12px; padding: 8px 14px 8px 8px; background: var(--st-bg); }
.acd-route__name { flex: 1; min-width: 0; }
.acd-route__title { font-size: 13px; font-weight: 600; color: var(--st-text); }
.acd-route__meta { font-size: 11px; color: var(--st-subtle); }
.acd-route__select { max-width: 280px; }
.acd-route__select.is-over { border-color: color-mix(in srgb, var(--st-error) 50%, var(--st-white)); }
.acd-route__pct { width: 54px; text-align: right; font-size: 13px; font-weight: 700; }
.acd-route__over {
  display: flex; align-items: center; gap: 6px; padding: 6px 14px; font-size: 11px;
  background: var(--st-error-light); color: var(--st-error-dark);
  border-top: 1px solid color-mix(in srgb, var(--st-error) 30%, var(--st-white));
}
.acd-route__over .mud-icon-root { color: var(--st-error); }
.acd-route__days { padding: 4px 14px 10px 50px; }
.acd-day { font-size: 11px; font-weight: 700; color: var(--st-muted); margin: 8px 0 2px; text-transform: capitalize; }
.acd-item { display: flex; justify-content: space-between; gap: 12px; font-size: 12px; color: var(--st-muted); padding: 2px 0 2px 12px; }
/* CoverageChangesDialog: search field with its suggestion list, and the current changes list. */
.ccd-body { gap: 24px; }
.ccd-row { display: flex; gap: 10px; align-items: flex-start; }
.ccd-row > .st-button { margin-top: 3px; }
.ccd-search { flex: 1; position: relative; min-width: 0; }
.ccd-suggest {
  position: absolute; z-index: 10; top: 100%; left: 0; right: 0; margin-top: 2px;
  background: var(--st-white); border: 1px solid var(--st-border); border-radius: var(--st-radius);
  max-height: 200px; overflow-y: auto; box-shadow: var(--st-shadow);
}
.ccd-suggest__item { padding: 8px 10px; cursor: pointer; font-size: 13px; color: var(--st-text); }
.ccd-suggest__item:hover { background: var(--st-bg); }
.ccd-out .ccd-member { color: var(--st-subtle); text-decoration: line-through; }
.ccd-list { display: flex; flex-direction: column; gap: 8px; max-height: 46vh; overflow-y: auto; }
.ccd-item { border: 1px solid var(--st-border); border-radius: var(--st-radius); padding: 10px 12px; display: flex; align-items: center; gap: 12px; }
.ccd-item__dir { font-size: 13px; color: var(--st-text); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ccd-item__meta { font-size: 11px; color: var(--st-subtle); margin-top: 2px; }
/* Single-pick rows in a dialog (invoice customer picker): initial avatar, two lines, a check when picked. */
.st-pick-rows { max-height: 340px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.st-pick-row {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: var(--st-radius);
  cursor: pointer; border: 1px solid transparent; transition: background var(--st-duration-fast);
}
.st-pick-row:hover { background: var(--st-bg); }
.st-pick-row.is-selected { background: var(--st-primary-light); border-color: var(--st-primary-border); }
.st-pick-row__avatar {
  width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0; background: var(--st-muted); color: var(--st-white);
  display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 600;
}
.st-pick-row.is-selected .st-pick-row__avatar { background: var(--st-primary); }
.st-pick-row__title { font-size: 13px; font-weight: 500; color: var(--st-text); }
.st-pick-row__sub { font-size: 11px; color: var(--st-subtle); }
.st-pick-row__check.mud-icon-root { color: var(--st-primary); font-size: 18px; flex-shrink: 0; }
/* CreateFromDocumentDialog: a tall stepped dialog (department, upload, processing, review). */
/* Sized to content (up to 90vh, then the body scrolls); .cfd-step-body keeps a minimum. */
.cfd-dialog { max-width: 960px; max-height: 90vh; display: flex; flex-direction: column; }
.cfd-dialog .mud-dialog-content { flex: 1; min-height: 0; overflow-y: auto; }
.cfd-steps { display: flex; align-items: center; padding: 0 8px 8px; }
.cfd-step { display: flex; align-items: center; flex: 1; min-width: 0; }
.cfd-step:last-child { flex: 0 0 auto; }
.cfd-step__col { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 48px; }
.cfd-step__dot {
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700;
  background: var(--st-border); color: var(--st-muted);
}
.cfd-step__dot.is-active { background: var(--st-primary); color: var(--st-white); }
.cfd-step__dot.is-done { background: var(--st-success); color: var(--st-white); }
.cfd-step__label { font-size: 10px; font-weight: 500; color: var(--st-muted); white-space: nowrap; }
.cfd-step__label.is-active { color: var(--st-primary); }
.cfd-step__line { flex: 1; height: 2px; background: var(--st-border); margin: 0 4px 18px; }
.cfd-step__line.is-done { background: var(--st-success); }
.cfd-step-body { min-height: 200px; }
.cfd-option {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 16px;
  border: 1px solid var(--st-border); border-radius: 10px; background: var(--st-white); cursor: pointer;
  transition: border-color var(--st-duration-fast), background var(--st-duration-fast);
}
.cfd-option:hover { border-color: var(--st-border-hover); }
.cfd-option.is-selected { border-color: var(--st-primary); background: var(--st-primary-light); }
.cfd-option.is-disabled { cursor: not-allowed; opacity: 0.5; }
.cfd-option__icon.mud-icon-root { color: var(--st-muted); font-size: 20px; }
.cfd-option__name { font-size: 14px; font-weight: 500; color: var(--st-text); }
.cfd-drop {
  display: block; position: relative; border: 2px dashed var(--st-border-hover); border-radius: var(--st-radius-md);
  padding: 32px; text-align: center; background: var(--st-bg); cursor: pointer;
  transition: border-color var(--st-duration-fast), background var(--st-duration-fast);
}
.cfd-drop.is-over { border-color: var(--st-primary); background: var(--st-primary-light); }
.cfd-drop.has-file { border-color: var(--st-success); background: var(--st-success-light); }
.cfd-drop__icon.mud-icon-root { font-size: 40px; color: var(--st-subtle); margin-bottom: 8px; }
.cfd-drop__icon.st-text-success.mud-icon-root { color: var(--st-success); }
.cfd-drop__text { font-size: 14px; color: var(--st-muted); margin: 0; }
.cfd-drop__name { font-size: 14px; font-weight: 600; color: var(--st-text); margin: 0; }
.cfd-drop__meta { font-size: 12px; color: var(--st-muted); margin: 4px 0 0; }
.cfd-drop__input { position: absolute; width: 1px; height: 1px; overflow: hidden; opacity: 0; }
.cfd-processing { min-height: 220px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; padding: 16px; }
.cfd-processing__title { font-size: 15px; font-weight: 600; color: var(--st-text); margin: 0; }
.cfd-processing__note { font-size: 13px; color: var(--st-muted); text-align: center; max-width: 400px; margin: 0; }
.cfd-progress { display: flex; flex-direction: column; gap: 8px; width: 100%; max-width: 340px; margin-top: 8px; }
.cfd-progress__row { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--st-subtle); }
.cfd-progress__row.is-done { color: var(--st-text); }
.cfd-progress__dot {
  width: 18px; height: 18px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: var(--st-border); color: var(--st-white);
}
.cfd-progress__row.is-done .cfd-progress__dot { background: var(--st-success); }
.cfd-summary {
  display: flex; gap: 12px; flex-wrap: wrap; padding: 12px 16px; font-size: 13px; color: var(--st-muted);
  background: var(--st-bg); border: 1px solid var(--st-border); border-radius: 10px;
}
.cfd-area { border: 1px solid var(--st-border); border-radius: var(--st-radius-md); background: var(--st-white); }
.cfd-area.is-off { opacity: 0.5; border-style: dashed; }
.cfd-area__head { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-bottom: 1px solid var(--st-border-light); }
.cfd-check { width: 16px; height: 16px; accent-color: var(--st-primary); cursor: pointer; flex-shrink: 0; }
.cfd-area__name {
  flex: 1; min-width: 0; font-size: 14px; font-weight: 600; color: var(--st-text);
  border: 1px solid transparent; border-radius: var(--st-radius-sm); padding: 4px 6px; outline: none; background: transparent; font-family: inherit;
}
.cfd-area__name:hover, .cfd-area__name:focus { border-color: var(--st-border); background: var(--st-white); }
.cfd-area__body { display: flex; flex-direction: column; gap: 10px; padding: 12px 14px 14px; }
.cfd-freq {
  display: flex; flex-direction: column; gap: 10px; padding: 12px;
  border: 1px solid var(--st-border-light); border-radius: var(--st-radius); background: var(--st-bg);
}
.cfd-freq.is-flagged { border-color: var(--st-warning); background: var(--st-warning-light); }
.cfd-freq__row { display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-start; }
.cfd-freq__schedule { flex: 1 1 200px; min-width: 180px; }
.cfd-range { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.cfd-w-84 { width: 84px; flex: 0 0 auto; }
.cfd-w-96 { width: 96px; flex: 0 0 auto; }
.cfd-w-120 { width: 120px; flex: 0 0 auto; }
.cfd-item-input { flex: 1; min-width: 0; height: 32px; font-size: 13px; }
.cfd-add-freq { max-width: 260px; }
/* ImportServiceAgreementsDialog: tall stepped dialog (reuses the cfd- drop zone and processing
   blocks), a bar stepper, and one card per extracted location with its agreements. */
.sai-dialog { max-width: 980px; max-height: 90vh; display: flex; flex-direction: column; }
.sai-dialog .mud-dialog-content { flex: 1; min-height: 0; overflow-y: auto; }
.sai-lang { max-width: 280px; }
.sai-global { display: flex; flex-direction: column; gap: 10px; border: 1px solid var(--st-border); border-radius: 10px; padding: 12px 14px; background: var(--st-bg); }
.sai-global__fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; }
.sai-loc { border: 1px solid var(--st-border); border-radius: 10px; padding: 14px; background: var(--st-white); display: flex; flex-direction: column; gap: 10px; }
.sai-loc__head { display: flex; align-items: center; gap: 10px; }
.sai-loc__name { flex: 1; min-width: 0; font-size: 15px; font-weight: 600; color: var(--st-text); }
.sai-loc__target { display: flex; gap: 12px; flex-wrap: wrap; padding-left: 38px; }
.sai-loc__address { min-width: 260px; flex: 1; }
.sai-loc__ags { padding-left: 38px; display: flex; flex-direction: column; gap: 6px; }
.sai-prices-head {
  display: flex; align-items: center; gap: 6px; margin-top: 10px; padding-top: 8px;
  border-top: 1px dashed var(--st-border-hover); font-size: 11px; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--st-primary);
}
.sai-ag { display: flex; align-items: flex-start; gap: 10px; border-top: 1px solid var(--st-border-light); padding-top: 6px; }
.sai-ag__title { font-size: 14px; font-weight: 500; color: var(--st-text); padding-top: 6px; }
.sai-ag__row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 5px; }
.sai-ag__assign { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.sai-months { display: flex; gap: 3px; flex-wrap: wrap; }
.sai-month {
  border: 1px solid var(--st-border); cursor: pointer; min-width: 38px; height: 22px; padding: 0 6px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.4px; border-radius: 5px;
  background: var(--st-bg); color: var(--st-subtle); transition: all 0.1s; font-family: inherit;
}
.sai-month.is-on { border-color: var(--st-primary); background: var(--st-primary); color: var(--st-white); }
.sai-note {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; padding: 3px 9px; font-size: 11px;
  color: var(--st-warning); background: var(--st-warning-light);
  border: 1px solid color-mix(in srgb, var(--st-warning) 30%, var(--st-white)); border-radius: 5px;
}
.sai-w-108 { width: 108px; }
.sai-w-150 { min-width: 150px; }
.sai-w-200 { min-width: 200px; }
.sai-w-240 { min-width: 240px; }
/* DepartmentTeamEditDialog: switches with a hint under each, and a pickable people list. */
.dte-skel { height: 40px; border-radius: var(--st-radius); }
.dte-option { display: flex; flex-direction: column; gap: 2px; }
.dte-people { max-height: 240px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.dte-person {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--st-radius);
  cursor: pointer; transition: background var(--st-duration-fast);
}
.dte-person:hover { background: var(--st-bg); }
.dte-person.is-selected { background: var(--st-primary-light); }
.dte-avatar { width: 30px; height: 30px; }
.dte-person__name { font-size: 13px; font-weight: 500; color: var(--st-text); }
.dte-person__role { font-size: 11px; color: var(--st-subtle); }
/* CustomerFilesTab: file thumbnails and names in the files table, search results, and the
   full-screen preview (a dark scrim with the image or PDF). */
.cft-thumb {
  width: 36px; height: 36px; object-fit: cover; border-radius: 4px; flex-shrink: 0;
  border: 1px solid var(--st-border); background: var(--st-bg);
}
.cft-icon.mud-icon-root { font-size: 20px; flex-shrink: 0; }
.cft-pdf {
  background: var(--st-error-light); color: var(--st-error); font-size: 10px; font-weight: 700;
  padding: 3px 6px; border-radius: 4px; flex-shrink: 0;
}
.cft-name {
  display: block; max-width: 420px; font-size: 14px; font-weight: 500; color: var(--st-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left;
}
.cft-name--link {
  background: none; border: none; padding: 0; font-family: inherit; cursor: pointer; color: var(--st-primary);
}
.cft-name--link:hover { text-decoration: underline; text-underline-offset: 2px; }
.cft-results-head { padding: 10px 16px; font-size: 12px; color: var(--st-muted); border-bottom: 1px solid var(--st-border-light); }
.cft-result { display: flex; flex-direction: column; gap: 8px; padding: 14px 16px; border-bottom: 1px solid var(--st-border-light); }
.cft-result:last-child { border-bottom: none; }
.cft-result__head { display: flex; align-items: center; gap: 10px; }
.cft-snippets { border-top: 1px solid var(--st-border-light); padding-top: 8px; font-size: 12px; line-height: 1.6; color: var(--st-muted); display: flex; flex-direction: column; gap: 4px; }
.cft-preview {
  position: fixed; inset: 0; z-index: 10000; background: rgba(0, 0, 0, 0.8);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.cft-preview__bar { position: absolute; top: 16px; right: 16px; display: flex; gap: 8px; }
.cft-preview__btn {
  background: rgba(255, 255, 255, 0.15); color: var(--st-white); border: none; border-radius: var(--st-radius);
  padding: 8px 14px; font-size: 13px; font-family: inherit; cursor: pointer; backdrop-filter: blur(4px);
  display: inline-flex; align-items: center;
}
.cft-preview__name { color: var(--st-white); font-size: 14px; font-weight: 600; margin-bottom: 12px; }
.cft-preview__img { max-width: 90vw; max-height: 80vh; border-radius: var(--st-radius); box-shadow: 0 8px 40px rgba(0, 0, 0, 0.3); }
.cft-preview__pdf { width: 90vw; max-width: 900px; height: 82vh; border: none; border-radius: var(--st-radius); background: var(--st-white); }
/* ===================================================================
   Rollout wave 7A (public/anonymous pages + customer file dialogs).
   =================================================================== */
/* Centred sign-in card shared by login, reset password, accept invite, verify email, email
   changed, mobile-only and the subcontractor signup/onboarding pages. */
.st-auth-page {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  background: var(--st-bg); padding: 24px 16px;
}
.st-auth-card {
  width: 100%; max-width: 400px; padding: 40px; background: var(--st-white);
  border: 1px solid var(--st-border); border-radius: var(--st-radius-lg);
}
.st-auth-card--wide { max-width: 460px; }
.st-auth-card--xwide { max-width: 640px; }
.st-auth-card--center { text-align: center; }
@media (max-width: 480px) { .st-auth-card { padding: 28px 20px; } }
.st-auth-brand { display: flex; justify-content: center; margin-bottom: 32px; }
.st-auth-logo { display: block; height: 32px; width: auto; }
.st-auth-title.mud-typography { color: var(--st-text); margin-bottom: 8px; }
.st-auth-subtitle.mud-typography { color: var(--st-muted); margin-bottom: 24px; line-height: 1.5; }
.st-auth-hint.mud-typography { color: var(--st-subtle); }
.st-auth-stack { display: flex; flex-direction: column; gap: 16px; }
.st-auth-stack--tight { gap: 12px; }
/* Big state icon at the top of a result card (success, error, "use the app"). */
.st-auth-state-icon.mud-icon-root { font-size: 48px; }
.st-auth-state-icon--xl.mud-icon-root { font-size: 56px; margin-bottom: 12px; }
.st-auth-link { font-size: 14px; cursor: pointer; }
.st-auth-foot { text-align: center; font-size: 13px; color: var(--st-subtle); margin: 0; }
.st-auth-foot a { color: var(--st-primary); text-decoration: none; font-weight: 600; }
.st-auth-skeleton { display: flex; flex-direction: column; gap: 14px; padding: 8px 0; }
.st-auth-skeleton .st-skeleton { height: 12px; }
.st-auth-skeleton .st-skeleton--title { height: 18px; width: 60%; }
.st-auth-skeleton .st-skeleton--field { height: 40px; border-radius: var(--st-radius); }
/* Pickable option card (subcontractor signup plan choice). */
.st-plan-option {
  display: block; width: 100%; text-align: left; font-family: inherit; cursor: pointer;
  border: 2px solid var(--st-border); border-radius: var(--st-radius-md); padding: 14px 16px;
  background: var(--st-white); transition: border-color var(--st-duration-fast), background var(--st-duration-fast);
}
.st-plan-option + .st-plan-option { margin-top: 10px; }
.st-plan-option:hover { border-color: var(--st-border-hover); }
.st-plan-option.is-selected { border-color: var(--st-primary); background: var(--st-primary-light); }
.st-plan-option__head { display: flex; align-items: center; gap: 8px; }
.st-plan-option__title { flex: 1; font-size: 15px; font-weight: 700; color: var(--st-text); }
.st-plan-option__desc { display: block; margin-top: 2px; font-size: 12px; line-height: 1.5; color: var(--st-muted); }
/* Country picker beside the phone field (subcontractor signup). */
.st-signup-country { min-width: 150px; }
.st-plan-option__tag {
  font-size: 11px; font-weight: 600; white-space: nowrap; color: var(--st-primary);
  background: var(--st-primary-100); border-radius: var(--st-radius-full); padding: 2px 10px;
}
/* Customer file upload / edit dialogs: staged file rows, tag chips, tag suggestions, results. */
.cfu-files { display: flex; flex-direction: column; gap: 6px; }
.cfu-file {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  background: var(--st-bg); border: 1px solid var(--st-border); border-radius: var(--st-radius);
}
.cfu-file__icon.mud-icon-root { font-size: 18px; color: var(--st-subtle); flex-shrink: 0; }
.cfu-file__body { flex: 1; min-width: 0; }
.cfu-file__name { font-size: 12px; font-weight: 500; color: var(--st-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cfu-file__meta { font-size: 11px; color: var(--st-subtle); }
.cfu-file__meta--error { color: var(--st-error); }
.cfu-tags { display: flex; flex-wrap: wrap; gap: 4px; }
.cfu-suggest {
  border: 1px solid var(--st-border); border-radius: var(--st-radius); background: var(--st-white);
  box-shadow: var(--st-shadow); overflow: hidden;
}
.cfu-suggest__item {
  display: block; width: 100%; text-align: left; border: none; background: transparent; font-family: inherit;
  padding: 8px 12px; font-size: 13px; color: var(--st-text); cursor: pointer;
}
.cfu-suggest__item:hover { background: var(--st-bg); }
.cfu-results { display: flex; flex-direction: column; }
.cfu-result { display: flex; align-items: center; gap: 8px; padding: 6px 0; font-size: 12px; border-bottom: 1px solid var(--st-border-light); color: var(--st-text); }
.cfu-result--failed { color: var(--st-muted); }
.cfu-result .mud-icon-root { font-size: 16px; flex-shrink: 0; }

/* ===================================================================
   Design rollout wave 6B
   =================================================================== */
/* WorkRequestPinMap's map box (was defined by WorkRequestDetailDialog's inline <style>). */
.wr-pin-map { height: 220px; border-radius: 10px; overflow: hidden; border: 1px solid var(--st-border); }

/* ===================================================================
   Design rollout wave 8
   =================================================================== */
/* The slate-200 border of the service agreement dialog's schedule boxes. */
:root { --st-border-input: #E2E8F0; }
/* CreateServiceAgreementDialog: the schedule-entry box and the picker popovers under its fields.
   Global, because the dialog body is portaled. */
.mud-paper.st-sched-entry {
  border: 1.5px solid var(--st-border-input); border-radius: 10px; padding: 16px;
  display: flex; flex-direction: column; gap: 12px;
}
.mud-paper.st-sched-popover {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 10;
  border: 1.5px solid var(--st-border-input); border-radius: 10px; padding: 16px;
  display: flex; flex-direction: column; gap: 10px; background: var(--st-white);
}
/* A sub view inside a page tab (an e-learning course's statistics or builder under HR): back
   button (the PageHeader back style), a title with one muted line of facts, actions right. */
.st-subview-head { display: flex; align-items: center; gap: var(--st-space-3); margin-bottom: var(--st-space-4); }
.st-subview-head__titles { flex: 1; min-width: 0; }
.st-subview-head__title {
  margin: 0; font-size: 20px; font-weight: 700; line-height: 1.3; letter-spacing: -0.01em;
  color: var(--st-text-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.st-subview-head__facts { font-size: 13px; color: var(--st-muted); margin-top: 2px; }
.st-subview-head__actions { display: flex; align-items: center; gap: var(--st-space-2); flex-shrink: 0; }
/* A row of small KPI tiles above a list or a statistics view. */
.st-kpi-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--st-space-3); margin-bottom: var(--st-space-4);
}
@media (max-width: 900px) { .st-kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Department name pill tinted with the department's colour (data, passed as --dept). */
.st-dept-pill {
  display: inline-block; font-size: 11px; font-weight: 600; padding: 2px 8px; white-space: nowrap;
  border-radius: var(--st-radius-full); color: var(--dept, var(--st-primary));
  background: color-mix(in srgb, var(--dept, var(--st-primary)) 10%, transparent);
}
/* A progress bar with its percentage in a table cell (the fill's width and colour are data). */
.st-progress-cell { display: flex; align-items: center; gap: var(--st-space-2); }
.st-progress-cell .st-progress { width: 80px; flex-shrink: 0; }
.st-progress-cell__pct { font-size: 12px; font-weight: 600; color: var(--st-text); }
/* A person's avatar in a table row: photo, or the initial on a primary tint. */
.st-table-avatar {
  width: 28px; height: 28px; border-radius: 50%; object-fit: cover; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--st-primary-light); color: var(--st-primary); font-size: 12px; font-weight: 600;
}
/* Knowledge base: the item-kind colours (file, image, video, YouTube, link, note) on a square
   glyph and on a small tag, shared by the folder view and the service-type view. */
.kn-kind { background: var(--kn-bg); color: var(--kn-fg); }
.kn-kind--file    { --kn-fg: var(--st-primary);    --kn-bg: var(--st-primary-light); }
.kn-kind--image   { --kn-fg: var(--st-success-dark); --kn-bg: var(--st-success-light); }
.kn-kind--video   { --kn-fg: var(--st-ai);         --kn-bg: color-mix(in srgb, var(--st-ai) 8%, var(--st-white)); }
.kn-kind--youtube { --kn-fg: var(--st-error-dark); --kn-bg: var(--st-error-light); }
.kn-kind--link    { --kn-fg: var(--st-primary);    --kn-bg: var(--st-primary-light); }
.kn-kind--note    { --kn-fg: var(--st-warning);    --kn-bg: var(--st-warning-light); }
.kn-kind--other   { --kn-fg: var(--st-muted);      --kn-bg: var(--st-bg-alt); }
.kn-glyph {
  width: 34px; height: 34px; border-radius: var(--st-radius); flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.kn-glyph .mud-icon-root { font-size: 18px; color: inherit; }
.kn-glyph.kn-glyph--lg { width: 54px; height: 54px; border-radius: var(--st-radius-md); }
.kn-glyph.kn-glyph--lg .mud-icon-root { font-size: 30px; }
/* A folder's accent colour (a department's colour, or the AI purple when shared with all) is
   data, passed as --dept; the glyph tints with it. */
.kn-glyph.kn-glyph--folder {
  color: var(--dept, var(--st-primary));
  background: color-mix(in srgb, var(--dept, var(--st-primary)) 10%, transparent);
}
/* LocationPopupDialog tab components (contacts, prices, checklists, drawings): the intro line and
   actions above a tab's card, matching the dialog's own tabs (its scoped .loc-toolbar). */
.st-tab-toolbar {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
  gap: var(--st-space-2); margin-bottom: var(--st-space-4);
}
.st-tab-hint { font-size: 13px; color: var(--st-muted); margin: 0; }
.st-table .st-table__money { text-align: right; white-space: nowrap; font-weight: 600; }
/* ── Side panel (decision A: small records open on the right, full height) ─────────────────
   Invoices, service agreements, requests and quality reports open here instead of in a centred
   dialog. Two ways in, one look:
   1. A MudDialog component opened with IDialogService.ShowSidePanelAsync (Services/
      DialogServiceExtensions.cs). MudBlazor 8's DialogOptions has no Class, so the helper marks the
      overlay with BackgroundClass "st-side-panel-backdrop" (+ --md / --lg) and these rules reach
      the dialog through its container. The st-dialog shell inside keeps working: the title bar and
      the actions stay put (sticky) while only .mud-dialog-content scrolls.
   2. A hand-rolled layout-level overlay (the quality report view/fill): .st-side-overlay holding
      .st-side-overlay__panel (+ --md / --lg), a flex column whose own body element scrolls.
   Global on purpose: dialog content is portaled, scoped CSS cannot reach it. */
.mud-dialog-container:has(.st-side-panel-backdrop) {
  padding: 0; align-items: stretch; justify-content: flex-end;
}
.mud-dialog-container:has(.st-side-panel-backdrop) .mud-dialog,
.st-side-overlay__panel {
  position: relative; top: auto; right: auto; bottom: auto; left: auto;
  width: 560px; max-width: 100vw; height: 100vh; height: 100dvh; max-height: none; margin: 0;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--st-white);
  border-radius: var(--st-radius-lg) 0 0 var(--st-radius-lg) !important;
  box-shadow: var(--st-shadow-modal);
  animation: st-side-panel-in 220ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
.mud-dialog-container:has(.st-side-panel-backdrop--lg) .mud-dialog,
.st-side-overlay__panel.st-side-overlay__panel--lg { width: 760px; }
.mud-dialog-container:has(.st-side-panel-backdrop) .mud-dialog .mud-dialog-title,
.mud-dialog-container:has(.st-side-panel-backdrop) .mud-dialog .mud-dialog-actions { flex: 0 0 auto; }
.mud-dialog-container:has(.st-side-panel-backdrop) .mud-dialog .mud-dialog-content {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
}
.mud-dialog-container:has(.st-side-panel-backdrop) .mud-dialog .mud-dialog-actions { justify-content: flex-end; }
/* Bodies that capped their own height inside a centred dialog grow with the panel instead, so
   there is one scroll area (the content) rather than a box scrolling inside a box. */
.mud-dialog-container:has(.st-side-panel-backdrop) .inv-body,
.mud-dialog-container:has(.st-side-panel-backdrop) .wr-body { max-height: none; overflow: visible; }
/* The service agreement's facts / tasks columns stack in the narrower panel, as they already
   do on small screens. */
.mud-dialog-container:has(.st-side-panel-backdrop) .sav-grid { grid-template-columns: minmax(0, 1fr); max-height: none; }
.mud-dialog-container:has(.st-side-panel-backdrop) .sav-left {
  overflow: visible; border-right: none; border-bottom: 1px solid var(--st-border-light);
}
.st-side-overlay {
  position: fixed; inset: 0; z-index: 1400;
  display: flex; align-items: stretch; justify-content: flex-end;
  background: rgba(0, 0, 0, 0.5);
}
@keyframes st-side-panel-in {
  from { transform: translateX(100%); }
  to   { transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
  .mud-dialog-container:has(.st-side-panel-backdrop) .mud-dialog,
  .st-side-overlay__panel { animation: none; }
}

/* ===================================================================
   PO review fixes (dialog header, location edit, links & QR codes).
   Global: dialog bodies are portaled.
   ========================================================================== */
/* Every st-dialog title bar gets the create-dialog padding explicitly, so a legacy per-dialog
   reset of MudDialog's slot padding can never leave the icon tile flush against the edge.
   The close X of a viewer dialog sits vertically centred at the right (optically aligned with
   MudBlazor's own CloseButton). */
.mud-dialog.st-dialog .mud-dialog-title { padding: 16px 24px; }
.st-dialog-title .st-dialog-close { margin-right: -8px; }
.st-dialog-title .st-dialog-title__text .ttl { line-height: 1.3; }
.st-dialog-title .st-dialog-title__sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* .st-toggle-row as a real <button> (keyboard reachable, role="switch"): reset the native
   button chrome, keep the row look, and give it the app's focus ring. */
button.st-toggle-row { width: 100%; margin: 0; font: inherit; text-align: left; color: inherit; }
button.st-toggle-row:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--st-primary-light); border-color: var(--st-primary); }
.st-toggle-row .info .t, .st-toggle-row .info .d { display: block; }
button.st-toggle-row:disabled { cursor: default; opacity: 0.6; }
button.st-toggle-row:disabled:hover { border-color: var(--st-border); }
button.st-toggle-row.on:disabled:hover { border-color: var(--st-primary); }
/* Address autocomplete (Google's place element): its search and clear glyphs inherit the host
   colour, which the forced light colour scheme left at near-black. Mute them to the field-icon
   tone the MudBlazor fields use; the typed text keeps its own colour via ::part(input). */
.addr-ac-input-container gmp-place-autocomplete { color: var(--st-subtle); }


/* ── Settings layout + sticky save bar (settings round, 2026-09-28) ───────────────────────
   .st-settings: the one content column every Settings tab uses (same width on every tab, cards
   stacked with the same gap). Two-card rows use .st-settings__row. StSaveBar sticks to the
   bottom of the viewport while a tab has unsaved edits. */
.st-settings { display: flex; flex-direction: column; gap: var(--st-space-4); }
.st-settings__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--st-space-4); align-items: stretch; }
@media (max-width: 1100px) { .st-settings__row { grid-template-columns: minmax(0, 1fr); } }
.st-settings .st-card__body > .st-card-intro { margin: 0 0 var(--st-space-4); font-size: 13px; color: var(--st-muted); max-width: 72ch; }

.st-save-bar {
  position: sticky; bottom: var(--st-space-4); z-index: 15;
  display: flex; align-items: center; justify-content: space-between; gap: var(--st-space-3);
  padding: 10px 12px 10px 16px; margin-top: var(--st-space-2);
  background: var(--st-white); border: 1px solid var(--st-border); border-radius: var(--st-radius-md);
  box-shadow: var(--st-shadow-popover);
  animation: st-save-bar-in var(--st-duration-fast) var(--st-ease, ease-out);
}
.st-save-bar__msg { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--st-text); }
.st-save-bar__msg .mud-icon-root { font-size: 18px; color: var(--st-primary); }
.st-save-bar__actions { display: flex; align-items: center; gap: var(--st-space-2); }
@keyframes st-save-bar-in { from { transform: translateY(8px); opacity: 0; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .st-save-bar { animation: none; } }

/* ── Settings tabs: flush-card intro + import tiles (settings round B, 2026-09-28) ───────────
   In a Flush StCard (edge-to-edge table or list) the .st-card-intro line gets its own padding and
   a divider, so the intro sits between the title bar and the rows. .st-settings-toolbar is the
   row above a tab's cards (search left, context right). .st-tile is a clickable picker tile
   (icon tile, label, optional one-line hint) used by the Import tab. */
.st-settings .st-card--flush > .st-card__body > .st-card-intro {
  margin: 0; padding: 12px 16px; max-width: none; border-bottom: 1px solid var(--st-border);
}
.st-settings-toolbar { display: flex; align-items: center; gap: var(--st-space-3); flex-wrap: wrap; }
.st-settings-toolbar > .st-search { flex: 0 1 320px; width: auto; min-width: 200px; }
.st-settings-toolbar__note { margin-left: auto; font-size: 13px; color: var(--st-muted); }
.st-tile-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--st-space-3); }
.st-tile {
  display: flex; align-items: center; justify-content: flex-start; gap: 12px; min-height: 64px; padding: 12px 14px; text-align: left;
  background: var(--st-white); border: 1px solid var(--st-border); border-radius: var(--st-radius-md);
  font-family: var(--st-font-body); color: var(--st-text); cursor: pointer;
  transition: border-color var(--st-duration-fast), background var(--st-duration-fast), box-shadow var(--st-duration-fast);
}
.st-tile:hover { border-color: var(--st-border-hover); }
.st-tile:focus-visible { outline: none; border-color: var(--st-primary); box-shadow: 0 0 0 3px var(--st-primary-focus-ring); }
.st-tile.is-active { border-color: var(--st-primary); background: var(--st-primary-light); }
.st-tile__icon {
  flex-shrink: 0; width: 36px; height: 36px; border-radius: var(--st-radius);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--st-primary-light); color: var(--st-primary);
}
.st-tile.is-active .st-tile__icon { background: var(--st-white); }
.st-tile__icon .mud-icon-root { font-size: 20px; }
.st-tile__text { display: flex; flex-direction: column; min-width: 0; }
.st-tile__label { font-size: 13px; font-weight: 600; line-height: 1.3; }
.st-tile__hint { font-size: 12px; color: var(--st-muted); line-height: 1.35; }

/* Number fields: no spin buttons anywhere (they clip labels and suffixes in dense fields; typing
   and the keyboard arrows still work). StNumericField also sets HideSpinButtons by default; this
   covers the MudNumericField instances used directly. */
.mud-input-numeric-spin { display: none !important; }


/* ── Settings at full page width (same content width as every other page) ──────────────────
   Width rules: a card is either full width, half of a pair (.st-settings__row) or a third of a
   triple (.st-settings__row--3); cards in a row stretch to equal height. Inside cards, fields use
   .st-form-grid (3 columns on wide screens, 2 on laptops, 1 on phones) instead of stretching one
   input across the page, and lists of switches use .st-toggle-grid (2 columns of toggle rows). */
.st-settings__row > .st-card { height: 100%; }
.st-settings__row--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1100px) { .st-settings__row--3 { grid-template-columns: minmax(0, 1fr); } }
.st-form-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px 16px; align-items: start; }
.st-form-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.st-form-grid > .st-form-grid__wide { grid-column: 1 / -1; }
@media (max-width: 1280px) { .st-form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 700px) { .st-form-grid, .st-form-grid--2 { grid-template-columns: minmax(0, 1fr); } }
.st-toggle-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 16px; align-items: stretch; }
@media (max-width: 900px) { .st-toggle-grid { grid-template-columns: minmax(0, 1fr); } }


/* ── Nothing floats on the grey page background (fill/float round, 2026-09-28) ─────────────
   Toolbars, search fields, intro lines, view switches and tab-level actions live inside a card:
   - .st-card-intro: a muted intro line opening a card body (in a Flush card: its own padded
     band with a divider under it, between the title bar and the rows).
   - A toolbar band (.st-table-card__toolbar) may also open a Flush StCard's body. In it,
     .st-toolbar-note is a muted line that takes the free width and .st-toolbar-actions groups
     the buttons at the right end.
   - .st-toolbar-card: a slim card holding only a toolbar band (a search above several cards).
   - .st-subview-head (a sub view's back button, title, facts and actions under a page's tabs)
     is a header card rather than a second page title on the grey. */
.st-card > .st-card__body > .st-card-intro { margin: 0 0 var(--st-space-4); font-size: 13px; line-height: 1.5; color: var(--st-muted); }
.st-card--flush > .st-card__body > .st-card-intro { margin: 0; padding: 12px 16px; border-bottom: 1px solid var(--st-border-light); }
.st-table-card__toolbar > .st-toolbar-note { flex: 1 1 280px; min-width: 0; margin: 0; font-size: 13px; line-height: 1.45; color: var(--st-muted); }
.st-table-card__toolbar > .st-toolbar-actions { display: flex; align-items: center; flex-wrap: wrap; gap: var(--st-space-2); margin-left: auto; }
.st-toolbar-card {
  background: var(--st-white); border: 1px solid var(--st-border); border-radius: var(--st-radius-md);
}
.st-toolbar-card > .st-table-card__toolbar { border-bottom: none; }
.st-subview-head {
  padding: 12px 16px; background: var(--st-white);
  border: 1px solid var(--st-border); border-radius: var(--st-radius-md);
}
.st-subview-head .st-subview-head__title { font-size: 18px; }
@media (min-width: 769px) {
  .st-card.st-fill > .st-card__body > .st-card-intro,
  .st-card.st-fill > .st-card__body > .st-table-card__toolbar { flex-shrink: 0; }
  .st-card.st-fill > .st-card__body:has(> .st-table-card__toolbar) { display: flex; flex-direction: column; }
  .st-card.st-fill > .st-card__body > .st-empty-state:last-child { flex: 1 1 auto; justify-content: center; }
}

/* Photo tile standing in for an upload the server is still transcoding (a HEIC original the
   browser cannot draw) or could not read. Rendered by Components/ImageProcessingTile.razor; the
   --72/--80 modifiers match the thumbnails it replaces. Global because it also lands in dialogs. */
.st-img-pending {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  box-sizing: border-box; padding: 4px; text-align: center;
  background: var(--st-bg); border: 1px dashed var(--st-border); border-radius: var(--st-radius-sm);
  color: var(--st-muted);
}
.st-img-pending--72 { width: 72px; height: 72px; }
.st-img-pending--80 { width: 80px; height: 80px; }
.st-img-pending--failed { color: var(--st-error); }
.st-img-pending__label { font-size: 10px; line-height: 1.2; }

/* Edit dialogs: until a picker's option list has loaded, it shows the record's saved name as its
   placeholder. Draw that placeholder like a real value so nothing flickers when the value lands. */
.st-pending-value .mud-input > input.mud-input-root::placeholder,
.st-pending-value div.mud-input-slot.mud-input-root::placeholder {
  color: var(--mud-palette-text-primary);
  opacity: 1;
}
