:root {
  color-scheme: light dark;
  --bg: #f5f6f8;
  --panel: #ffffff;
  --border: #e0e2e7;
  --text: #1f2430;
  --muted: #6b7280;
  --accent: #2f6feb;
  --accent-hover: #2558c4;
  --danger: #d1453d;
  --danger-hover: #b23a34;
  --success: #1a9c5b;
  --warning: #b8860b;
  --warning-bg: #fff6e0;
  --header-bg: #eef1f6;
  --total-bg: #f0f4ff;
  /* Content width is user-adjustable (drag the handle at its right edge,
     static/page-width.js), clamped to this range and remembered across
     every page via localStorage - see .page-width-handle below. */
  --page-max-width: 1200px;
  --page-min-width: 900px;
  --page-max-width-limit: 1200px;
  --sidebar-width: 220px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #14161a;
    --panel: #1c1f26;
    --border: #2c303a;
    --text: #e6e8ee;
    --muted: #9aa1ac;
    --accent: #5b8def;
    --accent-hover: #7ba2f2;
    --danger: #e2645d;
    --danger-hover: #ea7f79;
    --success: #3ecb82;
    --warning: #e0af3e;
    --warning-bg: #362b12;
    --header-bg: #21252d;
    --total-bg: #1f2740;
  }
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
}

/* App name badge, top-right corner of every page - a pure-CSS pseudo-
   element on <body> rather than an HTML element, so it shows up on every
   template (including login/setup, which don't include any of the shared
   per-page <script> utilities) with zero template changes. This is the
   app's own name (NUMIO), not the company's - see the "company" template
   variable/Settings page for that. Hidden when printing (see @media print
   below) - it has no business appearing on a printed Invoice/Statement. */
body::after {
  content: "NUMIO";
  position: fixed;
  top: 16px;
  right: 20px;
  font-weight: 700;
  font-size: 1.26rem;
  letter-spacing: 0.1em;
  color: var(--accent);
  z-index: 30;
  pointer-events: none;
}

.page {
  max-width: var(--page-max-width);
  margin: 0;
  margin-left: calc(var(--sidebar-width) + 28px);
  padding: 32px 24px 64px 0;
  position: relative;
}

/* The nav is repositioned into a fixed left sidebar purely with CSS - it
   stays exactly where it already sits in every page's HTML (nested inside
   .page, before <header>), it just no longer takes up flow space there
   once taken out of flow via position:fixed, so no template needed
   restructuring to get this layout. */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--sidebar-width);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  flex-wrap: nowrap;
  gap: 3px;
  margin: 0;
  padding: 24px 14px;
  background: var(--panel);
  border-right: 1px solid var(--border);
  overflow-y: auto;
  z-index: 10;
}

.nav-logo {
  width: 100px;
  height: 100px;
  object-fit: contain;
  display: block;
  margin: 0 auto 14px;
  flex-shrink: 0;
}

@media (prefers-color-scheme: dark) {
  .nav-logo {
    background: #ffffff;
    border-radius: 8px;
    padding: 6px;
  }
}

.nav-spacer {
  flex: 1 1 auto;
}

.nav-user {
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 600;
  padding: 6px 12px;
}

.nav-logout-form {
  margin: 0;
}

.nav-logout-btn {
  width: 100%;
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  padding: 8px 12px;
  font-size: 0.85rem;
  font-weight: 500;
}

.nav-logout-btn:hover {
  background: var(--danger);
  color: white;
  border-color: var(--danger);
}

.nav-link {
  display: block;
  text-decoration: none;
  color: var(--muted);
  font-weight: 600;
  font-size: 0.9rem;
  padding: 8px 12px;
  border-radius: 6px;
}

.nav-link:hover {
  background: var(--header-bg);
  color: var(--text);
}

.nav-link.active {
  background: var(--accent);
  color: white;
}

/* ---------------------------------------------------------------------- */
/* Mobile layout (static/mobile-nav.js) - the sidebar is already a fixed   */
/* left panel (see .nav above); under this breakpoint it becomes a        */
/* roll-up drawer instead (hidden by default, slides in over the page),   */
/* toggled by a hamburger button that mobile-nav.js injects - no template  */
/* changes needed beyond adding that one <script> tag. Same breakpoint     */
/* value the Help page's own responsive layout already uses (see the      */
/* max-width: 900px block further down), so there's one consistent        */
/* "mobile" threshold across the app rather than several arbitrary ones.  */
/* ---------------------------------------------------------------------- */

.nav-toggle {
  display: none;
  position: fixed;
  top: 14px;
  left: 14px;
  z-index: 30;
  width: 42px;
  height: 42px;
  align-items: center;
  justify-content: center;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
}

.nav-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  /* Below .nav's z-index (10, see above) - it needs to sit behind the open
     drawer, not in front of it, or it silently eats every click meant for
     a nav link (elementFromPoint at a link's position resolves to the
     backdrop instead of the link underneath it). Still above ordinary
     page content (which has no z-index of its own) so it dims it. */
  z-index: 9;
}

.nav-backdrop.nav-open {
  display: block;
}

@media (max-width: 900px) {
  /* The 20% smaller base font size every other rem/em value in the
     stylesheet scales down from - deliberately done here, once, instead
     of hand-shrinking each individual font-size rule. */
  html {
    font-size: 80%;
  }

  .nav-toggle {
    display: flex;
  }

  .page {
    margin-left: 0;
    padding: 72px 16px 48px;
  }

  .nav {
    transform: translateX(-100%);
    transition: transform 0.2s ease;
    width: min(var(--sidebar-width), 80vw);
    box-shadow: 4px 0 24px rgba(0, 0, 0, 0.25);
  }

  .nav.nav-open {
    transform: translateX(0);
  }

  /* Dragging the content area to a specific width doesn't apply once the
     page is already just "as wide as the phone screen" - hidden rather
     than left as a non-functional control. Column-by-column resizing
     (resizable.js, a different feature) is untouched and still works. */
  .page-width-handle {
    display: none;
  }
}

/* Drag handle for --page-max-width (static/page-width.js appends this one
   element to <body> on every page - anchored via calc() off the CSS
   variable itself, so it tracks the content area's right edge live as the
   variable changes, no JS repositioning needed mid-drag). */
.page-width-handle {
  position: fixed;
  top: 0;
  bottom: 0;
  left: calc(var(--sidebar-width) + 28px + var(--page-max-width));
  width: 10px;
  margin-left: -5px;
  cursor: col-resize;
  z-index: 20;
  touch-action: none;
}

.page-width-handle:hover,
.page-width-handle.resizing {
  background: var(--accent);
  opacity: 0.35;
}

.stats-row {
  display: flex;
  gap: 16px;
  margin-bottom: 28px;
  flex-wrap: wrap;
}

.stat-card {
  flex: 1 1 200px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 18px 20px;
}

.stat-card-balance {
  background: var(--total-bg);
}

.stat-label {
  font-size: 0.8rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 6px;
}

.stat-value {
  font-size: 1.6rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.stat-positive {
  color: var(--success);
}

.stat-negative {
  color: var(--danger);
}

.stat-neutral {
  color: var(--text);
}

.section-heading {
  font-size: 1.1rem;
  margin: 0 0 12px;
  color: var(--muted);
}

.customer-picker {
  max-width: 320px;
  margin-bottom: 20px;
}

.customer-picker select {
  width: 100%;
}

.totals-row {
  margin-top: 20px;
}

.tax-input-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 6px;
}

.tax-input-row input {
  width: 80px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font-size: 0.95rem;
}

.tax-input-row span {
  color: var(--muted);
  font-size: 0.9rem;
}

.section-divider {
  border: none;
  border-top: 1px solid var(--border);
  margin: 40px 0 28px;
}

.banner {
  background: var(--total-bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 14px;
  margin-bottom: 16px;
  font-size: 0.9rem;
}

.banner a {
  color: var(--accent);
  font-weight: 600;
}

.settings-logo-row {
  display: flex;
  align-items: flex-end;
  gap: 20px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.settings-logo-preview {
  width: 100px;
  height: 100px;
  object-fit: contain;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px;
}

header h1 {
  margin: 0 0 4px;
  font-size: 1.75rem;
}

.subtitle {
  margin: 0 0 24px;
  color: var(--muted);
}

.expense-form {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-end;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  margin-bottom: 12px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  /* A flex item's default min-width is `auto`, not 0 - without this, a
     field whose <select> has a long option (e.g. a tax category name)
     refuses to shrink below that option's text width no matter how
     little room is actually available, forcing the whole form (and the
     page itself) wider than the viewport. Invisible on a wide desktop
     window since nothing ever needs to shrink there - only shows up once
     a narrow/mobile viewport actually requires it. */
  min-width: 0;
}

.field-grow {
  flex: 1 1 220px;
}

.field label {
  font-size: 0.8rem;
  color: var(--muted);
}

.field input,
.field select {
  padding: 9px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font-size: 0.95rem;
  min-width: 0;
}

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

.field select:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background: var(--muted);
}

.field-button {
  align-self: stretch;
  justify-content: flex-end;
  flex-direction: row;
  gap: 8px;
}

.field-checkbox {
  align-self: flex-end;
  padding-bottom: 9px;
}

.inline-checkbox-label {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  font-size: 0.9rem;
  cursor: pointer;
  white-space: nowrap;
}

button {
  cursor: pointer;
  border: none;
  border-radius: 6px;
  padding: 10px 18px;
  font-size: 0.95rem;
  font-weight: 600;
  background: var(--accent);
  color: white;
  transition: background 0.15s ease;
}

button:hover {
  background: var(--accent-hover);
}

.form-error {
  color: var(--danger);
  font-size: 0.9rem;
  margin: 0 0 16px;
}

.expense-sheet {
  width: 100%;
  border-collapse: collapse;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}

.expense-sheet th,
.expense-sheet td {
  padding: 10px 14px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  font-size: 0.95rem;
}

.expense-sheet thead th {
  background: var(--header-bg);
  color: var(--muted);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.expense-sheet tbody tr:last-child td {
  border-bottom: none;
}

.expense-sheet tbody tr:hover {
  background: var(--header-bg);
}

.col-idname {
  width: 160px;
  font-weight: 600;
}

.col-usage {
  width: 270px;
  color: var(--muted);
  font-size: 0.85rem;
}

.col-project {
  width: 90px;
  color: var(--muted);
  font-size: 0.85rem;
}

.col-id-actions {
  width: 160px;
  text-align: right;
  white-space: nowrap;
}

.col-category {
  width: 240px;
}

.category-cell {
  color: var(--muted);
  font-size: 0.85rem;
}

.uncategorized-label {
  font-style: italic;
  color: var(--muted);
}

/* ---------------------------------------------------------------------- */
/* Auth pages (setup/login)                                               */
/* ---------------------------------------------------------------------- */

.auth-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.auth-card {
  width: 100%;
  max-width: 380px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 32px;
  text-align: center;
}

.auth-logo {
  max-width: 120px;
  max-height: 120px;
  margin: 0 auto 16px;
  display: block;
}

.auth-card h1 {
  font-size: 1.3rem;
  margin: 0 0 6px;
}

.auth-card .subtitle {
  margin-bottom: 22px;
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
  text-align: left;
}

.auth-form button {
  margin-top: 6px;
}

.auth-card .form-error {
  margin: 16px 0 0;
}

/* Wider auth-card variant for the signup form (name/company/phone/address
   + username/password - more fields than login's two) - everything else
   (.auth-page centering, .auth-logo, .auth-form spacing) is shared. */
.auth-card-wide {
  max-width: 520px;
  text-align: center;
}

.auth-card-wide .auth-form {
  text-align: left;
}

.auth-field-row {
  display: flex;
  gap: 14px;
}

.auth-field-row .field {
  flex: 1;
}

.auth-form .field label {
  display: block;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 4px;
}

.auth-form .field input {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
  font-size: 0.95rem;
}

.auth-form .field input:focus {
  outline: none;
  border-color: var(--accent);
}

.auth-switch {
  margin-top: 18px;
  font-size: 0.9rem;
  color: var(--muted);
}

.auth-switch a {
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
}

.auth-switch a:hover {
  text-decoration: underline;
}

/* ---------------------------------------------------------------------- */
/* Landing page                                                            */
/* ---------------------------------------------------------------------- */

.landing-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 20px;
  text-align: center;
  background:
    radial-gradient(circle at 50% 0%, var(--total-bg) 0%, var(--bg) 60%);
}

.landing-card {
  width: 100%;
  max-width: 460px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.landing-logo {
  width: 148px;
  height: 148px;
  margin-bottom: 8px;
  filter: drop-shadow(0 8px 24px rgba(47, 111, 235, 0.18));
}

.landing-wordmark {
  font-size: 2.4rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  margin: 0;
}

.landing-tagline {
  color: var(--muted);
  font-size: 1.05rem;
  margin: 10px 0 36px;
  line-height: 1.5;
}

.landing-actions {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  max-width: 280px;
}

.landing-btn {
  display: block;
  width: 100%;
  padding: 13px 20px;
  border-radius: 10px;
  font-size: 1rem;
  font-weight: 600;
  text-decoration: none;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  box-sizing: border-box;
}

.landing-btn:hover {
  transform: translateY(-1px);
}

.landing-btn-primary {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 6px 18px rgba(47, 111, 235, 0.3);
}

.landing-btn-primary:hover {
  background: var(--accent-hover);
}

.landing-btn-secondary {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
}

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

.landing-footnote {
  margin-top: 40px;
  font-size: 0.8rem;
  color: var(--muted);
}

/* .field sets display:flex, which beats the browser's [hidden] rule - so the
   Backups page's upload buttons / inline "are you sure?" block have to say so explicitly. Kept
   to this one element on purpose rather than a global [hidden] rule, which
   would also change other pages' .field elements that currently rely on
   being visible despite carrying hidden. */
#upload-actions[hidden],
#upload-confirm[hidden] {
  display: none;
}

/* Edit/Delete/Archive/etc. controls are for admins and "User Plus" (role editor) - see
   require_edit_permission in app.py, which is what actually enforces it
   (User Plus only for records entered today; older ones are refused there).
   <body data-role="..."> is set by every page's template; this just keeps
   those controls out of a standard user's sight rather than showing buttons
   that would only be refused. */
body:not([data-role="admin"]):not([data-role="editor"]) .edit-only {
  display: none !important;
}

/* Suggest / Save buttons under the Billed Services job builder - they sit
   below the items table + subtotal but belong to the Job Date/Description
   form at the top of the section (form="job-save-form" on the buttons). */
.job-save-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}

.secondary-btn {
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--border);
  padding: 4px 10px;
  font-weight: 500;
  font-size: 0.85rem;
  margin-right: 6px;
}

.secondary-btn:hover {
  background: var(--accent);
  color: white;
}

.inline-rename-input {
  padding: 6px 8px;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font-size: 0.95rem;
  width: 100%;
}

.col-date {
  width: 130px;
  white-space: nowrap;
}

.col-amount {
  width: 120px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.col-tax-included {
  width: 110px;
  text-align: center;
}

.col-qty {
  width: 100px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.col-action {
  width: 140px;
  text-align: right;
  white-space: nowrap;
}

/* Expenses only: View/Replace/Remove (receipt) share this same cell with
   Edit/Delete (see ledger.js's actionCell) instead of a separate Receipt
   column, so it needs to be wide enough for all five buttons on one line. */
.col-action-wide {
  width: 420px;
}

.image-cell-actions {
  display: inline-flex;
  flex-wrap: nowrap;
  justify-content: flex-end;
  gap: 4px;
  margin-right: 6px;
}

.delete-btn {
  background: transparent;
  color: var(--danger);
  border: 1px solid var(--border);
  padding: 4px 10px;
  font-weight: 500;
  font-size: 0.85rem;
}

.inline-edit-input {
  padding: 6px 8px;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font-size: 0.9rem;
  width: 100%;
  min-width: 0;
}

.inline-edit-amount {
  text-align: right;
}

.delete-btn:hover {
  background: var(--danger);
  color: white;
}

tfoot td {
  border-bottom: none;
}

.total-label {
  text-align: right;
  font-weight: 600;
  color: var(--muted);
}

.total-amount {
  font-weight: 700;
  background: var(--total-bg);
  font-size: 1.05rem;
}

.empty-state {
  text-align: center;
  color: var(--muted);
  margin-top: 16px;
}

/* ---------------------------------------------------------------------- */
/* Archived services/materials (Materials & Services page) - hidden from  */
/* the active list and billing dropdowns by default, without deleting     */
/* the row (real Customer Status history may still reference it)          */
/* ---------------------------------------------------------------------- */

.show-archived-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 10px;
  color: var(--muted);
  font-size: 0.85rem;
  cursor: pointer;
}

.expense-sheet tbody tr.archived-row {
  opacity: 0.55;
  font-style: italic;
}

/* ---------------------------------------------------------------------- */
/* Resizable columns/rows (static/resizable.js) - applies to every         */
/* .expense-sheet table across the app                                    */
/* ---------------------------------------------------------------------- */

.table-scroll {
  overflow-x: auto;
  border-radius: 10px;
}

.expense-sheet th {
  position: relative;
}

.col-resize-handle {
  position: absolute;
  top: 0;
  right: -4px;
  width: 8px;
  height: 100%;
  cursor: col-resize;
  z-index: 3;
  touch-action: none;
}

.col-resize-handle:hover,
.col-resize-handle.resizing {
  background: var(--accent);
  opacity: 0.6;
}

.expense-sheet tbody tr.resizable-row {
  position: relative;
}

.row-resize-handle {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 8px;
  cursor: row-resize;
  z-index: 3;
  touch-action: none;
}

.row-resize-handle:hover,
.row-resize-handle.resizing {
  background: var(--accent);
  opacity: 0.6;
}

.expense-sheet tbody tr.row-height-set > td {
  overflow: hidden;
}

/* ---------------------------------------------------------------------- */
/* Sort toolbar (static/sortable.js) - applies to every .expense-sheet     */
/* table across the app                                                   */
/* ---------------------------------------------------------------------- */

.sort-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.sort-toolbar-label {
  font-size: 0.8rem;
  color: var(--muted);
  font-weight: 600;
}

.sort-select {
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--panel);
  color: var(--text);
  font-size: 0.85rem;
}

.sort-select:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.sort-direction-btn {
  padding: 6px 10px;
  font-size: 0.8rem;
  font-weight: 500;
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--border);
}

.sort-direction-btn:hover:not(:disabled) {
  background: var(--accent);
  color: white;
}

.sort-direction-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  background: transparent;
}

.section-hint {
  color: var(--muted);
  font-size: 0.9rem;
  margin: -6px 0 16px;
}

/* ---------------------------------------------------------------------- */
/* Customer Status: per-line expand/collapse for "Build a Job" detail      */
/* ---------------------------------------------------------------------- */

.col-toggle {
  width: 32px;
  padding-left: 8px;
  padding-right: 0;
}

.detail-toggle-btn {
  background: transparent;
  color: var(--muted);
  border: none;
  padding: 2px 6px;
  font-size: 0.8rem;
  border-radius: 4px;
}

.detail-toggle-btn:hover {
  background: var(--header-bg);
  color: var(--text);
}

.job-detail-row td {
  background: var(--bg);
  padding: 10px 14px 14px 40px;
}

.job-items-subtable {
  border-collapse: collapse;
  /* No fixed width here on purpose - static/resizable.js switches this to
     table-layout: fixed with an explicit per-column width (via <colgroup>)
     the first time it runs, same as every .expense-sheet table. Until then
     it just auto-sizes to content, same as always. */
}

.job-items-subtable th,
.job-items-subtable td {
  padding: 6px 10px;
  text-align: left;
  font-size: 0.85rem;
  border-bottom: 1px solid var(--border);
}

.job-items-subtable th {
  position: relative; /* anchors static/resizable.js's .col-resize-handle */
  color: var(--muted);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-weight: 600;
}

.job-items-subtable tbody tr:last-child td {
  border-bottom: none;
}

.job-items-subtable tbody tr.resizable-row {
  position: relative; /* anchors static/resizable.js's .row-resize-handle */
}

/* ---------------------------------------------------------------------- */
/* Print report (Customer Status page)                                    */
/* ---------------------------------------------------------------------- */

.print-report {
  width: 100%;
  max-width: 900px;
  box-sizing: border-box;
  margin: 20px auto;
  padding: 24px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text);
}

.print-report h1 {
  font-size: 1.4rem;
  margin: 0 0 16px;
}

.print-company-header {
  margin-bottom: 16px;
}

.print-company-name {
  font-weight: 700;
  font-size: 1.05rem;
}

.print-company-line {
  font-size: 0.85rem;
  color: var(--muted);
}

.print-report h2 {
  font-size: 1.05rem;
  margin: 24px 0 10px;
  color: var(--muted);
}

.print-label {
  color: var(--muted);
  font-weight: 600;
}

.print-header-table {
  margin-bottom: 12px;
}

.print-header-table td {
  padding: 2px 10px 2px 0;
  font-size: 0.9rem;
}

/* Tidy table: real <table>, full page width, header row, right-aligned
   numeric columns. Same-date rows are merged into one Date cell via
   rowspan (set in JS) so the date is never repeated. */
.print-table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 10px;
  table-layout: fixed;
}

.print-table th,
.print-table td {
  border: 1px solid var(--border);
  padding: 6px 10px;
  text-align: left;
  font-size: 0.85rem;
  word-break: break-word;
  vertical-align: top;
}

.print-table th {
  background: var(--header-bg);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
}

.print-table .print-col-date {
  width: 12%;
  white-space: nowrap;
}

.print-table .print-col-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  width: 14%;
}

/* "Preview & Print with Job Details" (static/customers.js) nests a job's
   itemized breakdown right under its summary row - a colspan row holding
   this smaller inset table, same idea as the on-screen .job-items-subtable
   expand/collapse view, just always shown rather than click-to-expand. */
.print-table td.print-subitems-cell {
  padding: 0;
  background: #fff;
}

.print-subitems-table {
  width: calc(100% - 24px);
  margin: 4px 0 4px 24px;
  border-collapse: collapse;
}

.print-subitems-table th,
.print-subitems-table td {
  padding: 3px 8px;
  font-size: 0.72rem;
  text-align: left;
}

.print-subitems-table th {
  color: var(--muted);
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.print-subitems-table .print-col-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.print-summary-table {
  margin: 0 0 20px auto;
}

.print-summary-table td {
  padding: 2px 10px;
  font-size: 0.9rem;
  text-align: right;
}

.print-summary-table td:first-child {
  text-align: left;
}

/* ---------------------------------------------------------------------- */
/* Customer Status print report - light green theme, fixed regardless of */
/* the app's light/dark mode (same reasoning as the invoice/quote theme   */
/* below: this is a document you print/send, not a UI screen, so it      */
/* shouldn't shift with the viewer's preference). Only .customer-status-  */
/* print - the Tax Report page reuses the same .print-report/.print-table */
/* classes and must NOT pick this up, hence scoping every rule under the  */
/* extra class rather than restyling .print-report/.print-table directly. */
/* ---------------------------------------------------------------------- */

.print-report.customer-status-print {
  --cs-dark: #2e7d32;
  --cs-border-dark: #1b5e20;
  --cs-light: #e8f5e9;
  --cs-border-light: #a5d6a7;
  background: var(--cs-light);
  border-color: var(--cs-border-light);
  color: #1a1a1a;
}

.customer-status-print h1,
.customer-status-print h2 {
  color: var(--cs-dark);
}

.customer-status-print .print-table {
  background: #ffffff;
}

/* !important to beat the @media print block's own !important black-text/
   gray-border reset further down (it targets .print-label/.print-table
   th/td by design, for the plain Tax Report case) - matching specificity
   convention already used there, scoped so it only wins here. */
.customer-status-print .print-label {
  color: var(--cs-dark) !important;
}

.customer-status-print .print-table th {
  background: var(--cs-dark) !important;
  color: #ffffff !important;
  border-color: var(--cs-border-dark) !important;
}

.customer-status-print .print-table td {
  background: #ffffff !important;
  border-color: var(--cs-border-light) !important;
  color: #1a1a1a !important;
}

/* ---------------------------------------------------------------------- */
/* Invoice / Quote print layout - pixel-matched to the company's real     */
/* letterhead PDF (temp2/202606-03.pdf), not the app's light/dark theme.  */
/* Always renders with these fixed colors, on screen and in print, since  */
/* this is the actual document that gets sent to a client.                */
/* ---------------------------------------------------------------------- */

.print-report.invoice-print {
  background: #ffffff;
  color: #1a1a1a;
  padding: 0;
  overflow: hidden;
}

.invoice-topband {
  display: flex;
  align-items: center;
  gap: 18px;
  background: #d9eef5;
  padding: 20px 26px;
}

.invoice-logo-img {
  width: 84px;
  height: auto;
  flex-shrink: 0;
}

.invoice-brand {
  flex: 1 1 auto;
}

.invoice-brand-name1,
.invoice-brand-name2 {
  font-family: Georgia, "Times New Roman", serif;
  font-weight: 700;
  color: #1a1a1a;
  line-height: 1.25;
}

.invoice-brand-name1 {
  font-size: 1.6rem;
}

.invoice-brand-name2 {
  font-size: 1.1rem;
}

.invoice-company-info {
  text-align: right;
  font-size: 0.82rem;
  color: #1a1a1a;
  line-height: 1.55;
  white-space: nowrap;
}

.invoice-hst-number {
  color: #2b6774;
  font-weight: 600;
}

.invoice-title-bar {
  background: #2b6774;
  padding: 14px 0;
  text-align: center;
}

.invoice-title-bar h1 {
  margin: 0;
  font-family: Georgia, "Times New Roman", serif;
  color: #ffffff;
  font-size: 1.9rem;
  letter-spacing: 0.06em;
}

.invoice-body {
  padding: 20px 26px 26px;
}

.invoice-meta-table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 18px;
  font-size: 0.9rem;
}

.invoice-meta-table td {
  padding: 3px 10px 3px 0;
  vertical-align: top;
}

.invoice-meta-table td.print-label {
  color: #1a1a1a;
  font-weight: 700;
  white-space: nowrap;
  width: 1%;
}

.invoice-items-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
  margin-bottom: 4px;
}

.invoice-items-table th {
  background: #2b6774;
  color: #ffffff;
  font-weight: 700;
  padding: 8px 10px;
  text-align: left;
  border: 1px solid #1f4e58;
}

.invoice-items-table th.invoice-col-item {
  width: 6%;
  text-align: center;
}

.invoice-items-table th.invoice-col-num {
  text-align: right;
  width: 13%;
}

.invoice-items-table td {
  padding: 8px 10px;
  border: 1px solid #cfe4ea;
  vertical-align: top;
}

.invoice-items-table td.invoice-col-item {
  text-align: center;
  color: #6b98a0;
}

.invoice-items-table td.invoice-col-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.invoice-items-table tbody tr:nth-child(odd) {
  background: #d9eef5;
}

.invoice-items-table tbody tr:nth-child(even) {
  background: #ffffff;
}

.invoice-currency {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-variant-numeric: tabular-nums;
}

.invoice-totals-wrap {
  display: flex;
  justify-content: flex-end;
  margin: 14px 0 26px;
}

.invoice-totals-table {
  border-collapse: collapse;
  border: 1.5px solid #1a1a1a;
  min-width: 270px;
}

.invoice-totals-table td {
  padding: 8px 16px;
  font-size: 0.9rem;
  border: 1px solid #1a1a1a;
  color: #1a1a1a;
}

.invoice-totals-label {
  background: #ffffff;
  font-weight: 600;
}

.invoice-totals-label.invoice-subtotal-bg {
  background: #d9eef5;
}

.invoice-totals-value {
  text-align: right;
  min-width: 110px;
}

.invoice-total-row {
  font-weight: 700;
}

.invoice-footer {
  text-align: center;
  color: #1a1a1a;
  font-size: 0.85rem;
  margin: 4px 0 12px;
}

/* ---------------------------------------------------------------------- */
/* Quote print layout - same structure/markup as Invoice above (this      */
/* element always carries both .invoice-print and .quote-print classes -  */
/* see documents.html), just re-colored light orange instead of teal/blue */
/* so the two documents are visually distinguishable at a glance. Invoice */
/* itself never gets .quote-print, so none of this reaches it.            */
/* ---------------------------------------------------------------------- */

.quote-print {
  --quote-dark: #b5570f;
  --quote-border-dark: #7a3a09;
  --quote-light: #fbe8d2;
  --quote-border-light: #f0cfa0;
  --quote-muted: #b98a5e;
}

.quote-print .invoice-topband {
  background: var(--quote-light);
}

.quote-print .invoice-hst-number {
  color: var(--quote-dark);
}

.quote-print .invoice-title-bar {
  background: var(--quote-dark);
}

.quote-print .invoice-items-table th {
  background: var(--quote-dark);
  border-color: var(--quote-border-dark);
}

.quote-print .invoice-items-table td {
  border-color: var(--quote-border-light);
}

.quote-print .invoice-items-table td.invoice-col-item {
  color: var(--quote-muted);
}

.quote-print .invoice-items-table tbody tr:nth-child(odd) {
  background: var(--quote-light);
}

.quote-print .invoice-totals-label.invoice-subtotal-bg {
  background: var(--quote-light);
}

@page {
  margin: 12mm;
}

@media print {
  html,
  body {
    width: 100%;
    margin: 0;
    padding: 0;
    background: #fff;
    /* Chrome/Edge/Firefox all drop background-color and background-image
       by default when printing or "Save as PDF" - without this, the
       invoice's teal bars, light-blue bands, and zebra-striped rows would
       silently print as plain white even though they look right in the
       on-screen Preview (which isn't subject to this browser default). */
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .no-print {
    display: none !important;
  }

  /* A printed page is narrower than 900px, so the mobile rules match while
     printing - without this the injected hamburger button prints on top of
     the invoice. */
  .nav-toggle,
  .nav-backdrop {
    display: none !important;
  }

  body::after {
    display: none !important;
  }

  .print-report {
    display: block !important;
    width: 100% !important;
    max-width: none !important;
    margin: 0 !important;
    padding: 0 !important;
    border: none !important;
    box-shadow: none !important;
    color: #000;
    background: #fff;
  }

  .print-report.invoice-print,
  .print-report.invoice-print *,
  .print-report.customer-status-print,
  .print-report.customer-status-print * {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }

  .print-label,
  .print-table th,
  .print-table td,
  .print-subitems-table th,
  .print-subitems-table td {
    color: #000 !important;
    border-color: #999 !important;
  }

  .print-table th {
    background: #eee !important;
  }

  .print-subitems-table {
    background: #fff !important;
  }
}

/* ---------------------------------------------------------------------- */
/* Help page                                                               */
/* ---------------------------------------------------------------------- */

.help-layout {
  display: flex;
  align-items: flex-start;
  gap: 24px;
}

.help-topics {
  flex: 0 0 220px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  position: sticky;
  top: 32px;
}

.help-topic-btn {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  color: var(--muted);
  border: none;
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
}

.help-topic-btn:hover {
  background: var(--header-bg);
  color: var(--text);
}

.help-topic-btn.active {
  background: var(--accent);
  color: #fff;
}

.help-topic-group-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  padding: 14px 12px 4px;
}

.help-topic-group-label:first-child {
  padding-top: 4px;
}

.help-content {
  flex: 1 1 auto;
  min-width: 0;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 24px 28px;
}

.help-topic-panel h2 {
  margin: 0 0 4px;
  font-size: 1.3rem;
}

.help-topic-tagline {
  color: var(--muted);
  margin: 0 0 18px;
}

.help-topic-panel p {
  line-height: 1.6;
  margin: 0 0 16px;
}

.help-diagram {
  width: 100%;
  max-width: 560px;
  height: auto;
  margin: 8px 0 18px;
  display: block;
}

.help-diagram text {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

@media (max-width: 900px) {
  .help-layout {
    flex-direction: column;
  }
  .help-topics {
    flex: 0 0 auto;
    flex-direction: row;
    flex-wrap: wrap;
    position: static;
  }
}

/* ---- Attendance page ---- */
.attendance-filter {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 4px 0 12px;
  font-size: 0.9rem;
  color: var(--muted);
}

.attendance-filter select {
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
}

.attendance-flag {
  color: var(--warning);
  font-weight: 600;
}

.attendance-onsite {
  color: var(--success);
}

.attendance-muted {
  color: var(--muted);
}

.attendance-strong {
  font-weight: 700;
}

.attendance-map-link {
  font-weight: 400;
  font-size: 0.85em;
}

.attendance-total-row td {
  background: var(--total-bg);
  font-weight: 700;
}

.attendance-lan {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 16px;
  margin-bottom: 12px;
}

.attendance-lan[hidden] {
  display: none;
}

.attendance-lan-status {
  margin-top: 6px;
  font-size: 0.88rem;
}

.attendance-settings-group {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 16px 16px;
  margin: 0 0 14px;
}

.attendance-settings-group legend {
  font-weight: 700;
  padding: 0 6px;
}

.attendance-settings-wide {
  grid-column: 1 / -1;
}

.attendance-brackets {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.attendance-bracket-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.9rem;
  color: var(--muted);
}

.attendance-bracket-row span:first-child {
  width: 80px;
}

.attendance-bracket-row input {
  width: 130px;
  padding: 7px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
}

.attendance-bracket-row input[hidden] {
  display: none;
}

.attendance-settings-actions {
  display: flex;
  gap: 8px;
  margin-bottom: 40px;
}

.attendance-saved {
  color: var(--success);
  font-weight: 600;
}

#lan-address-field[hidden] {
  display: none;
}

.attendance-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 20px;
  flex-wrap: wrap;
}

.attendance-tab {
  background: transparent;
  color: var(--muted);
  border-radius: 8px 8px 0 0;
  border-bottom: 3px solid transparent;
  padding: 10px 18px;
}

.attendance-tab:hover {
  background: var(--header-bg);
  color: var(--text);
}

.attendance-tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.attendance-loaded {
  color: var(--accent);
  font-weight: 600;
}

/* ---- Owner portal (/owner) - no sidebar, so its own page container ---- */
.owner-page {
  max-width: 1300px;
  margin: 0 auto;
  padding: 32px 24px 64px;
}

.owner-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  /* clear the fixed NUMIO badge in the top-right corner */
  padding-right: 110px;
}

.attendance-filter input[type="search"] {
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  min-width: 0;
  flex: 1 1 200px;
  max-width: 320px;
}

.owner-role-select {
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
}

@media (max-width: 900px) {
  .owner-page {
    padding: 20px 16px 48px;
  }
}

.owner-header button {
  white-space: nowrap;
  flex-shrink: 0;
}

.auth-hint {
  font-size: 0.78rem;
  color: var(--muted);
}

.auth-success {
  color: var(--success);
  font-weight: 600;
}

#forgot-form[hidden],
#reset-form[hidden] {
  display: none;
}

.owner-email-box {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  margin-bottom: 12px;
}

.owner-email-settings {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 4px 16px;
  margin: 0 0 12px;
  font-size: 0.9rem;
}

.owner-email-settings dt {
  color: var(--muted);
}

.owner-email-settings dd {
  margin: 0;
  word-break: break-all;
}

.owner-email-result {
  border-radius: 8px;
  padding: 12px 14px;
}

.owner-email-result p {
  margin: 6px 0 0;
}

.owner-email-ok {
  background: var(--total-bg);
  color: var(--success);
}

.owner-email-fail {
  background: var(--warning-bg);
  color: var(--text);
  border: 1px solid var(--danger);
}

.owner-link-btn {
  display: inline-block;
  text-decoration: none;
  margin-right: 6px;
}

/* Users page inline password reset: wraps instead of overflowing the
   (nowrap) actions cell, so Save/Cancel always stay reachable. */
.password-reset-editor {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-end;
  white-space: normal;
  min-width: 220px;
}

.password-reset-editor .inline-edit-input {
  flex: 1 1 160px;
  width: auto;
}

.users-success {
  color: var(--success);
  font-weight: 600;
}

.owner-row-error {
  flex-basis: 100%;
  color: var(--danger);
  font-size: 0.85rem;
  text-align: right;
}

.owner-row-error[hidden] {
  display: none;
}

/* ---- Import & Export page ---- */
.data-box {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  margin-bottom: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.data-sheet-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 8px 16px;
}

.data-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.data-link-btn {
  display: inline-block;
  text-decoration: none;
}

.data-import-sheets {
  margin: 0;
  padding-left: 18px;
  font-size: 0.9rem;
  color: var(--muted);
  line-height: 1.6;
}

.data-import-sheets strong {
  color: var(--text);
}

.data-detail h3 {
  font-size: 1rem;
  margin: 16px 0 6px;
}

.data-detail ul {
  margin: 0;
  padding-left: 18px;
  font-size: 0.9rem;
}

/* Manage IDs: Done column + finished IDs shown muted */
.col-done {
  width: 70px;
  text-align: center;
}

.col-done input {
  width: 18px;
  height: 18px;
  cursor: pointer;
}

.id-done-row .name-cell {
  color: var(--muted);
  text-decoration: line-through;
}

/* Customer Status: per-line "Tax" checkbox */
.col-line-tax {
  width: 56px;
  text-align: center;
}

.col-line-tax input {
  width: 18px;
  height: 18px;
  cursor: pointer;
}

/* ---- Settings > Quote and Invoice Template ---- */
.tpl-toolbar { display: flex; align-items: center; gap: 10px; margin: 6px 0 12px; color: var(--muted); font-size: 0.9rem; }
.tpl-switch { display: inline-flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.tpl-switch button { border: 0; border-radius: 0; background: var(--panel); color: var(--text); padding: 7px 16px; font-weight: 600; }
.tpl-switch button.active { background: var(--accent); color: #fff; }
.tpl-group-title { font-size: 1rem; margin: 22px 0 10px; }
.tpl-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 16px; }
.tpl-card { background: var(--panel); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; display: flex; flex-direction: column; }
.tpl-card-active { border: 2px solid var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent); }
.tpl-thumb { position: relative; height: 320px; overflow: hidden; background: #e6e8ec; border-bottom: 1px solid var(--border); }
.tpl-thumb iframe { position: absolute; top: 0; left: 0; width: 816px; height: 1056px; border: 0; transform: scale(0.305); transform-origin: top left; pointer-events: none; }
.tpl-info { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.tpl-name { font-weight: 700; }
.tpl-blurb { color: var(--muted); font-size: 0.85rem; flex: 1; }
.tpl-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.tpl-actions a { text-decoration: none; display: inline-block; }
.tpl-actions button { flex: 1 1 100%; }
.tpl-in-use { background: var(--success) !important; color: #fff !important; opacity: 1 !important; }
.tpl-toolbar { flex-wrap: wrap; }
.tpl-toolbar-gap { width: 14px; }
.tpl-current { margin: 0 0 10px; font-weight: 600; color: var(--success); }
.tpl-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.tpl-tag { font-size: 0.72rem; font-weight: 600; padding: 1px 8px; border-radius: 99px; background: var(--header-bg); color: var(--muted); border: 1px solid var(--border); }

/* Materials & Services: the category tabs inside each top tab - smaller pills */
.mat-subtabs { border-bottom: 0; flex-direction: column; align-items: flex-start; gap: 10px; margin: -8px 0 18px; }
.mat-tabrow { display: flex; flex-wrap: wrap; gap: 6px; }
.mat-tabrow-cats { padding-left: 18px; border-left: 2px solid var(--border); }
.mat-tabrow-cats:empty { display: none; }
.mat-tabrow-manage { align-self: stretch; justify-content: center; }
.mat-subtabs .mat-tabrow-manage .attendance-tab { font-size: 0.935rem; padding: 5.5px 15.4px; } /* 10% larger than the category pills */
.mat-subtabs .attendance-tab { border: 1px solid var(--border); border-radius: 999px; padding: 5px 14px; font-size: 0.85rem; }
.mat-subtabs .attendance-tab.active { background: var(--accent); color: #fff; border-color: var(--accent); }

/* A field hidden with the `hidden` attribute must stay hidden (.field's own
   display:flex used to override it - e.g. Customer Status's custom-item
   fields showed even with a catalog item picked), and a form row whose
   fields are all hidden disappears instead of leaving an empty box. */
.field[hidden] { display: none; }
.expense-form:not(:has(> :not([hidden]))) { display: none; }
